diff --git a/.gitignore b/.gitignore index c166681da..00a6e84e9 100644 --- a/.gitignore +++ b/.gitignore @@ -80,7 +80,7 @@ contiki-cc2530dk.lib *.dsc #cc65 build artifacts -*.S +*.s *.eth *.dsk *.po @@ -125,3 +125,7 @@ platform/galileo/bsp/grub/bin/ *.galileo.dll *.galileo.efi LOG_OPENOCD + +# nRF52 build artifacts +*.jlink +*.nrf52dk diff --git a/.gitmodules b/.gitmodules index 1fc8b720e..eecb69722 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,9 +4,6 @@ [submodule "tools/cc2538-bsl"] path = tools/cc2538-bsl url = https://github.com/JelmerT/cc2538-bsl.git -[submodule "platform/osd-merkur/dev/LED_Strip_Suli"] - path = platform/osd-merkur/dev/LED_Strip_Suli - url = https://github.com/osdomotics/LED_Strip_Suli.git [submodule "cpu/cc26xx-cc13xx/lib/cc26xxware"] path = cpu/cc26xx-cc13xx/lib/cc26xxware url = https://github.com/g-oikonomou/cc26xxware.git diff --git a/.travis.yml b/.travis.yml index 3a035fd2e..1a76347bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,11 @@ before_script: msp430-gcc --version ## Install avr toolchain - - sudo apt-get -qq install gcc-avr avr-libc + - $WGET http://atiselsts.github.io/resources/avr-gcc-4.9.2-compiled.tar.bz2 && + tar xjf avr-gcc*.tar.bz2 -C /tmp/ && + sudo cp -f -r /tmp/avr-gcc/* /usr/local/ && + rm -rf /tmp/avr-gcc avr-gcc*.tar.bz2 && + avr-gcc --version ## Install 32-bit compatibility libraries - sudo apt-get -qq install libc6:i386 libgcc1:i386 gcc-4.6-base:i386 @@ -40,13 +44,13 @@ before_script: arm-none-eabi-gcc --version ; fi - ## Install mainline ARM toolchain. gcc-arm-none-eabi is available - ## in Ubuntu >= 14.04, but this external PPA is needed for 12.04. - ## Install srecord + ## Install mainline ARM toolchain and srecord. - if [ ${BUILD_ARCH:-0} = arm-aapcs ] ; then - sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa && - sudo apt-get -qq update && - sudo apt-get -qq install gcc-arm-embedded=5-2015q4-1~precise1 srecord && + sudo apt-get -qq install srecord && + $WGET https://launchpad.net/gcc-arm-embedded/5.0/5-2015-q4-major/+download/gcc-arm-none-eabi-5_2-2015q4-20151219-linux.tar.bz2 && + tar xjf gcc-arm-none-eabi-5_2-2015q4-20151219-linux.tar.bz2 -C /tmp/ && + sudo cp -f -r /tmp/gcc-arm-none-eabi-5_2-2015q4/* /usr/local/ && + rm -rf /tmp/gcc-arm-none-eabi-* gcc-arm-none-eabi-*-linux.tar.bz2 && arm-none-eabi-gcc --version ; fi @@ -70,7 +74,6 @@ before_script: git clone https://github.com/cc65/cc65 /tmp/cc65 && make -C /tmp/cc65 bin apple2enh atarixl c64 c128 && sudo make -C /tmp/cc65 avail && - export CC65_HOME=/tmp/cc65/ && cc65 --version ; fi @@ -89,6 +92,18 @@ before_script: rm -rf /tmp/ba-elf-gcc* /tmp/jn516x-sdk* && ba-elf-gcc --version ; fi + + ## Install mainline ARM toolchain and download nRF52 SDK + - if [ ${BUILD_ARCH:-0} = nrf52dk ] ; then + sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa && + sudo apt-get -qq update && + sudo apt-get -qq install gcc-arm-embedded srecord && + arm-none-eabi-gcc --version && + $WGET https://developer.nordicsemi.com/nRF5_IoT_SDK/nRF5_IoT_SDK_v0.9.x/nrf5_iot_sdk_3288530.zip && + mkdir /tmp/nrf52-sdk && + unzip nrf5_iot_sdk_3288530.zip -d /tmp/nrf52-sdk && + export NRF52_SDK_ROOT=/tmp/nrf52-sdk ; + fi ## Compile cooja.jar only when it's going to be needed - if [ ${BUILD_CATEGORY:-sim} = sim ] ; then @@ -120,6 +135,7 @@ env: - BUILD_TYPE='collect' - BUILD_TYPE='collect-lossy' - BUILD_TYPE='rpl' + - BUILD_TYPE='rpl-non-storing' - BUILD_TYPE='large-rpl' - BUILD_TYPE='rime' - BUILD_TYPE='ipv6' @@ -138,5 +154,7 @@ env: - BUILD_TYPE='compile-6502-ports' BUILD_CATEGORY='compile' BUILD_ARCH='6502' - BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm-aapcs' - BUILD_TYPE='compile-nxp-ports' BUILD_CATEGORY='compile' BUILD_ARCH='jn516x' + - BUILD_TYPE='compile-nrf52-ports' BUILD_CATEGORY='compile' BUILD_ARCH='nrf52dk' - BUILD_TYPE='slip-radio' MAKE_TARGETS='cooja' - BUILD_TYPE='llsec' MAKE_TARGETS='cooja' + - BUILD_TYPE='compile-avr' BUILD_CATEGORY='compile' BUILD_ARCH='avr-rss2' diff --git a/Makefile.include b/Makefile.include index 4545c9c4f..f55427cf9 100644 --- a/Makefile.include +++ b/Makefile.include @@ -184,7 +184,7 @@ CONTIKI_CPU_DIRS_CONCAT = ${addprefix $(CONTIKI_CPU)/, \ $(CONTIKI_CPU_DIRS)} SOURCEDIRS = . $(PROJECTDIRS) $(CONTIKI_TARGET_DIRS_CONCAT) \ - $(CONTIKI_CPU_DIRS_CONCAT) $(CONTIKIDIRS) $(APPDS) ${dir $(target_makefile)} + $(CONTIKI_CPU_DIRS_CONCAT) $(CONTIKIDIRS) $(APPDS) $(EXTERNALDIRS) ${dir $(target_makefile)} vpath %.c $(SOURCEDIRS) vpath %.cpp $(SOURCEDIRS) diff --git a/apps/arduino/arduino-process.c b/apps/arduino/arduino-process.c index ff26d6abd..d3041e602 100644 --- a/apps/arduino/arduino-process.c +++ b/apps/arduino/arduino-process.c @@ -54,6 +54,34 @@ #include "adc.h" #include "hw-arduino.h" +extern volatile uint8_t mcusleepcycle; +volatile uint8_t mcusleepcycleval; + +/*-------------- enabled sleep mode ----------------------------------------*/ +void +mcu_sleep_init(void) +{ + mcusleepcycleval=mcusleepcycle; +} +void +mcu_sleep_on(void) +{ + mcusleepcycle= mcusleepcycleval; +} +/*--------------- disable sleep mode ---------------------------------------*/ +void +mcu_sleep_off(void) +{ + mcusleepcycle=0; +} +/*---------------- set duty cycle value ------------------------------------*/ +void +mcu_sleep_set(uint8_t value) +{ + mcusleepcycleval= value; + mcusleepcycle = mcusleepcycleval; +} + PROCESS(arduino_sketch, "Arduino Sketch Wrapper"); #ifndef LOOP_INTERVAL @@ -65,8 +93,8 @@ PROCESS_THREAD(arduino_sketch, ev, data) static struct etimer loop_periodic_timer; PROCESS_BEGIN(); - adc_init (); + mcu_sleep_init (); setup (); /* Define application-specific events here. */ etimer_set(&loop_periodic_timer, LOOP_INTERVAL); diff --git a/apps/arduino/arduino-process.h b/apps/arduino/arduino-process.h index 23b00ede4..bea6708f8 100644 --- a/apps/arduino/arduino-process.h +++ b/apps/arduino/arduino-process.h @@ -51,6 +51,13 @@ #include "contiki.h" +/*--------------- enable sleep mode ---------------------------------------*/ +void mcu_sleep_on(void); +/*--------------- disable sleep mode ---------------------------------------*/ +void mcu_sleep_off(void); +/*---------------- set sleep value ------------------------------------*/ +void mcu_sleep_set(uint8_t value); + extern void loop (void); extern void setup (void); extern void arduino_init (void); diff --git a/apps/at-master/Makefile.at-master b/apps/at-master/Makefile.at-master new file mode 100644 index 000000000..9ab561a16 --- /dev/null +++ b/apps/at-master/Makefile.at-master @@ -0,0 +1 @@ +at-master_src = at-master.c diff --git a/apps/at-master/at-master.c b/apps/at-master/at-master.c new file mode 100644 index 000000000..c9e0597b6 --- /dev/null +++ b/apps/at-master/at-master.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.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 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. + * + */ +#include "contiki.h" +#include "contiki-lib.h" +#include "at-master.h" +#include "cpu.h" +#include "dev/uart.h" +#include "dev/serial-line.h" +#include "dev/sys-ctrl.h" +#include "lib/list.h" +#include "sys/cc.h" + +#include +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +LIST(at_cmd_list); +process_event_t at_cmd_received_event; +/*---------------------------------------------------------------------------*/ +static uint8_t at_uart = 0; +/*---------------------------------------------------------------------------*/ +PROCESS(at_process, "AT process"); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(at_process, ev, data) +{ + uint8_t plen; + char *pch, *buf; + struct at_cmd *a; + PROCESS_BEGIN(); + + while(1) { + PROCESS_WAIT_EVENT_UNTIL(ev == serial_line_event_message && data != NULL); + buf = (char *)data; + plen = strlen(buf); + for(a = list_head(at_cmd_list); a != NULL; a = list_item_next(a)) { + pch = strstr(buf, a->cmd_header); + if((plen <= a->cmd_max_len) && (pch != NULL)) { + if(strncmp(a->cmd_header, pch, a->cmd_hdr_len) == 0) { + if((a->cmd_hdr_len == plen) || (a->cmd_max_len > a->cmd_hdr_len)) { + a->event_callback(a, plen, (char *)pch); + process_post(a->app_process, at_cmd_received_event, NULL); + break; + } + } + } + } + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +struct at_cmd * +at_list(void) +{ + return list_head(at_cmd_list); +} +/*---------------------------------------------------------------------------*/ +uint8_t +at_send(char *s, uint8_t len) +{ + uint8_t i = 0; + while(s && *s != 0) { + if(i >= len) { + break; + } + uart_write_byte(at_uart, *s++); + i++; + } + return i; +} +/*---------------------------------------------------------------------------*/ +void +at_init(uint8_t uart_sel) +{ + static uint8_t inited = 0; + if(!inited) { + list_init(at_cmd_list); + at_cmd_received_event = process_alloc_event(); + inited = 1; + + at_uart = uart_sel; + uart_init(at_uart); + uart_set_input(at_uart, serial_line_input_byte); + serial_line_init(); + + process_start(&at_process, NULL); + PRINTF("AT: Started (%u)\n", at_uart); + } +} +/*---------------------------------------------------------------------------*/ +at_status_t +at_register(struct at_cmd *cmd, struct process *app_process, + const char *cmd_hdr, const uint8_t hdr_len, + const uint8_t cmd_max_len, at_event_callback_t event_callback) +{ + if((hdr_len < 1) || (cmd_max_len < 1) || (!strncmp(cmd_hdr, "AT", 2) == 0) || + (event_callback == NULL)) { + PRINTF("AT: Invalid argument\n"); + return AT_STATUS_INVALID_ARGS_ERROR; + } + + memset(cmd, 0, sizeof(struct at_cmd)); + cmd->event_callback = event_callback; + cmd->cmd_header = cmd_hdr; + cmd->cmd_hdr_len = hdr_len; + cmd->cmd_max_len = cmd_max_len; + cmd->app_process = app_process; + list_add(at_cmd_list, cmd); + PRINTF("AT: registered HDR %s LEN %u MAX %u\n", cmd->cmd_header, + cmd->cmd_hdr_len, + cmd->cmd_max_len); + return AT_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ diff --git a/apps/at-master/at-master.h b/apps/at-master/at-master.h new file mode 100644 index 000000000..ad625c0dc --- /dev/null +++ b/apps/at-master/at-master.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.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 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. + * + */ +#ifndef AT_MASTER_H_ +#define AT_MASTER_H_ +#include "contiki.h" +/*---------------------------------------------------------------------------*/ +#define AT_DEFAULT_RESPONSE_OK "\r\nOK\r\n" +#define AT_DEFAULT_RESPONSE_ERROR "\r\nERROR\r\n" +/*---------------------------------------------------------------------------*/ +#define AT_RESPONSE(x) at_send((x), (strlen(x))) +/*---------------------------------------------------------------------------*/ +extern process_event_t at_cmd_received_event; +struct at_cmd; +/*---------------------------------------------------------------------------*/ +typedef enum { + AT_STATUS_OK, + AT_STATUS_ERROR, + AT_STATUS_INVALID_ARGS_ERROR, +} at_status_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief AT initialization + * \param uart selects which UART to use + * + * The AT driver invokes this function upon registering a command, this will + * wait for the serial_line_event_message event + */ +void at_init(uint8_t uart); +/*---------------------------------------------------------------------------*/ +/** + * \brief AT initialization + * \param uart selects which UART to use + * + * The AT driver invokes this function upon registering a command, this will + * wait for the serial_line_event_message event + */ +uint8_t at_send(char *s, uint8_t len); +/*---------------------------------------------------------------------------*/ +/** + * \brief AT event callback + * \param cmd A pointer to the AT command placeholder + * \param len Lenght of the received data (including the AT command header) + * \param data A user-defined pointer + * + * The AT event callback function gets called whenever there is an + * event on an incoming AT command + */ +typedef void (*at_event_callback_t)(struct at_cmd *cmd, + uint8_t len, + char *data); +/*---------------------------------------------------------------------------*/ +struct at_cmd { + struct at_cmd *next; + const char *cmd_header; + uint8_t cmd_hdr_len; + uint8_t cmd_max_len; + at_event_callback_t event_callback; + struct process *app_process; +}; +/*---------------------------------------------------------------------------*/ +/** + * \brief Registers the callback to return an AT command + * \param cmd A pointer to the CMD placeholder + * \param cmd_hdr String to compare when an AT command is received + * \param cmd_len Lenght of cmd_hdr + * \param event_callback Callback function to handle the AT command + * \return AT_STATUS_OK or AT_STATUS_INVALID_ARGS_ERROR + * + * Register the commands to search for when a valid AT frame has been received + */ +at_status_t at_register(struct at_cmd *cmd, + struct process *app_process, + const char *cmd_hdr, + const uint8_t cmd_hdr_len, + const uint8_t cmd_max_len, + at_event_callback_t event_callback); +/*---------------------------------------------------------------------------*/ +struct at_cmd *at_list(void); +/*---------------------------------------------------------------------------*/ +/** + * \brief Registers the callback to return an AT command + * \param cmd A pointer to the CMD placeholder + * \param cmd_hdr String to compare when an AT command is received + * \param cmd_len Lenght of cmd_hdr + * \param event_callback Callback function to handle the AT command + * \return AT_STATUS_OK or AT_STATUS_INVALID_ARGS_ERROR + * + * Register the commands to search for when a valid AT frame has been received + */ +at_status_t at_register(struct at_cmd *cmd, + struct process *app_process, + const char *cmd_hdr, + const uint8_t cmd_hdr_len, + const uint8_t cmd_max_len, + at_event_callback_t event_callback); +#endif /* AT_MASTER_H_ */ diff --git a/apps/deluge/Makefile.deluge b/apps/deluge/Makefile.deluge deleted file mode 100644 index abadf18d0..000000000 --- a/apps/deluge/Makefile.deluge +++ /dev/null @@ -1 +0,0 @@ -deluge_src = deluge.c diff --git a/apps/deluge/deluge.c b/apps/deluge/deluge.c deleted file mode 100644 index 9e3235b25..000000000 --- a/apps/deluge/deluge.c +++ /dev/null @@ -1,698 +0,0 @@ -/* - * Copyright (c) 2007, Swedish Institute of Computer Science - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ - -/** - * \file - * An implementation of the Deluge protocol. - * (Hui and Culler: The dynamic behavior of a data - * dissemination protocol for network programming at scale, - * ACM SenSys 2004) - * \author - * Nicolas Tsiftes - */ - -#include "contiki.h" -#include "net/rime/rime.h" -#include "cfs/cfs.h" -#include "loader/elfloader.h" -#include "lib/crc16.h" -#include "lib/random.h" -#include "sys/node-id.h" -#include "deluge.h" - -#if NETSIM -#include "ether.h" -#include -#endif - -#include "dev/leds.h" -#include -#include - -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif - -/* Implementation-specific variables. */ -static struct broadcast_conn deluge_broadcast; -static struct unicast_conn deluge_uc; -static struct deluge_object current_object; -static process_event_t deluge_event; - -/* Deluge variables. */ -static int deluge_state; -static int old_summary; -static int neighbor_inconsistency; -static unsigned r_interval; -static unsigned recv_adv; -static int broadcast_profile; - -/* Deluge timers. */ -static struct ctimer rx_timer; -static struct ctimer tx_timer; -static struct ctimer summary_timer; -static struct ctimer profile_timer; - -/* Deluge objects will get an ID that defaults to the current value of - the next_object_id parameter. */ -static deluge_object_id_t next_object_id; - -/* Rime callbacks. */ -static void broadcast_recv(struct broadcast_conn *, const linkaddr_t *); -static void unicast_recv(struct unicast_conn *, const linkaddr_t *); - -static const struct broadcast_callbacks broadcast_call = {broadcast_recv, NULL}; -static const struct unicast_callbacks unicast_call = {unicast_recv, NULL}; - -/* The Deluge process manages the main Deluge timer. */ -PROCESS(deluge_process, "Deluge"); - -static void -transition(int state) -{ - if(state != deluge_state) { - switch(deluge_state) { - case DELUGE_STATE_MAINTAIN: - ctimer_stop(&summary_timer); - ctimer_stop(&profile_timer); - break; - case DELUGE_STATE_RX: - ctimer_stop(&rx_timer); - break; - case DELUGE_STATE_TX: - ctimer_stop(&tx_timer); - break; - } - deluge_state = state; - } -} - -static int -write_page(struct deluge_object *obj, unsigned pagenum, unsigned char *data) -{ - cfs_offset_t offset; - - offset = pagenum * S_PAGE; - - if(cfs_seek(obj->cfs_fd, offset, CFS_SEEK_SET) != offset) { - return -1; - } - return cfs_write(obj->cfs_fd, (char *)data, S_PAGE); -} - -static int -read_page(struct deluge_object *obj, unsigned pagenum, unsigned char *buf) -{ - cfs_offset_t offset; - - offset = pagenum * S_PAGE; - - if(cfs_seek(obj->cfs_fd, offset, CFS_SEEK_SET) != offset) { - return -1; - } - return cfs_read(obj->cfs_fd, (char *)buf, S_PAGE); -} - -static void -init_page(struct deluge_object *obj, int pagenum, int have) -{ - struct deluge_page *page; - unsigned char buf[S_PAGE]; - - page = &obj->pages[pagenum]; - - page->flags = 0; - page->last_request = 0; - page->last_data = 0; - - if(have) { - page->version = obj->version; - page->packet_set = ALL_PACKETS; - page->flags |= PAGE_COMPLETE; - read_page(obj, pagenum, buf); - page->crc = crc16_data(buf, S_PAGE, 0); - } else { - page->version = 0; - page->packet_set = 0; - } -} - -static cfs_offset_t -file_size(const char *file) -{ - int fd; - cfs_offset_t size; - - fd = cfs_open(file, CFS_READ); - if(fd < 0) { - return (cfs_offset_t)-1; - } - - size = cfs_seek(fd, 0, CFS_SEEK_END); - cfs_close(fd); - - return size; -} - -static int -init_object(struct deluge_object *obj, char *filename, unsigned version) -{ - static struct deluge_page *page; - int i; - - obj->cfs_fd = cfs_open(filename, CFS_READ | CFS_WRITE); - if(obj->cfs_fd < 0) { - return -1; - } - - obj->filename = filename; - obj->object_id = next_object_id++; - obj->size = file_size(filename); - obj->version = obj->update_version = version; - obj->current_rx_page = 0; - obj->nrequests = 0; - obj->tx_set = 0; - - obj->pages = malloc(OBJECT_PAGE_COUNT(*obj) * sizeof(*obj->pages)); - if(obj->pages == NULL) { - cfs_close(obj->cfs_fd); - return -1; - } - - for(i = 0; i < OBJECT_PAGE_COUNT(current_object); i++) { - page = ¤t_object.pages[i]; - init_page(¤t_object, i, 1); - } - - memset(obj->current_page, 0, sizeof(obj->current_page)); - - return 0; -} - -static int -highest_available_page(struct deluge_object *obj) -{ - int i; - - for(i = 0; i < OBJECT_PAGE_COUNT(*obj); i++) { - if(!(obj->pages[i].flags & PAGE_COMPLETE)) { - break; - } - } - - return i; -} - -static void -send_request(void *arg) -{ - struct deluge_object *obj; - struct deluge_msg_request request; - - obj = (struct deluge_object *)arg; - - request.cmd = DELUGE_CMD_REQUEST; - request.pagenum = obj->current_rx_page; - request.version = obj->pages[request.pagenum].version; - request.request_set = ~obj->pages[obj->current_rx_page].packet_set; - request.object_id = obj->object_id; - - PRINTF("Sending request for page %d, version %u, request_set %u\n", - request.pagenum, request.version, request.request_set); - packetbuf_copyfrom(&request, sizeof(request)); - unicast_send(&deluge_uc, &obj->summary_from); - - /* Deluge R.2 */ - if(++obj->nrequests == CONST_LAMBDA) { - /* XXX check rate here too. */ - obj->nrequests = 0; - transition(DELUGE_STATE_MAINTAIN); - } else { - ctimer_reset(&rx_timer); - } -} - -static void -advertise_summary(struct deluge_object *obj) -{ - struct deluge_msg_summary summary; - - if(recv_adv >= CONST_K) { - ctimer_stop(&summary_timer); - return; - } - - summary.cmd = DELUGE_CMD_SUMMARY; - summary.version = obj->update_version; - summary.highest_available = highest_available_page(obj); - summary.object_id = obj->object_id; - - PRINTF("Advertising summary for object id %u: version=%u, available=%u\n", - (unsigned)obj->object_id, summary.version, summary.highest_available); - - packetbuf_copyfrom(&summary, sizeof(summary)); - broadcast_send(&deluge_broadcast); -} - -static void -handle_summary(struct deluge_msg_summary *msg, const linkaddr_t *sender) -{ - int highest_available, i; - clock_time_t oldest_request, oldest_data, now; - struct deluge_page *page; - - highest_available = highest_available_page(¤t_object); - - if(msg->version != current_object.version || - msg->highest_available != highest_available) { - neighbor_inconsistency = 1; - } else { - recv_adv++; - } - - if(msg->version < current_object.version) { - old_summary = 1; - broadcast_profile = 1; - } - - /* Deluge M.5 */ - if(msg->version == current_object.update_version && - msg->highest_available > highest_available) { - if(msg->highest_available > OBJECT_PAGE_COUNT(current_object)) { - PRINTF("Error: highest available is above object page count!\n"); - return; - } - - oldest_request = oldest_data = now = clock_time(); - for(i = 0; i < msg->highest_available; i++) { - page = ¤t_object.pages[i]; - if(page->last_request < oldest_request) { - oldest_request = page->last_request; - } - if(page->last_request < oldest_data) { - oldest_data = page->last_data; - } - } - - if(((now - oldest_request) / CLOCK_SECOND) <= 2 * r_interval || - ((now - oldest_data) / CLOCK_SECOND) <= r_interval) { - return; - } - - linkaddr_copy(¤t_object.summary_from, sender); - transition(DELUGE_STATE_RX); - - if(ctimer_expired(&rx_timer)) { - ctimer_set(&rx_timer, - CONST_OMEGA * ESTIMATED_TX_TIME + ((unsigned)random_rand() % T_R), - send_request, ¤t_object); - } - } -} - -static void -send_page(struct deluge_object *obj, unsigned pagenum) -{ - unsigned char buf[S_PAGE]; - struct deluge_msg_packet pkt; - unsigned char *cp; - - pkt.cmd = DELUGE_CMD_PACKET; - pkt.pagenum = pagenum; - pkt.version = obj->pages[pagenum].version; - pkt.packetnum = 0; - pkt.object_id = obj->object_id; - pkt.crc = 0; - - read_page(obj, pagenum, buf); - - /* Divide the page into packets and send them one at a time. */ - for(cp = buf; cp + S_PKT <= (unsigned char *)&buf[S_PAGE]; cp += S_PKT) { - if(obj->tx_set & (1 << pkt.packetnum)) { - pkt.crc = crc16_data(cp, S_PKT, 0); - memcpy(pkt.payload, cp, S_PKT); - packetbuf_copyfrom(&pkt, sizeof(pkt)); - broadcast_send(&deluge_broadcast); - } - pkt.packetnum++; - } - obj->tx_set = 0; -} - -static void -tx_callback(void *arg) -{ - struct deluge_object *obj; - - obj = (struct deluge_object *)arg; - if(obj->current_tx_page >= 0 && obj->tx_set) { - send_page(obj, obj->current_tx_page); - /* Deluge T.2. */ - if(obj->tx_set) { - packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, - PACKETBUF_ATTR_PACKET_TYPE_STREAM); - ctimer_reset(&tx_timer); - } else { - packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, - PACKETBUF_ATTR_PACKET_TYPE_STREAM_END); - obj->current_tx_page = -1; - transition(DELUGE_STATE_MAINTAIN); - } - } -} - -static void -handle_request(struct deluge_msg_request *msg) -{ - int highest_available; - - if(msg->pagenum >= OBJECT_PAGE_COUNT(current_object)) { - return; - } - - if(msg->version != current_object.version) { - neighbor_inconsistency = 1; - } - - highest_available = highest_available_page(¤t_object); - - /* Deluge M.6 */ - if(msg->version == current_object.version && - msg->pagenum <= highest_available) { - current_object.pages[msg->pagenum].last_request = clock_time(); - - /* Deluge T.1 */ - if(msg->pagenum == current_object.current_tx_page) { - current_object.tx_set |= msg->request_set; - } else { - current_object.current_tx_page = msg->pagenum; - current_object.tx_set = msg->request_set; - } - - transition(DELUGE_STATE_TX); - ctimer_set(&tx_timer, CLOCK_SECOND, tx_callback, ¤t_object); - } -} - -static void -handle_packet(struct deluge_msg_packet *msg) -{ - struct deluge_page *page; - uint16_t crc; - struct deluge_msg_packet packet; - - memcpy(&packet, msg, sizeof(packet)); - - PRINTF("Incoming packet for object id %u, version %u, page %u, packet num %u!\n", - (unsigned)packet.object_id, (unsigned)packet.version, - (unsigned)packet.pagenum, (unsigned)packet.packetnum); - - if(packet.pagenum != current_object.current_rx_page) { - return; - } - - if(packet.version != current_object.version) { - neighbor_inconsistency = 1; - } - - page = ¤t_object.pages[packet.pagenum]; - if(packet.version == page->version && !(page->flags & PAGE_COMPLETE)) { - memcpy(¤t_object.current_page[S_PKT * packet.packetnum], - packet.payload, S_PKT); - - crc = crc16_data(packet.payload, S_PKT, 0); - if(packet.crc != crc) { - PRINTF("packet crc: %hu, calculated crc: %hu\n", packet.crc, crc); - return; - } - - page->last_data = clock_time(); - page->packet_set |= (1 << packet.packetnum); - - if(page->packet_set == ALL_PACKETS) { - /* This is the last packet of the requested page; stop streaming. */ - packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, - PACKETBUF_ATTR_PACKET_TYPE_STREAM_END); - - write_page(¤t_object, packet.pagenum, current_object.current_page); - page->version = packet.version; - page->flags = PAGE_COMPLETE; - PRINTF("Page %u completed\n", packet.pagenum); - - current_object.current_rx_page++; - - if(packet.pagenum == OBJECT_PAGE_COUNT(current_object) - 1) { - current_object.version = current_object.update_version; - leds_on(LEDS_RED); - PRINTF("Update completed for object %u, version %u\n", - (unsigned)current_object.object_id, packet.version); - } else if(current_object.current_rx_page < OBJECT_PAGE_COUNT(current_object)) { - if(ctimer_expired(&rx_timer)) { - ctimer_set(&rx_timer, - CONST_OMEGA * ESTIMATED_TX_TIME + (random_rand() % T_R), - send_request, ¤t_object); - } - } - /* Deluge R.3 */ - transition(DELUGE_STATE_MAINTAIN); - } else { - /* More packets to come. Put lower layers in streaming mode. */ - packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, - PACKETBUF_ATTR_PACKET_TYPE_STREAM); - } - } -} - -static void -send_profile(struct deluge_object *obj) -{ - struct deluge_msg_profile *msg; - unsigned char buf[sizeof(*msg) + OBJECT_PAGE_COUNT(*obj)]; - int i; - - if(broadcast_profile && recv_adv < CONST_K) { - broadcast_profile = 0; - - msg = (struct deluge_msg_profile *)buf; - msg->cmd = DELUGE_CMD_PROFILE; - msg->version = obj->version; - msg->npages = OBJECT_PAGE_COUNT(*obj); - msg->object_id = obj->object_id; - for(i = 0; i < msg->npages; i++) { - msg->version_vector[i] = obj->pages[i].version; - } - - packetbuf_copyfrom(buf, sizeof(buf)); - broadcast_send(&deluge_broadcast); - } -} - -static void -handle_profile(struct deluge_msg_profile *msg) -{ - int i; - int npages; - struct deluge_object *obj; - char *p; - - obj = ¤t_object; - if(msg->version <= current_object.update_version) { - return; - } - - PRINTF("Received profile of version %u with a vector of %u pages.\n", - msg->version, msg->npages); - - leds_off(LEDS_RED); - current_object.tx_set = 0; - - npages = OBJECT_PAGE_COUNT(*obj); - obj->size = msg->npages * S_PAGE; - - p = malloc(OBJECT_PAGE_COUNT(*obj) * sizeof(*obj->pages)); - if(p == NULL) { - PRINTF("Failed to reallocate memory for pages!\n"); - return; - } - - memcpy(p, obj->pages, npages * sizeof(*obj->pages)); - free(obj->pages); - obj->pages = (struct deluge_page *)p; - - if(msg->npages < npages) { - npages = msg->npages; - } - - for(i = 0; i < npages; i++) { - if(msg->version_vector[i] > obj->pages[i].version) { - obj->pages[i].packet_set = 0; - obj->pages[i].flags &= ~PAGE_COMPLETE; - obj->pages[i].version = msg->version_vector[i]; - } - } - - for(; i < msg->npages; i++) { - init_page(obj, i, 0); - } - - obj->current_rx_page = highest_available_page(obj); - obj->update_version = msg->version; - - transition(DELUGE_STATE_RX); - - ctimer_set(&rx_timer, - CONST_OMEGA * ESTIMATED_TX_TIME + ((unsigned)random_rand() % T_R), - send_request, obj); -} - -static void -command_dispatcher(const linkaddr_t *sender) -{ - char *msg; - int len; - struct deluge_msg_profile *profile; - - msg = packetbuf_dataptr(); - len = packetbuf_datalen(); - if(len < 1) - return; - - switch(msg[0]) { - case DELUGE_CMD_SUMMARY: - if(len >= sizeof(struct deluge_msg_summary)) - handle_summary((struct deluge_msg_summary *)msg, sender); - break; - case DELUGE_CMD_REQUEST: - if(len >= sizeof(struct deluge_msg_request)) - handle_request((struct deluge_msg_request *)msg); - break; - case DELUGE_CMD_PACKET: - if(len >= sizeof(struct deluge_msg_packet)) - handle_packet((struct deluge_msg_packet *)msg); - break; - case DELUGE_CMD_PROFILE: - profile = (struct deluge_msg_profile *)msg; - if(len >= sizeof(*profile) && - len >= sizeof(*profile) + profile->npages * profile->version_vector[0]) - handle_profile((struct deluge_msg_profile *)msg); - break; - default: - PRINTF("Incoming packet with unknown command: %d\n", msg[0]); - } -} - -static void -unicast_recv(struct unicast_conn *c, const linkaddr_t *sender) -{ - command_dispatcher(sender); -} - -static void -broadcast_recv(struct broadcast_conn *c, const linkaddr_t *sender) -{ - command_dispatcher(sender); -} - -int -deluge_disseminate(char *file, unsigned version) -{ - /* This implementation disseminates at most one object. */ - if(next_object_id > 0 || init_object(¤t_object, file, version) < 0) { - return -1; - } - process_start(&deluge_process, (void *)file); - - return 0; -} - -PROCESS_THREAD(deluge_process, ev, data) -{ - static struct etimer et; - static unsigned time_counter; - static unsigned r_rand; - - PROCESS_EXITHANDLER(goto exit); - - PROCESS_BEGIN(); - - deluge_event = process_alloc_event(); - - broadcast_open(&deluge_broadcast, DELUGE_BROADCAST_CHANNEL, &broadcast_call); - unicast_open(&deluge_uc, DELUGE_UNICAST_CHANNEL, &unicast_call); - r_interval = T_LOW; - - PRINTF("Maintaining state for object %s of %d pages\n", - current_object.filename, OBJECT_PAGE_COUNT(current_object)); - - deluge_state = DELUGE_STATE_MAINTAIN; - - for(r_interval = T_LOW;;) { - if(neighbor_inconsistency) { - /* Deluge M.2 */ - r_interval = T_LOW; - neighbor_inconsistency = 0; - } else { - /* Deluge M.3 */ - r_interval = (2 * r_interval >= T_HIGH) ? T_HIGH : 2 * r_interval; - } - - r_rand = r_interval / 2 + ((unsigned)random_rand() % (r_interval / 2)); - recv_adv = 0; - old_summary = 0; - - /* Deluge M.1 */ - ctimer_set(&summary_timer, r_rand * CLOCK_SECOND, - (void *)(void *)advertise_summary, ¤t_object); - - /* Deluge M.4 */ - ctimer_set(&profile_timer, r_rand * CLOCK_SECOND, - (void *)(void *)send_profile, ¤t_object); - - LONG_TIMER(et, time_counter, r_interval); - } - -exit: - unicast_close(&deluge_uc); - broadcast_close(&deluge_broadcast); - if(current_object.cfs_fd >= 0) { - cfs_close(current_object.cfs_fd); - } - if(current_object.pages != NULL) { - free(current_object.pages); - } - - PROCESS_END(); -} diff --git a/apps/deluge/deluge.h b/apps/deluge/deluge.h deleted file mode 100644 index 11bdd0a96..000000000 --- a/apps/deluge/deluge.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2007, Swedish Institute of Computer Science - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ - -/** - * \file - * Header for Deluge. - * \author - * Nicolas Tsiftes - */ - -#ifndef DELUGE_H -#define DELUGE_H - -#include "net/rime/rime.h" - -PROCESS_NAME(deluge_process); - -#define LONG_TIMER(et, counter, time) \ - do { \ - for (counter = 0; counter < time; counter++) { \ - etimer_set(&et, CLOCK_SECOND); \ - PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); \ - } \ - } while (0) - -#define DELUGE_UNICAST_CHANNEL 55 -#define DELUGE_BROADCAST_CHANNEL 56 - -/* All the packets in a page have been received. */ -#define PAGE_COMPLETE 1 -/* All pages up to, and including, this page are complete. */ -#define PAGE_AVAILABLE 1 - -#define S_PKT 64 /* Deluge packet size. */ -#define N_PKT 4 /* Packets per page. */ -#define S_PAGE (S_PKT * N_PKT) /* Fixed page size. */ - -/* Bounds for the round time in seconds. */ -#define T_LOW 2 -#define T_HIGH 64 - -/* Random interval for request transmissions in jiffies. */ -#define T_R (CLOCK_SECOND * 2) - -/* Bound for the number of advertisements. */ -#define CONST_K 1 - -/* The number of pages in this object. */ -#define OBJECT_PAGE_COUNT(obj) (((obj).size + (S_PAGE - 1)) / S_PAGE) - -#define ALL_PACKETS ((1 << N_PKT) - 1) - -#define DELUGE_CMD_SUMMARY 1 -#define DELUGE_CMD_REQUEST 2 -#define DELUGE_CMD_PACKET 3 -#define DELUGE_CMD_PROFILE 4 - -#define DELUGE_STATE_MAINTAIN 1 -#define DELUGE_STATE_RX 2 -#define DELUGE_STATE_TX 3 - -#define CONST_LAMBDA 2 -#define CONST_ALPHA 0.5 - -#define CONST_OMEGA 8 -#define ESTIMATED_TX_TIME (CLOCK_SECOND) - -typedef uint8_t deluge_object_id_t; - -struct deluge_msg_summary { - uint8_t cmd; - uint8_t version; - uint8_t highest_available; - deluge_object_id_t object_id; -}; - -struct deluge_msg_request { - uint8_t cmd; - uint8_t version; - uint8_t pagenum; - uint8_t request_set; - deluge_object_id_t object_id; -}; - -struct deluge_msg_packet { - uint8_t cmd; - uint8_t version; - uint8_t pagenum; - uint8_t packetnum; - uint16_t crc; - deluge_object_id_t object_id; - unsigned char payload[S_PKT]; -}; - -struct deluge_msg_profile { - uint8_t cmd; - uint8_t version; - uint8_t npages; - deluge_object_id_t object_id; - uint8_t version_vector[]; -}; - -struct deluge_object { - char *filename; - uint16_t object_id; - uint16_t size; - uint8_t version; - uint8_t update_version; - struct deluge_page *pages; - uint8_t current_rx_page; - int8_t current_tx_page; - uint8_t nrequests; - uint8_t current_page[S_PAGE]; - uint8_t tx_set; - int cfs_fd; - linkaddr_t summary_from; -}; - -struct deluge_page { - uint32_t packet_set; - uint16_t crc; - clock_time_t last_request; - clock_time_t last_data; - uint8_t flags; - uint8_t version; -}; - -int deluge_disseminate(char *file, unsigned version); - -#endif diff --git a/apps/er-coap/er-coap-separate.h b/apps/er-coap/er-coap-separate.h index dbecf1b39..33a923240 100644 --- a/apps/er-coap/er-coap-separate.h +++ b/apps/er-coap/er-coap-separate.h @@ -61,7 +61,7 @@ typedef struct coap_separate { int coap_separate_handler(resource_t *resource, void *request, void *response); -void coap_separate_reject(); +void coap_separate_reject(void); void coap_separate_accept(void *request, coap_separate_t *separate_store); void coap_separate_resume(void *response, coap_separate_t *separate_store, uint8_t code); diff --git a/apps/er-coap/er-coap-transactions.h b/apps/er-coap/er-coap-transactions.h index 18bb421b1..10697134a 100644 --- a/apps/er-coap/er-coap-transactions.h +++ b/apps/er-coap/er-coap-transactions.h @@ -67,7 +67,7 @@ typedef struct coap_transaction { * Use snprintf(buf, len+1, "", ...) to completely fill payload */ } coap_transaction_t; -void coap_register_as_transaction_handler(); +void coap_register_as_transaction_handler(void); coap_transaction_t *coap_new_transaction(uint16_t mid, uip_ipaddr_t *addr, uint16_t port); @@ -75,6 +75,6 @@ void coap_send_transaction(coap_transaction_t *t); void coap_clear_transaction(coap_transaction_t *t); coap_transaction_t *coap_get_transaction_by_mid(uint16_t mid); -void coap_check_transactions(); +void coap_check_transactions(void); #endif /* COAP_TRANSACTIONS_H_ */ diff --git a/apps/ipso-objects/ipso-temperature.c b/apps/ipso-objects/ipso-temperature.c index 61c87554a..457dfe0f8 100644 --- a/apps/ipso-objects/ipso-temperature.c +++ b/apps/ipso-objects/ipso-temperature.c @@ -79,7 +79,7 @@ LWM2M_RESOURCES(temperature_resources, /* Temperature (Current) */ LWM2M_RESOURCE_CALLBACK(5700, { temp, NULL, NULL }), /* Units */ - LWM2M_RESOURCE_STRING(5701, "Celcius"), + LWM2M_RESOURCE_STRING(5701, "Cel"), /* Min Range Value */ LWM2M_RESOURCE_FLOATFIX(5603, IPSO_TEMPERATURE_MIN), /* Max Range Value */ diff --git a/apps/json/json.h b/apps/json/json.h index 51ef652f8..e4d7094c6 100644 --- a/apps/json/json.h +++ b/apps/json/json.h @@ -71,6 +71,7 @@ enum { JSON_ERROR_UNEXPECTED_ARRAY, JSON_ERROR_UNEXPECTED_END_OF_ARRAY, JSON_ERROR_UNEXPECTED_OBJECT, + JSON_ERROR_UNEXPECTED_END_OF_OBJECT, JSON_ERROR_UNEXPECTED_STRING }; diff --git a/apps/json/jsonparse.c b/apps/json/jsonparse.c index 8089ae9fb..6277b56c4 100644 --- a/apps/json/jsonparse.c +++ b/apps/json/jsonparse.c @@ -43,6 +43,14 @@ push(struct jsonparse_state *state, char c) return state->depth < JSONPARSE_MAX_DEPTH; } /*--------------------------------------------------------------------*/ +static void +modify(struct jsonparse_state *state, char c) +{ + if(state->depth > 0) { + state->stack[state->depth - 1] = c; + } +} +/*--------------------------------------------------------------------*/ static char pop(struct jsonparse_state *state) { @@ -50,25 +58,31 @@ pop(struct jsonparse_state *state) return JSON_TYPE_ERROR; } state->depth--; + state->vtype = state->stack[state->depth]; return state->stack[state->depth]; } /*--------------------------------------------------------------------*/ /* will pass by the value and store the start and length of the value for atomic types */ /*--------------------------------------------------------------------*/ -static void +static char atomic(struct jsonparse_state *state, char type) { char c; + const char *str; + int len; state->vstart = state->pos; - state->vtype = type; if(type == JSON_TYPE_STRING || type == JSON_TYPE_PAIR_NAME) { while((c = state->json[state->pos++]) && c != '"') { if(c == '\\') { state->pos++; /* skip current char */ } } + if (c != '"') { + state->error = JSON_ERROR_SYNTAX; + return JSON_TYPE_ERROR; + } state->vlen = state->pos - state->vstart - 1; } else if(type == JSON_TYPE_NUMBER) { do { @@ -82,8 +96,31 @@ atomic(struct jsonparse_state *state, char type) /* need to back one step since first char is already gone */ state->vstart--; state->vlen = state->pos - state->vstart; + } else if(type == JSON_TYPE_NULL || type == JSON_TYPE_TRUE || type == JSON_TYPE_FALSE) { + state->vstart--; + switch (type) { + case JSON_TYPE_NULL: str = "null"; break; + case JSON_TYPE_TRUE: str = "true"; break; + case JSON_TYPE_FALSE: str = "false"; break; + default: str = ""; break; + } + + while ((c = state->json[state->pos]) && c != ' ' && c != ',' && c != ']' && c != '}') { + state->pos++; + } + + state->vlen = state->pos - state->vstart; + len = strlen(str); + len = state->vlen > len ? state->vlen : len; + + if (strncmp(str, &state->json[state->vstart], len) != 0) { + state->error = JSON_ERROR_SYNTAX; + return JSON_TYPE_ERROR; + } } - /* no other types for now... */ + + state->vtype = type; + return state->vtype; } /*--------------------------------------------------------------------*/ static void @@ -97,6 +134,17 @@ skip_ws(struct jsonparse_state *state) } } /*--------------------------------------------------------------------*/ +static int +is_atomic(struct jsonparse_state *state) +{ + char v = state->vtype; + if(v == 'N' || v == '"' || v == '0' || v == 'n' || v == 't' || v == 'f') { + return 1; + } else { + return 0; + } +} +/*--------------------------------------------------------------------*/ void jsonparse_setup(struct jsonparse_state *state, const char *json, int len) { @@ -105,6 +153,7 @@ jsonparse_setup(struct jsonparse_state *state, const char *json, int len) state->pos = 0; state->depth = 0; state->error = 0; + state->vtype = 0; state->stack[0] = 0; } /*--------------------------------------------------------------------*/ @@ -113,31 +162,33 @@ jsonparse_next(struct jsonparse_state *state) { char c; char s; + char v; skip_ws(state); c = state->json[state->pos]; s = jsonparse_get_type(state); + v = state->vtype; state->pos++; switch(c) { case '{': - push(state, c); + if((s == 0 && v == 0) || s == '[' || s == ':') { + push(state, c); + } else { + state->error = JSON_ERROR_UNEXPECTED_OBJECT; + return JSON_TYPE_ERROR; + } return c; case '}': - if(s == ':' && state->vtype != 0) { -/* printf("Popping vtype: '%c'\n", state->vtype); */ - pop(state); - s = jsonparse_get_type(state); - } - if(s == '{') { + if((s == ':' && v != ',' && v != 0 ) || (s == '{' && v == 0)) { pop(state); } else { - state->error = JSON_ERROR_SYNTAX; + state->error = JSON_ERROR_UNEXPECTED_END_OF_OBJECT; return JSON_TYPE_ERROR; } return c; case ']': - if(s == '[') { + if(s == '[' && v != ',') { pop(state); } else { state->error = JSON_ERROR_UNEXPECTED_END_OF_ARRAY; @@ -145,41 +196,67 @@ jsonparse_next(struct jsonparse_state *state) } return c; case ':': - push(state, c); - return c; + if(s == '{' && v == 'N') { + modify(state, ':'); + state->vtype = 0; + } else { + state->error = JSON_ERROR_SYNTAX; + return JSON_TYPE_ERROR; + } + return jsonparse_next(state); case ',': - /* if x:y ... , */ - if(s == ':' && state->vtype != 0) { - pop(state); + if(s == ':' && v != 0) { + modify(state, '{'); + state->vtype = c; } else if(s == '[') { - /* ok! */ + state->vtype = c; } else { state->error = JSON_ERROR_SYNTAX; return JSON_TYPE_ERROR; } return c; case '"': - if(s == '{' || s == '[' || s == ':') { - atomic(state, c = (s == '{' ? JSON_TYPE_PAIR_NAME : c)); + if((s == 0 && v == 0) || s == '{' || s == '[' || s == ':') { + return atomic(state, c = (s == '{' ? JSON_TYPE_PAIR_NAME : c)); } else { state->error = JSON_ERROR_UNEXPECTED_STRING; return JSON_TYPE_ERROR; } return c; case '[': - if(s == '{' || s == '[' || s == ':') { + if((s == 0 && v == 0) || s == '[' || s == ':') { push(state, c); } else { state->error = JSON_ERROR_UNEXPECTED_ARRAY; return JSON_TYPE_ERROR; } return c; + case 0: + if(v == 0 || state->depth > 0) { + state->error = JSON_ERROR_SYNTAX; + } + return JSON_TYPE_ERROR; default: - if(s == ':' || s == '[') { - if(c <= '9' && c >= '0') { - atomic(state, JSON_TYPE_NUMBER); - return JSON_TYPE_NUMBER; + if(s == 0 || s == ':' || s == '[') { + if (v != 0 && v != ',') { + state->error = JSON_ERROR_SYNTAX; + return JSON_TYPE_ERROR; } + if(c == '-' || (c <= '9' && c >= '0')) { + return atomic(state, JSON_TYPE_NUMBER); + } else if(c == 'n') { + return atomic(state, JSON_TYPE_NULL); + } else if(c == 't') { + return atomic(state, JSON_TYPE_TRUE); + } else if(c == 'f') { + return atomic(state, JSON_TYPE_FALSE); + } else { + state->error = JSON_ERROR_SYNTAX; + return JSON_TYPE_ERROR; + } + } else if(s == '{') { + state->error = JSON_ERROR_SYNTAX; + return JSON_TYPE_ERROR; } } return 0; @@ -192,16 +269,31 @@ jsonparse_next(struct jsonparse_state *state) int jsonparse_copy_value(struct jsonparse_state *state, char *str, int size) { - int i; + int i, o; + char c; - if(state->vtype == 0) { + if(!is_atomic(state)) { return 0; } - size = size <= state->vlen ? (size - 1) : state->vlen; - for(i = 0; i < size; i++) { - str[i] = state->json[state->vstart + i]; + for(i = 0, o = 0; i < state->vlen && o < size - 1; i++) { + c = state->json[state->vstart + i]; + if(c == '\\') { + i++; + switch(state->json[state->vstart + i]) { + case '"': str[o++] = '"'; break; + case '\\': str[o++] = '\\'; break; + case '/': str[o++] = '/'; break; + case 'b': str[o++] = '\b'; break; + case 'f': str[o++] = '\f'; break; + case 'n': str[o++] = '\n'; break; + case 'r': str[o++] = '\r'; break; + case 't': str[o++] = '\t'; break; + } + continue; + } + str[o++] = c; } - str[i] = 0; + str[o] = 0; return state->vtype; } /*--------------------------------------------------------------------*/ @@ -228,7 +320,7 @@ jsonparse_get_value_as_long(struct jsonparse_state *state) int jsonparse_strcmp_value(struct jsonparse_state *state, const char *str) { - if(state->vtype == 0) { + if(!is_atomic(state)) { return -1; } return strncmp(str, &state->json[state->vstart], state->vlen); diff --git a/apps/oma-lwm2m/Makefile.oma-lwm2m b/apps/oma-lwm2m/Makefile.oma-lwm2m index 8445530ed..000147939 100644 --- a/apps/oma-lwm2m/Makefile.oma-lwm2m +++ b/apps/oma-lwm2m/Makefile.oma-lwm2m @@ -1,5 +1,13 @@ -oma-lwm2m_src = lwm2m-object.c lwm2m-engine.c \ - lwm2m-device.c lwm2m-server.c lwm2m-security.c \ - oma-tlv.c oma-tlv-reader.c oma-tlv-writer.c \ - lwm2m-plain-text.c +oma-lwm2m_src = \ + lwm2m-object.c \ + lwm2m-engine.c \ + lwm2m-device.c \ + lwm2m-server.c \ + lwm2m-security.c \ + oma-tlv.c \ + oma-tlv-reader.c \ + oma-tlv-writer.c \ + lwm2m-plain-text.c \ + lwm2m-json.c \ + # CFLAGS += -DHAVE_OMA_LWM2M=1 diff --git a/apps/oma-lwm2m/lwm2m-engine.c b/apps/oma-lwm2m/lwm2m-engine.c index 62f549db4..0fe86bbbb 100644 --- a/apps/oma-lwm2m/lwm2m-engine.c +++ b/apps/oma-lwm2m/lwm2m-engine.c @@ -46,10 +46,12 @@ #include "lwm2m-object.h" #include "lwm2m-device.h" #include "lwm2m-plain-text.h" +#include "lwm2m-json.h" #include "rest-engine.h" #include "er-coap-constants.h" #include "er-coap-engine.h" #include "oma-tlv.h" +#include "oma-tlv-reader.h" #include "oma-tlv-writer.h" #include "net/ipv6/uip-ds6.h" #include @@ -639,10 +641,10 @@ write_rd_json_data(const lwm2m_context_t *context, value = lwm2m_object_get_resource_string(resource, context); slen = lwm2m_object_get_resource_strlen(resource, context); if(value != NULL) { - PRINTF("%s{\"n\":\"%u\",\"vs\":\"%.*s\"}", s, + PRINTF("%s{\"n\":\"%u\",\"sv\":\"%.*s\"}", s, resource->id, slen, value); len = snprintf(&buffer[rdlen], size - rdlen, - "%s{\"n\":\"%u\",\"vs\":\"%.*s\"}", s, + "%s{\"n\":\"%u\",\"sv\":\"%.*s\"}", s, resource->id, slen, value); } } else if(lwm2m_object_is_resource_int(resource)) { @@ -682,10 +684,10 @@ write_rd_json_data(const lwm2m_context_t *context, } else if(lwm2m_object_is_resource_boolean(resource)) { int value; if(lwm2m_object_get_resource_boolean(resource, context, &value)) { - PRINTF("%s{\"n\":\"%u\",\"v\":%s}", s, resource->id, + PRINTF("%s{\"n\":\"%u\",\"bv\":%s}", s, resource->id, value ? "true" : "false"); len = snprintf(&buffer[rdlen], size - rdlen, - "%s{\"n\":\"%u\",\"v\":%s}", s, resource->id, + "%s{\"n\":\"%u\",\"bv\":%s}", s, resource->id, value ? "true" : "false"); } } @@ -707,6 +709,63 @@ write_rd_json_data(const lwm2m_context_t *context, return rdlen; } /*---------------------------------------------------------------------------*/ +/** + * @brief Set the writer pointer to the proper writer based on the Accept: header + * + * @param[in] context LWM2M context to operate on + * @param[in] accept Accept type number from CoAP headers + * + * @return The content type of the response if the selected writer is used + */ +static unsigned int +lwm2m_engine_select_writer(lwm2m_context_t *context, unsigned int accept) +{ + switch(accept) { + case LWM2M_TLV: + context->writer = &oma_tlv_writer; + break; + case LWM2M_TEXT_PLAIN: + case TEXT_PLAIN: + context->writer = &lwm2m_plain_text_writer; + break; + case LWM2M_JSON: + case APPLICATION_JSON: + context->writer = &lwm2m_json_writer; + break; + default: + PRINTF("Unknown Accept type %u, using LWM2M plain text\n", accept); + context->writer = &lwm2m_plain_text_writer; + /* Set the response type to plain text */ + accept = LWM2M_TEXT_PLAIN; + break; + } + return accept; +} +/*---------------------------------------------------------------------------*/ +/** + * @brief Set the reader pointer to the proper reader based on the Content-format: header + * + * @param[in] context LWM2M context to operate on + * @param[in] content_format Content-type type number from CoAP headers + */ +static void +lwm2m_engine_select_reader(lwm2m_context_t *context, unsigned int content_format) +{ + switch(content_format) { + case LWM2M_TLV: + context->reader = &oma_tlv_reader; + break; + case LWM2M_TEXT_PLAIN: + case TEXT_PLAIN: + context->reader = &lwm2m_plain_text_reader; + break; + default: + PRINTF("Unknown content type %u, using LWM2M plain text\n", accept); + context->reader = &lwm2m_plain_text_reader; + break; + } +} +/*---------------------------------------------------------------------------*/ void lwm2m_engine_handler(const lwm2m_object_t *object, void *request, void *response, @@ -716,6 +775,8 @@ lwm2m_engine_handler(const lwm2m_object_t *object, int len; const char *url; unsigned int format; + unsigned int accept; + unsigned int content_type; int depth; lwm2m_context_t context; rest_resource_flags_t method; @@ -734,11 +795,19 @@ lwm2m_engine_handler(const lwm2m_object_t *object, /* CoAP content format text plain - assume LWM2M text plain */ format = LWM2M_TEXT_PLAIN; } + if(!REST.get_header_accept(request, &accept)) { + PRINTF("No Accept header, using same as Content-format...\n"); + accept = format; + } depth = lwm2m_engine_parse_context(object, url, len, &context); PRINTF("Context: %u/%u/%u found: %d\n", context.object_id, context.object_instance_id, context.resource_id, depth); + /* Select reader and writer based on provided Content type and Accept headers */ + lwm2m_engine_select_reader(&context, format); + content_type = lwm2m_engine_select_writer(&context, accept); + #if (DEBUG) & DEBUG_PRINT /* for debugging */ if(method == METHOD_GET) { @@ -861,7 +930,7 @@ lwm2m_engine_handler(const lwm2m_object_t *object, if(depth == 3) { const lwm2m_resource_t *resource = get_resource(instance, &context); - size_t tlvlen = 0; + size_t content_len = 0; if(resource == NULL) { PRINTF("Error - do not have resource %d\n", context.resource_id); REST.set_response_status(response, NOT_FOUND_4_04); @@ -879,9 +948,9 @@ lwm2m_engine_handler(const lwm2m_object_t *object, context.reader = &lwm2m_plain_text_reader; PRINTF("PUT Callback with data: '%.*s'\n", plen, data); /* no specific reader for plain text */ - tlvlen = resource->value.callback.write(&context, data, plen, + content_len = resource->value.callback.write(&context, data, plen, buffer, preferred_size); - PRINTF("tlvlen:%u\n", (unsigned int)tlvlen); + PRINTF("content_len:%u\n", (unsigned int)content_len); REST.set_response_status(response, CHANGED_2_04); } else { PRINTF("PUT callback with format %d\n", format); @@ -899,48 +968,39 @@ lwm2m_engine_handler(const lwm2m_object_t *object, } else if(method == METHOD_GET) { if(lwm2m_object_is_resource_string(resource)) { const uint8_t *value; - uint16_t len; value = lwm2m_object_get_resource_string(resource, &context); - len = lwm2m_object_get_resource_strlen(resource, &context); if(value != NULL) { + uint16_t len = lwm2m_object_get_resource_strlen(resource, &context); PRINTF("Get string value: %.*s\n", (int)len, (char *)value); - /* TODO check format */ - REST.set_response_payload(response, value, len); - REST.set_header_content_type(response, LWM2M_TEXT_PLAIN); - /* Done */ - return; + content_len = context.writer->write_string(&context, buffer, + preferred_size, (const char *)value, len); } } else if(lwm2m_object_is_resource_int(resource)) { int32_t value; if(lwm2m_object_get_resource_int(resource, &context, &value)) { - /* export INT as TLV */ - tlvlen = oma_tlv_write_int32(resource->id, value, buffer, preferred_size); - PRINTF("Exporting int as TLV: %" PRId32 ", len: %u\n", - value, (unsigned int)tlvlen); + content_len = context.writer->write_int(&context, buffer, preferred_size, value); } } else if(lwm2m_object_is_resource_floatfix(resource)) { int32_t value; if(lwm2m_object_get_resource_floatfix(resource, &context, &value)) { - /* export FLOATFIX as TLV */ + /* export FLOATFIX */ PRINTF("Exporting %d-bit fix as float: %" PRId32 "\n", LWM2M_FLOAT32_BITS, value); - tlvlen = oma_tlv_write_float32(resource->id, - value, LWM2M_FLOAT32_BITS, - buffer, preferred_size); - PRINTF("Exporting as TLV: len:%u\n", (unsigned int)tlvlen); + content_len = context.writer->write_float32fix(&context, buffer, + preferred_size, value, LWM2M_FLOAT32_BITS); } } else if(lwm2m_object_is_resource_callback(resource)) { if(resource->value.callback.read != NULL) { - tlvlen = resource->value.callback.read(&context, + content_len = resource->value.callback.read(&context, buffer, preferred_size); } else { REST.set_response_status(response, METHOD_NOT_ALLOWED_4_05); return; } } - if(tlvlen > 0) { - REST.set_response_payload(response, buffer, tlvlen); - REST.set_header_content_type(response, LWM2M_TLV); + if(content_len > 0) { + REST.set_response_payload(response, buffer, content_len); + REST.set_header_content_type(response, content_type); } else { /* failed to produce output - it is an internal error */ REST.set_response_status(response, INTERNAL_SERVER_ERROR_5_00); @@ -952,7 +1012,7 @@ lwm2m_engine_handler(const lwm2m_object_t *object, const uint8_t *data; int plen = REST.get_request_payload(request, &data); PRINTF("Execute Callback with data: '%.*s'\n", plen, data); - tlvlen = resource->value.callback.exec(&context, + content_len = resource->value.callback.exec(&context, data, plen, buffer, preferred_size); REST.set_response_status(response, CHANGED_2_04); @@ -973,7 +1033,7 @@ lwm2m_engine_handler(const lwm2m_object_t *object, REST.set_response_status(response, NOT_FOUND_4_04); } else { int rdlen; - if(format == APPLICATION_LINK_FORMAT) { + if(accept == APPLICATION_LINK_FORMAT) { rdlen = write_rd_link_data(object, instance, (char *)buffer, preferred_size); } else { @@ -986,10 +1046,10 @@ lwm2m_engine_handler(const lwm2m_object_t *object, return; } REST.set_response_payload(response, buffer, rdlen); - if(format == APPLICATION_LINK_FORMAT) { + if(accept == APPLICATION_LINK_FORMAT) { REST.set_header_content_type(response, REST.type.APPLICATION_LINK_FORMAT); } else { - REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + REST.set_header_content_type(response, LWM2M_JSON); } } } diff --git a/apps/oma-lwm2m/lwm2m-json.c b/apps/oma-lwm2m/lwm2m-json.c new file mode 100644 index 000000000..8924ceb8c --- /dev/null +++ b/apps/oma-lwm2m/lwm2m-json.c @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2016, Eistec AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup oma-lwm2m + * @{ + */ + +/** + * \file + * Implementation of the Contiki OMA LWM2M JSON writer + * \author + * Joakim NohlgÃ¥rd + */ + +#include "lwm2m-object.h" +#include "lwm2m-json.h" +#include "lwm2m-plain-text.h" +#include +#include +#include +#include + +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/*---------------------------------------------------------------------------*/ +static size_t +write_boolean(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + int value) +{ + int len = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"bv\":%s}]}\n", ctx->resource_id, value ? "true" : "false"); + if((len < 0) || (len >= outlen)) { + return 0; + } + return len; +} +/*---------------------------------------------------------------------------*/ +static size_t +write_int(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + int32_t value) +{ + int len = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"v\":%" PRId32 "}]}\n", ctx->resource_id, value); + if((len < 0) || (len >= outlen)) { + return 0; + } + return len; +} +/*---------------------------------------------------------------------------*/ +static size_t +write_float32fix(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + int32_t value, int bits) +{ + size_t len = 0; + int res; + res = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"v\":", ctx->resource_id); + if(res <= 0 || res >= outlen) { + return 0; + } + len += res; + outlen -= res; + res = lwm2m_plain_text_write_float32fix(&outbuf[len], outlen, value, bits); + if((res <= 0) || (res >= outlen)) { + return 0; + } + len += res; + outlen -= res; + res = snprintf((char *)&outbuf[len], outlen, "}]}\n"); + if((res <= 0) || (res >= outlen)) { + return 0; + } + len += res; + return len; +} +/*---------------------------------------------------------------------------*/ +static size_t +write_string(const lwm2m_context_t *ctx, uint8_t *outbuf, size_t outlen, + const char *value, size_t stringlen) +{ + size_t i; + size_t len = 0; + int res; + PRINTF("{\"e\":[{\"n\":\"%u\",\"sv\":\"", ctx->resource_id); + res = snprintf((char *)outbuf, outlen, "{\"e\":[{\"n\":\"%u\",\"sv\":\"", ctx->resource_id); + if(res < 0 || res >= outlen) { + return 0; + } + len += res; + for (i = 0; i < stringlen && len < outlen; ++i) { + /* Escape special characters */ + /* TODO: Handle UTF-8 strings */ + if(value[i] < '\x20') { + PRINTF("\\x%x", value[i]); + res = snprintf((char *)&outbuf[len], outlen - len, "\\x%x", value[i]); + if((res < 0) || (res >= (outlen - len))) { + return 0; + } + len += res; + continue; + } else if(value[i] == '"' || value[i] == '\\') { + PRINTF("\\"); + outbuf[len] = '\\'; + ++len; + if(len >= outlen) { + return 0; + } + } + PRINTF("%c", value[i]); + outbuf[len] = value[i]; + ++len; + if(len >= outlen) { + return 0; + } + } + PRINTF("\"}]}\n"); + res = snprintf((char *)&outbuf[len], outlen - len, "\"}]}\n"); + if((res < 0) || (res >= (outlen - len))) { + return 0; + } + len += res; + return len; +} +/*---------------------------------------------------------------------------*/ +const lwm2m_writer_t lwm2m_json_writer = { + write_int, + write_string, + write_float32fix, + write_boolean +}; +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/apps/oma-lwm2m/lwm2m-json.h b/apps/oma-lwm2m/lwm2m-json.h new file mode 100644 index 000000000..bc1a1e32a --- /dev/null +++ b/apps/oma-lwm2m/lwm2m-json.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016, Eistec AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup oma-lwm2m + * @{ + */ + +/** + * \file + * Header file for the Contiki OMA LWM2M JSON writer + * \author + * Joakim NohlgÃ¥rd + */ + +#ifndef LWM2M_JSON_H_ +#define LWM2M_JSON_H_ + +#include "lwm2m-object.h" + +extern const lwm2m_writer_t lwm2m_json_writer; + +#endif /* LWM2M_JSON_H_ */ +/** @} */ diff --git a/apps/oma-lwm2m/lwm2m-plain-text.c b/apps/oma-lwm2m/lwm2m-plain-text.c index 34b7f2318..b2bc5dcbe 100644 --- a/apps/oma-lwm2m/lwm2m-plain-text.c +++ b/apps/oma-lwm2m/lwm2m-plain-text.c @@ -100,6 +100,11 @@ lwm2m_plain_text_read_float32fix(const uint8_t *inbuf, size_t len, break; } } + if(dot == 0) { + integerpart = counter; + counter = 0; + frac = 1; + } *value = integerpart << bits; if(frac > 1) { *value += ((counter << bits) / frac); diff --git a/apps/orchestra/Makefile.orchestra b/apps/orchestra/Makefile.orchestra index 314fdac23..8c30a816e 100644 --- a/apps/orchestra/Makefile.orchestra +++ b/apps/orchestra/Makefile.orchestra @@ -1 +1 @@ -orchestra_src = orchestra.c orchestra-rule-default-common.c orchestra-rule-eb-per-time-source.c orchestra-rule-unicast-per-neighbor.c +orchestra_src = orchestra.c orchestra-rule-default-common.c orchestra-rule-eb-per-time-source.c orchestra-rule-unicast-per-neighbor-rpl-storing.c orchestra-rule-unicast-per-neighbor-rpl-ns.c diff --git a/apps/orchestra/orchestra-conf.h b/apps/orchestra/orchestra-conf.h index 910917620..d8116ff16 100644 --- a/apps/orchestra/orchestra-conf.h +++ b/apps/orchestra/orchestra-conf.h @@ -46,10 +46,10 @@ * - a sender-based or receiver-based slotframe for unicast to RPL parents and children * - a common shared slotframe for any other traffic (mostly broadcast) * */ -#define ORCHESTRA_RULES { &eb_per_time_source, \ - &unicast_per_neighbor, \ - &default_common, \ - } +#define ORCHESTRA_RULES { &eb_per_time_source, &unicast_per_neighbor_rpl_storing, &default_common } +/* Example configuration for RPL non-storing mode: */ +/* #define ORCHESTRA_RULES { &eb_per_time_source, &unicast_per_neighbor_rpl_ns, &default_common } */ + #endif /* ORCHESTRA_CONF_RULES */ /* Length of the various slotframes. Tune to balance network capacity, diff --git a/apps/orchestra/orchestra-rule-eb-per-time-source.c b/apps/orchestra/orchestra-rule-eb-per-time-source.c index 0f774f531..ed037291b 100644 --- a/apps/orchestra/orchestra-rule-eb-per-time-source.c +++ b/apps/orchestra/orchestra-rule-eb-per-time-source.c @@ -74,8 +74,8 @@ select_packet(uint16_t *slotframe, uint16_t *timeslot) static void new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new) { - uint16_t old_ts = get_node_timeslot(&old->addr); - uint16_t new_ts = get_node_timeslot(&new->addr); + uint16_t old_ts = old != NULL ? get_node_timeslot(&old->addr) : 0xffff; + uint16_t new_ts = new != NULL ? get_node_timeslot(&new->addr) : 0xffff; if(new_ts == old_ts) { return; @@ -83,14 +83,24 @@ new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new if(old_ts != 0xffff) { /* Stop listening to the old time source's EBs */ - tsch_schedule_remove_link_by_timeslot(sf_eb, old_ts); + if(old_ts == get_node_timeslot(&linkaddr_node_addr)) { + /* This was the same timeslot as slot. Reset original link options */ + tsch_schedule_add_link(sf_eb, LINK_OPTION_TX, LINK_TYPE_ADVERTISING_ONLY, + &tsch_broadcast_address, old_ts, 0); + } else { + /* Remove slot */ + tsch_schedule_remove_link_by_timeslot(sf_eb, old_ts); + } } if(new_ts != 0xffff) { + uint8_t link_options = LINK_OPTION_RX; + if(new_ts == get_node_timeslot(&linkaddr_node_addr)) { + /* This is also our timeslot, add necessary flags */ + link_options |= LINK_OPTION_TX; + } /* Listen to the time source's EBs */ - tsch_schedule_add_link(sf_eb, - LINK_OPTION_RX, - LINK_TYPE_ADVERTISING_ONLY, NULL, - new_ts, 0); + tsch_schedule_add_link(sf_eb, link_options, LINK_TYPE_ADVERTISING_ONLY, + &tsch_broadcast_address, new_ts, 0); } } /*---------------------------------------------------------------------------*/ diff --git a/apps/orchestra/orchestra-rule-unicast-per-neighbor-rpl-ns.c b/apps/orchestra/orchestra-rule-unicast-per-neighbor-rpl-ns.c new file mode 100644 index 000000000..d72646e1d --- /dev/null +++ b/apps/orchestra/orchestra-rule-unicast-per-neighbor-rpl-ns.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2016, Inria. + * 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 + * Orchestra: a slotframe dedicated to unicast data transmission. Designed primarily + * for RPL non-storing mode but would work with any mode-of-operation. Does not require + * any knowledge of the children. Works only as received-base, and as follows: + * Nodes listen at a timeslot defined as hash(MAC) % ORCHESTRA_SB_UNICAST_PERIOD + * Nodes transmit at: for any neighbor, hash(nbr.MAC) % ORCHESTRA_SB_UNICAST_PERIOD + * + * \author Simon Duquennoy + */ + +#include "contiki.h" +#include "orchestra.h" +#include "net/ipv6/uip-ds6-route.h" +#include "net/packetbuf.h" + +static uint16_t slotframe_handle = 0; +static uint16_t channel_offset = 0; +static struct tsch_slotframe *sf_unicast; + +/*---------------------------------------------------------------------------*/ +static uint16_t +get_node_timeslot(const linkaddr_t *addr) +{ + if(addr != NULL && ORCHESTRA_UNICAST_PERIOD > 0) { + return ORCHESTRA_LINKADDR_HASH(addr) % ORCHESTRA_UNICAST_PERIOD; + } else { + return 0xffff; + } +} +/*---------------------------------------------------------------------------*/ +static void +child_added(const linkaddr_t *linkaddr) +{ +} +/*---------------------------------------------------------------------------*/ +static void +child_removed(const linkaddr_t *linkaddr) +{ +} +/*---------------------------------------------------------------------------*/ +static int +select_packet(uint16_t *slotframe, uint16_t *timeslot) +{ + /* Select data packets we have a unicast link to */ + const linkaddr_t *dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); + if(packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE) == FRAME802154_DATAFRAME + && !linkaddr_cmp(dest, &linkaddr_null)) { + if(slotframe != NULL) { + *slotframe = slotframe_handle; + } + if(timeslot != NULL) { + *timeslot = get_node_timeslot(dest); + } + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new) +{ +} +/*---------------------------------------------------------------------------*/ +static void +init(uint16_t sf_handle) +{ + int i; + uint16_t rx_timeslot; + slotframe_handle = sf_handle; + channel_offset = sf_handle; + /* Slotframe for unicast transmissions */ + sf_unicast = tsch_schedule_add_slotframe(slotframe_handle, ORCHESTRA_UNICAST_PERIOD); + rx_timeslot = get_node_timeslot(&linkaddr_node_addr); + /* Add a Tx link at each available timeslot. Make the link Rx at our own timeslot. */ + for(i = 0; i < ORCHESTRA_UNICAST_PERIOD; i++) { + tsch_schedule_add_link(sf_unicast, + LINK_OPTION_SHARED | LINK_OPTION_TX | ( i == rx_timeslot ? LINK_OPTION_RX : 0 ), + LINK_TYPE_NORMAL, &tsch_broadcast_address, + i, channel_offset); + } +} +/*---------------------------------------------------------------------------*/ +struct orchestra_rule unicast_per_neighbor_rpl_ns = { + init, + new_time_source, + select_packet, + child_added, + child_removed, +}; diff --git a/apps/orchestra/orchestra-rule-unicast-per-neighbor.c b/apps/orchestra/orchestra-rule-unicast-per-neighbor-rpl-storing.c similarity index 82% rename from apps/orchestra/orchestra-rule-unicast-per-neighbor.c rename to apps/orchestra/orchestra-rule-unicast-per-neighbor-rpl-storing.c index b70a907d0..76e039f09 100644 --- a/apps/orchestra/orchestra-rule-unicast-per-neighbor.c +++ b/apps/orchestra/orchestra-rule-unicast-per-neighbor-rpl-storing.c @@ -29,12 +29,13 @@ */ /** * \file - * Orchestra: a slotframe dedicated to unicast data transmission. - * If sender-based: + * Orchestra: a slotframe dedicated to unicast data transmission. Designed for + * RPL storing mode only, as this is based on the knowledge of the children (and parent). + * If receiver-based: * Nodes listen at a timeslot defined as hash(MAC) % ORCHESTRA_SB_UNICAST_PERIOD * Nodes transmit at: for each nbr in RPL children and RPL preferred parent, * hash(nbr.MAC) % ORCHESTRA_SB_UNICAST_PERIOD - * If receiver-based: the opposite + * If sender-based: the opposite * * \author Simon Duquennoy */ @@ -43,6 +44,7 @@ #include "orchestra.h" #include "net/ipv6/uip-ds6-route.h" #include "net/packetbuf.h" +#include "net/rpl/rpl-conf.h" #if ORCHESTRA_UNICAST_SENDER_BASED && ORCHESTRA_COLLISION_FREE_HASH #define UNICAST_SLOT_SHARED_FLAG ((ORCHESTRA_UNICAST_PERIOD < (ORCHESTRA_MAX_HASH + 1)) ? LINK_OPTION_SHARED : 0) @@ -85,10 +87,16 @@ add_uc_link(const linkaddr_t *linkaddr) { if(linkaddr != NULL) { uint16_t timeslot = get_node_timeslot(linkaddr); - tsch_schedule_add_link(sf_unicast, - ORCHESTRA_UNICAST_SENDER_BASED ? LINK_OPTION_RX : LINK_OPTION_TX | UNICAST_SLOT_SHARED_FLAG, - LINK_TYPE_NORMAL, &tsch_broadcast_address, - timeslot, channel_offset); + uint8_t link_options = ORCHESTRA_UNICAST_SENDER_BASED ? LINK_OPTION_RX : LINK_OPTION_TX | UNICAST_SLOT_SHARED_FLAG; + + if(timeslot == get_node_timeslot(&linkaddr_node_addr)) { + /* This is also our timeslot, add necessary flags */ + link_options |= ORCHESTRA_UNICAST_SENDER_BASED ? LINK_OPTION_TX | UNICAST_SLOT_SHARED_FLAG: LINK_OPTION_RX; + } + + /* Add/update link */ + tsch_schedule_add_link(sf_unicast, link_options, LINK_TYPE_NORMAL, &tsch_broadcast_address, + timeslot, channel_offset); } } /*---------------------------------------------------------------------------*/ @@ -123,7 +131,17 @@ remove_uc_link(const linkaddr_t *linkaddr) } item = nbr_table_next(nbr_routes, item); } - tsch_schedule_remove_link(sf_unicast, l); + + /* Do we need this timeslot? */ + if(timeslot == get_node_timeslot(&linkaddr_node_addr)) { + /* This is our link, keep it but update the link options */ + uint8_t link_options = ORCHESTRA_UNICAST_SENDER_BASED ? LINK_OPTION_TX | UNICAST_SLOT_SHARED_FLAG: LINK_OPTION_RX; + tsch_schedule_add_link(sf_unicast, link_options, LINK_TYPE_NORMAL, &tsch_broadcast_address, + timeslot, channel_offset); + } else { + /* Remove link */ + tsch_schedule_remove_link(sf_unicast, l); + } } /*---------------------------------------------------------------------------*/ static void @@ -160,13 +178,14 @@ static void new_time_source(const struct tsch_neighbor *old, const struct tsch_neighbor *new) { if(new != old) { + const linkaddr_t *old_addr = old != NULL ? &old->addr : NULL; const linkaddr_t *new_addr = new != NULL ? &new->addr : NULL; if(new_addr != NULL) { linkaddr_copy(&orchestra_parent_linkaddr, new_addr); } else { linkaddr_copy(&orchestra_parent_linkaddr, &linkaddr_null); } - remove_uc_link(new_addr); + remove_uc_link(old_addr); add_uc_link(new_addr); } } @@ -185,7 +204,7 @@ init(uint16_t sf_handle) timeslot, channel_offset); } /*---------------------------------------------------------------------------*/ -struct orchestra_rule unicast_per_neighbor = { +struct orchestra_rule unicast_per_neighbor_rpl_storing = { init, new_time_source, select_packet, diff --git a/apps/orchestra/orchestra.h b/apps/orchestra/orchestra.h index a895335b5..b948a2985 100644 --- a/apps/orchestra/orchestra.h +++ b/apps/orchestra/orchestra.h @@ -53,7 +53,8 @@ struct orchestra_rule { }; struct orchestra_rule eb_per_time_source; -struct orchestra_rule unicast_per_neighbor; +struct orchestra_rule unicast_per_neighbor_rpl_storing; +struct orchestra_rule unicast_per_neighbor_rpl_ns; struct orchestra_rule default_common; extern linkaddr_t orchestra_parent_linkaddr; diff --git a/apps/shell/shell-exec.c b/apps/shell/shell-exec.c index 1f5bbf383..8442f22ef 100644 --- a/apps/shell/shell-exec.c +++ b/apps/shell/shell-exec.c @@ -116,11 +116,13 @@ PROCESS_THREAD(shell_exec_process, ev, data) shell_output_str(&exec_command, print, symbol); if(ret == ELFLOADER_OK) { +#if !PROCESS_CONF_NO_PROCESS_NAMES int i; for(i = 0; elfloader_autostart_processes[i] != NULL; ++i) { shell_output_str(&exec_command, "exec: starting process ", elfloader_autostart_processes[i]->name); } +#endif autostart_start(elfloader_autostart_processes); } diff --git a/core/cfs/cfs-coffee.c b/core/cfs/cfs-coffee.c index 4b08d4544..9aa5726b7 100644 --- a/core/cfs/cfs-coffee.c +++ b/core/cfs/cfs-coffee.c @@ -75,12 +75,6 @@ #error "Cannot have COFFEE_APPEND_ONLY set when COFFEE_MICRO_LOGS is set." #endif -/* I/O semantics can be set on file descriptors in order to optimize - file access on certain storage types. */ -#ifndef COFFEE_IO_SEMANTICS -#define COFFEE_IO_SEMANTICS 0 -#endif - /* * Prevent sectors from being erased directly after file removal. * This will level the wear across sectors better, but may lead @@ -94,61 +88,66 @@ #error COFFEE_START must point to the first byte in a sector. #endif +/* File descriptor flags. */ #define COFFEE_FD_FREE 0x0 #define COFFEE_FD_READ 0x1 #define COFFEE_FD_WRITE 0x2 #define COFFEE_FD_APPEND 0x4 +/* File object flags. */ #define COFFEE_FILE_MODIFIED 0x1 -#define INVALID_PAGE ((coffee_page_t)-1) +/* Internal Coffee markers. */ +#define INVALID_PAGE ((coffee_page_t)-1) #define UNKNOWN_OFFSET ((cfs_offset_t)-1) -#define REMOVE_LOG 1 -#define CLOSE_FDS 1 -#define ALLOW_GC 1 +/* File removal actions. They can have the same values because + they are passed as separate parameters. */ +#define REMOVE_LOG 1 +#define CLOSE_FDS 1 +#define ALLOW_GC 1 /* "Greedy" garbage collection erases as many sectors as possible. */ -#define GC_GREEDY 0 +#define GC_GREEDY 0 /* "Reluctant" garbage collection stops after erasing one sector. */ -#define GC_RELUCTANT 1 +#define GC_RELUCTANT 1 /* File descriptor macros. */ -#define FD_VALID(fd) \ - ((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \ - coffee_fd_set[(fd)].flags != COFFEE_FD_FREE) +#define FD_VALID(fd) ((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \ + coffee_fd_set[(fd)].flags != COFFEE_FD_FREE) #define FD_READABLE(fd) (coffee_fd_set[(fd)].flags & CFS_READ) #define FD_WRITABLE(fd) (coffee_fd_set[(fd)].flags & CFS_WRITE) #define FD_APPENDABLE(fd) (coffee_fd_set[(fd)].flags & CFS_APPEND) /* File object macros. */ -#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED) -#define FILE_FREE(file) ((file)->max_pages == 0) +#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED) +#define FILE_FREE(file) ((file)->max_pages == 0) #define FILE_UNREFERENCED(file) ((file)->references == 0) /* File header flags. */ -#define HDR_FLAG_VALID 0x1 /* Completely written header. */ -#define HDR_FLAG_ALLOCATED 0x2 /* Allocated file. */ -#define HDR_FLAG_OBSOLETE 0x4 /* File marked for GC. */ -#define HDR_FLAG_MODIFIED 0x8 /* Modified file, log exists. */ -#define HDR_FLAG_LOG 0x10 /* Log file. */ -#define HDR_FLAG_ISOLATED 0x20 /* Isolated page. */ +#define HDR_FLAG_VALID 0x01 /* Completely written header. */ +#define HDR_FLAG_ALLOCATED 0x02 /* Allocated file. */ +#define HDR_FLAG_OBSOLETE 0x04 /* File marked for GC. */ +#define HDR_FLAG_MODIFIED 0x08 /* Modified file, log exists. */ +#define HDR_FLAG_LOG 0x10 /* Log file. */ +#define HDR_FLAG_ISOLATED 0x20 /* Isolated page. */ /* File header macros. */ #define CHECK_FLAG(hdr, flag) ((hdr).flags & (flag)) -#define HDR_VALID(hdr) CHECK_FLAG(hdr, HDR_FLAG_VALID) -#define HDR_ALLOCATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ALLOCATED) -#define HDR_FREE(hdr) !HDR_ALLOCATED(hdr) -#define HDR_LOG(hdr) CHECK_FLAG(hdr, HDR_FLAG_LOG) -#define HDR_MODIFIED(hdr) CHECK_FLAG(hdr, HDR_FLAG_MODIFIED) -#define HDR_ISOLATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ISOLATED) -#define HDR_OBSOLETE(hdr) CHECK_FLAG(hdr, HDR_FLAG_OBSOLETE) -#define HDR_ACTIVE(hdr) (HDR_ALLOCATED(hdr) && \ - !HDR_OBSOLETE(hdr) && \ - !HDR_ISOLATED(hdr)) +#define HDR_VALID(hdr) CHECK_FLAG(hdr, HDR_FLAG_VALID) +#define HDR_ALLOCATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ALLOCATED) +#define HDR_FREE(hdr) !HDR_ALLOCATED(hdr) +#define HDR_LOG(hdr) CHECK_FLAG(hdr, HDR_FLAG_LOG) +#define HDR_MODIFIED(hdr) CHECK_FLAG(hdr, HDR_FLAG_MODIFIED) +#define HDR_ISOLATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ISOLATED) +#define HDR_OBSOLETE(hdr) CHECK_FLAG(hdr, HDR_FLAG_OBSOLETE) +#define HDR_ACTIVE(hdr) (HDR_ALLOCATED(hdr) && \ + !HDR_OBSOLETE(hdr) && \ + !HDR_ISOLATED(hdr)) /* Shortcuts derived from the hardware-dependent configuration of Coffee. */ -#define COFFEE_SECTOR_COUNT (unsigned)(COFFEE_SIZE / COFFEE_SECTOR_SIZE) +#define COFFEE_SECTOR_COUNT \ + (coffee_page_t)(COFFEE_SIZE / COFFEE_SECTOR_SIZE) #define COFFEE_PAGE_COUNT \ ((coffee_page_t)(COFFEE_SIZE / COFFEE_PAGE_SIZE)) #define COFFEE_PAGES_PER_SECTOR \ @@ -176,9 +175,7 @@ struct file_desc { cfs_offset_t offset; struct file *file; uint8_t flags; -#if COFFEE_IO_SEMANTICS uint8_t io_flags; -#endif }; /* The file header structure mimics the representation of file headers @@ -196,26 +193,18 @@ struct file_header { /* This is needed because of a buggy compiler. */ struct log_param { cfs_offset_t offset; - const char *buf; + char *buf; uint16_t size; }; /* - * The protected memory consists of structures that should not be - * overwritten during system checkpointing because they may be used by - * the checkpointing implementation. These structures need not be - * protected if checkpointing is not used. + * Variables that keep track of opened files and internal + * optimization information for Coffee. */ -static struct protected_mem_t { - struct file coffee_files[COFFEE_MAX_OPEN_FILES]; - struct file_desc coffee_fd_set[COFFEE_FD_SET_SIZE]; - coffee_page_t next_free; - char gc_wait; -} protected_mem; -static struct file *const coffee_files = protected_mem.coffee_files; -static struct file_desc *const coffee_fd_set = protected_mem.coffee_fd_set; -static coffee_page_t *const next_free = &protected_mem.next_free; -static char *const gc_wait = &protected_mem.gc_wait; +static struct file coffee_files[COFFEE_MAX_OPEN_FILES]; +static struct file_desc coffee_fd_set[COFFEE_FD_SET_SIZE]; +static coffee_page_t next_free; +static char gc_wait; /*---------------------------------------------------------------------------*/ static void @@ -229,11 +218,9 @@ static void read_header(struct file_header *hdr, coffee_page_t page) { COFFEE_READ(hdr, sizeof(*hdr), page * COFFEE_PAGE_SIZE); -#if DEBUG - if(HDR_ACTIVE(*hdr) && !HDR_VALID(*hdr)) { - PRINTF("Invalid header at page %u!\n", (unsigned)page); + if(DEBUG && HDR_ACTIVE(*hdr) && !HDR_VALID(*hdr)) { + PRINTF("Coffee: Invalid header at page %u!\n", (unsigned)page); } -#endif } /*---------------------------------------------------------------------------*/ static cfs_offset_t @@ -243,7 +230,7 @@ absolute_offset(coffee_page_t page, cfs_offset_t offset) } /*---------------------------------------------------------------------------*/ static coffee_page_t -get_sector_status(uint16_t sector, struct sector_status *stats) +get_sector_status(coffee_page_t sector, struct sector_status *stats) { static coffee_page_t skip_pages; static char last_pages_are_active; @@ -313,7 +300,7 @@ get_sector_status(uint16_t sector, struct sector_status *stats) /* * Determine the amount of pages in the following sectors that * should be remembered for the next iteration. This is necessary - * because no page except the first of a file contains information + * because no file page except the first contains information * about what type of page it is. A side effect of remembering this * amount is that there is no need to read in the headers of each * of these pages from the storage. @@ -364,11 +351,11 @@ isolate_pages(coffee_page_t start, coffee_page_t skip_pages) static void collect_garbage(int mode) { - uint16_t sector; + coffee_page_t sector; struct sector_status stats; coffee_page_t first_page, isolation_count; - PRINTF("Coffee: Running the file system garbage collector in %s mode\n", + PRINTF("Coffee: Running the garbage collector in %s mode\n", mode == GC_RELUCTANT ? "reluctant" : "greedy"); /* * The garbage collector erases as many sectors as possible. A sector is @@ -377,7 +364,7 @@ collect_garbage(int mode) for(sector = 0; sector < COFFEE_SECTOR_COUNT; sector++) { isolation_count = get_sector_status(sector, &stats); PRINTF("Coffee: Sector %u has %u active, %u obsolete, and %u free pages.\n", - sector, (unsigned)stats.active, + (unsigned)sector, (unsigned)stats.active, (unsigned)stats.obsolete, (unsigned)stats.free); if(stats.active > 0) { @@ -387,8 +374,8 @@ collect_garbage(int mode) if((mode == GC_RELUCTANT && stats.free == 0) || (mode == GC_GREEDY && stats.obsolete > 0)) { first_page = sector * COFFEE_PAGES_PER_SECTOR; - if(first_page < *next_free) { - *next_free = first_page; + if(first_page < next_free) { + next_free = first_page; } if(isolation_count > 0) { @@ -410,7 +397,7 @@ next_file(coffee_page_t page, struct file_header *hdr) { /* * The quick-skip algorithm for finding file extents is the most - * essential part of Coffee. The file allocation rules enables this + * essential part of Coffee. The file allocation rules enable this * algorithm to quickly jump over free areas and allocated extents * after reading single headers and determining their status. * @@ -458,10 +445,7 @@ load_file(coffee_page_t start, struct file_header *hdr) file->page = start; file->end = UNKNOWN_OFFSET; file->max_pages = hdr->max_pages; - file->flags = 0; - if(HDR_MODIFIED(*hdr)) { - file->flags |= COFFEE_FILE_MODIFIED; - } + file->flags = HDR_MODIFIED(*hdr) ? COFFEE_FILE_MODIFIED : 0; /* We don't know the amount of records yet. */ file->record_count = -1; @@ -539,7 +523,7 @@ find_contiguous_pages(coffee_page_t amount) struct file_header hdr; start = INVALID_PAGE; - for(page = *next_free; page < COFFEE_PAGE_COUNT;) { + for(page = next_free; page < COFFEE_PAGE_COUNT;) { read_header(&hdr, page); if(HDR_FREE(hdr)) { if(start == INVALID_PAGE) { @@ -555,8 +539,8 @@ find_contiguous_pages(coffee_page_t amount) page = next_file(page, &hdr); if(start + amount <= page) { - if(start == *next_free) { - *next_free = start + amount; + if(start == next_free) { + next_free = start + amount; } return start; } @@ -569,8 +553,8 @@ find_contiguous_pages(coffee_page_t amount) } /*---------------------------------------------------------------------------*/ static int -remove_by_page(coffee_page_t page, int remove_log, int close_fds, - int gc_allowed) +remove_by_page(coffee_page_t page, int remove_log, + int close_fds, int gc_allowed) { struct file_header hdr; int i; @@ -589,7 +573,7 @@ remove_by_page(coffee_page_t page, int remove_log, int close_fds, hdr.flags |= HDR_FLAG_OBSOLETE; write_header(&hdr, page); - *gc_wait = 0; + gc_wait = 0; /* Close all file descriptors that reference the removed file. */ if(close_fds) { @@ -608,11 +592,9 @@ remove_by_page(coffee_page_t page, int remove_log, int close_fds, } } -#if !COFFEE_EXTENDED_WEAR_LEVELLING - if(gc_allowed) { + if(!COFFEE_EXTENDED_WEAR_LEVELLING && gc_allowed) { collect_garbage(GC_RELUCTANT); } -#endif return 0; } @@ -638,13 +620,13 @@ reserve(const char *name, coffee_page_t pages, page = find_contiguous_pages(pages); if(page == INVALID_PAGE) { - if(*gc_wait) { + if(gc_wait) { return NULL; } collect_garbage(GC_GREEDY); page = find_contiguous_pages(pages); if(page == INVALID_PAGE) { - *gc_wait = 1; + gc_wait = 1; return NULL; } } @@ -656,7 +638,7 @@ reserve(const char *name, coffee_page_t pages, write_header(&hdr, page); PRINTF("Coffee: Reserved %u pages starting from %u for file %s\n", - pages, page, name); + (unsigned)pages, (unsigned)page, name); file = load_file(page, &hdr); if(file != NULL) { @@ -851,7 +833,7 @@ merge_log(coffee_page_t file_page, int extend) return -1; } - /* Copy the log configuration and the EOF hint. */ + /* Copy the log configuration. */ read_header(&hdr2, new_file->page); hdr2.log_record_size = hdr.log_record_size; hdr2.log_records = hdr.log_records; @@ -1005,6 +987,7 @@ cfs_open(const char *name, int flags) fdp = &coffee_fd_set[fd]; fdp->flags = 0; + fdp->io_flags = 0; fdp->file = find_file(name); if(fdp->file == NULL) { @@ -1063,7 +1046,12 @@ cfs_seek(int fd, cfs_offset_t offset, int whence) } if(fdp->file->end < new_offset) { - fdp->file->end = new_offset; + if(FD_WRITABLE(fd)) { + fdp->file->end = new_offset; + } else { + /* Disallow seeking past the end of the file for read only FDs */ + return (cfs_offset_t)-1; + } } return fdp->offset = new_offset; @@ -1106,11 +1094,16 @@ cfs_read(int fd, void *buf, unsigned size) fdp = &coffee_fd_set[fd]; file = fdp->file; - if(fdp->offset + size > file->end) { + + if(fdp->io_flags & CFS_COFFEE_IO_ENSURE_READ_LENGTH) { + while(fdp->offset + size > file->end) { + ((char *)buf)[--size] = '\0'; + } + } else if(fdp->offset + size > file->end) { size = file->end - fdp->offset; } - /* If the file is allocated, read directly in the file. */ + /* If the file is not modified, read directly from the file extent. */ if(!FILE_MODIFIED(file)) { COFFEE_READ(buf, size, absolute_offset(file->page, fdp->offset)); fdp->offset += size; @@ -1121,8 +1114,9 @@ cfs_read(int fd, void *buf, unsigned size) read_header(&hdr, file->page); /* - * Fill the buffer by copying from the log in first hand, or the - * ordinary file if the page has no log record. + * Copy the contents of the most recent log record. If there is + * no log record for the file area to read from, we simply read + * from the original file extent. */ for(bytes_left = size; bytes_left > 0; bytes_left -= r) { lp.offset = fdp->offset; @@ -1164,32 +1158,24 @@ cfs_write(int fd, const void *buf, unsigned size) file = fdp->file; /* Attempt to extend the file if we try to write past the end. */ -#if COFFEE_IO_SEMANTICS if(!(fdp->io_flags & CFS_COFFEE_IO_FIRM_SIZE)) { -#endif - while(size + fdp->offset + sizeof(struct file_header) > - (file->max_pages * COFFEE_PAGE_SIZE)) { - if(merge_log(file->page, 1) < 0) { - return -1; + while(size + fdp->offset + sizeof(struct file_header) > + (file->max_pages * COFFEE_PAGE_SIZE)) { + if(merge_log(file->page, 1) < 0) { + return -1; + } + file = fdp->file; + PRINTF("Extended the file at page %u\n", (unsigned)file->page); } - file = fdp->file; - PRINTF("Extended the file at page %u\n", (unsigned)file->page); } -#if COFFEE_IO_SEMANTICS -} -#endif #if COFFEE_MICRO_LOGS -#if COFFEE_IO_SEMANTICS if(!(fdp->io_flags & CFS_COFFEE_IO_FLASH_AWARE) && (FILE_MODIFIED(file) || fdp->offset < file->end)) { -#else - if(FILE_MODIFIED(file) || fdp->offset < file->end) { -#endif need_dummy_write = 0; for(bytes_left = size; bytes_left > 0;) { lp.offset = fdp->offset; - lp.buf = buf; + lp.buf = (void *)buf; lp.size = bytes_left; i = write_log_page(file, &lp); if(i < 0) { @@ -1227,16 +1213,14 @@ cfs_write(int fd, const void *buf, unsigned size) } } else { #endif /* COFFEE_MICRO_LOGS */ -#if COFFEE_APPEND_ONLY - if(fdp->offset < file->end) { - return -1; - } -#endif /* COFFEE_APPEND_ONLY */ + if(COFFEE_APPEND_ONLY && fdp->offset < file->end) { + return -1; + } - COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset)); - fdp->offset += size; + COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset)); + fdp->offset += size; #if COFFEE_MICRO_LOGS -} + } #endif /* COFFEE_MICRO_LOGS */ if(fdp->offset > file->end) { @@ -1250,10 +1234,10 @@ int cfs_opendir(struct cfs_dir *dir, const char *name) { /* - * Coffee is only guaranteed to support "/" and ".", but it does not - * currently enforce this. + * Coffee is only guaranteed to support the directory names "/" and ".", + * but it does not enforce this currently. */ - memset(dir->dummy_space, 0, sizeof(coffee_page_t)); + memset(dir->state, 0, sizeof(coffee_page_t)); return 0; } /*---------------------------------------------------------------------------*/ @@ -1262,19 +1246,19 @@ cfs_readdir(struct cfs_dir *dir, struct cfs_dirent *record) { struct file_header hdr; coffee_page_t page; + coffee_page_t next_page; - memcpy(&page, dir->dummy_space, sizeof(coffee_page_t)); + memcpy(&page, dir->state, sizeof(coffee_page_t)); while(page < COFFEE_PAGE_COUNT) { read_header(&hdr, page); if(HDR_ACTIVE(hdr) && !HDR_LOG(hdr)) { - coffee_page_t next_page; memcpy(record->name, hdr.name, sizeof(record->name)); record->name[sizeof(record->name) - 1] = '\0'; record->size = file_end(page); next_page = next_file(page, &hdr); - memcpy(dir->dummy_space, &next_page, sizeof(coffee_page_t)); + memcpy(dir->state, &next_page, sizeof(coffee_page_t)); return 0; } page = next_file(page, &hdr); @@ -1342,11 +1326,9 @@ cfs_coffee_set_io_semantics(int fd, unsigned flags) int cfs_coffee_format(void) { - unsigned i; + coffee_page_t i; - PRINTF("Coffee: Formatting %u sectors", COFFEE_SECTOR_COUNT); - - *next_free = 0; + PRINTF("Coffee: Formatting %u sectors", (unsigned)COFFEE_SECTOR_COUNT); for(i = 0; i < COFFEE_SECTOR_COUNT; i++) { COFFEE_ERASE(i); @@ -1354,16 +1336,13 @@ cfs_coffee_format(void) } /* Formatting invalidates the file information. */ - memset(&protected_mem, 0, sizeof(protected_mem)); + memset(&coffee_files, 0, sizeof(coffee_files)); + memset(&coffee_fd_set, 0, sizeof(coffee_fd_set)); + next_free = 0; + gc_wait = 1; PRINTF(" done!\n"); return 0; } /*---------------------------------------------------------------------------*/ -void * -cfs_coffee_get_protected_mem(unsigned *size) -{ - *size = sizeof(protected_mem); - return &protected_mem; -} diff --git a/core/cfs/cfs-coffee.h b/core/cfs/cfs-coffee.h index a227792a1..96d382980 100644 --- a/core/cfs/cfs-coffee.h +++ b/core/cfs/cfs-coffee.h @@ -46,15 +46,15 @@ * invoke its own micro logs when file modifications occur. * * This semantical I/O setting is useful when implementing flash storage - * algorithms on top of Coffee. + * algorithms such as database indices on top of Coffee. * * \sa cfs_coffee_set_io_semantics() */ #define CFS_COFFEE_IO_FLASH_AWARE 0x1 /** - * Instruct Coffee not to attempt to extend the file when there is - * an attempt to write past the reserved file size. + * Instruct Coffee not to attempt to extend the file upon a request + * to write past the reserved file size. * * A case when this is necessary is when the file has a firm size limit, * and a safeguard is needed to protect against writes beyond this limit. @@ -63,6 +63,15 @@ */ #define CFS_COFFEE_IO_FIRM_SIZE 0x2 +/** + * Instruct Coffee to set unused bytes in the destination buffer to zero. + * Trailing zeros may cause a wrong file size, this option ensures that + * the corresponding bytes get set, so Coffee does not read unexpected data. + * + * \sa cfs_coffee_set_io_semantics() + */ +#define CFS_COFFEE_IO_ENSURE_READ_LENGTH 0x4 + /** * \file * Header for the Coffee file system. @@ -75,8 +84,8 @@ /** * \brief Reserve space for a file. - * \param name The filename. - * \param size The size of the file. + * \param name The file name. + * \param size The initial size to be reserved for the file. * \return 0 on success, -1 on failure. * * Coffee uses sequential page structures for files. The sequential @@ -88,15 +97,15 @@ int cfs_coffee_reserve(const char *name, cfs_offset_t size); /** * \brief Configure the on-demand log file. - * \param file The filename. - * \param log_size The total log size. + * \param file The file name. + * \param log_size The total log file size. * \param log_entry_size The log entry size. * \return 0 on success, -1 on failure. * * When file data is first modified, Coffee creates a micro log for the - * file. The micro log stores a table of modifications whose - * parameters--the log size and the log entry size--can be modified - * through the cfs_coffee_configure_log function. + * file. The micro log stores a table of modifications whose parameters -- + * the log size and the log entry size -- can be modified through the + * cfs_coffee_configure_log function. */ int cfs_coffee_configure_log(const char *file, unsigned log_size, unsigned log_entry_size); @@ -109,8 +118,8 @@ int cfs_coffee_configure_log(const char *file, unsigned log_size, * * Coffee is used on a wide range of storage types, and the default * I/O file semantics may not be optimal for the access pattern - * of a certain file. Hence, this functions allows programmers to - * switch the /O semantics on a file that is accessed through a + * of a certain file. Hence, this function allows programmers to + * switch the I/O semantics on a file that is accessed through a * particular file descriptor. * */ @@ -123,21 +132,14 @@ int cfs_coffee_set_io_semantics(int fd, unsigned flags); * Coffee formats the underlying storage by setting all bits to zero. * Formatting must be done before using Coffee for the first time in * a mote. + * + * Notice that the erased bits may be set to 1 on the physical storage + * when using flash memory. In this case, Coffee requires that the + * COFFEE_READ and COFFEE_WRITE functions used to access the flash memory + * invert all bits. */ int cfs_coffee_format(void); -/** - * \brief Points out a memory region that may not be altered during - * checkpointing operations that use the file system. - * \param size - * \return A pointer to the protected memory. - * - * This function returns the protected memory pointer and writes its size - * to the given parameter. Mainly used by sensornet checkpointing to protect - * the coffee state during CFS-based checkpointing operations. - */ -void *cfs_coffee_get_protected_mem(unsigned *size); - /** @} */ /** @} */ diff --git a/core/cfs/cfs.h b/core/cfs/cfs.h index a0426b9ff..3e2452c61 100644 --- a/core/cfs/cfs.h +++ b/core/cfs/cfs.h @@ -68,7 +68,9 @@ typedef CFS_CONF_OFFSET_TYPE cfs_offset_t; #endif struct cfs_dir { - char dummy_space[32]; + /* Iteration state, which is implementation-defined and should not be + accessed externally. */ + char state[32]; }; struct cfs_dirent { diff --git a/core/contiki-default-conf.h b/core/contiki-default-conf.h index 0083f7e10..c26a2b8df 100644 --- a/core/contiki-default-conf.h +++ b/core/contiki-default-conf.h @@ -78,13 +78,6 @@ #define NETSTACK_CONF_LLSEC nullsec_driver #endif /* NETSTACK_CONF_LLSEC */ -/* To avoid unnecessary complexity, we assume the common case of - a constant LoWPAN-wide IEEE 802.15.4 security level, which - can be specified by defining LLSEC802154_CONF_SECURITY_LEVEL. */ -#ifndef LLSEC802154_CONF_SECURITY_LEVEL -#define LLSEC802154_CONF_SECURITY_LEVEL 0 -#endif /* LLSEC802154_CONF_SECURITY_LEVEL */ - /* NETSTACK_CONF_NETWORK specifies the network layer and can be either sicslowpan_driver, for IPv6 networking, or rime_driver, for the custom Rime network stack. */ @@ -148,12 +141,32 @@ #define UIP_CONF_IPV6_RPL 1 #endif /* UIP_CONF_IPV6_RPL */ +/* If RPL is enabled also enable the RPL NBR Policy */ +#if UIP_CONF_IPV6_RPL +#ifndef NBR_TABLE_FIND_REMOVABLE +#define NBR_TABLE_FIND_REMOVABLE rpl_nbr_policy_find_removable +#endif /* NBR_TABLE_FIND_REMOVABLE */ +#endif /* UIP_CONF_IPV6_RPL */ + +/* RPL_CONF_MOP specifies the RPL mode of operation that will be + * advertised by the RPL root. Possible values: RPL_MOP_NO_DOWNWARD_ROUTES, + * RPL_MOP_NON_STORING, RPL_MOP_STORING_NO_MULTICAST, RPL_MOP_STORING_MULTICAST */ +#ifndef RPL_CONF_MOP +#define RPL_CONF_MOP RPL_MOP_STORING_NO_MULTICAST +#endif /* RPL_CONF_MOP */ + /* UIP_CONF_MAX_ROUTES specifies the maximum number of routes that each node will be able to handle. */ #ifndef UIP_CONF_MAX_ROUTES #define UIP_CONF_MAX_ROUTES 20 #endif /* UIP_CONF_MAX_ROUTES */ +/* RPL_NS_CONF_LINK_NUM specifies the maximum number of links a RPL root + * will maintain in non-storing mode. */ +#ifndef RPL_NS_CONF_LINK_NUM +#define RPL_NS_CONF_LINK_NUM 20 +#endif /* RPL_NS_CONF_LINK_NUM */ + /* UIP_CONF_UDP specifies if UDP support should be included or not. Disabling UDP saves memory but breaks a lot of stuff. */ #ifndef UIP_CONF_UDP @@ -220,14 +233,6 @@ * on the target platform, and are therefore platform-specific. */ -/* SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS specifies how many times the - MAC layer should resend packets if no link-layer ACK was - received. This only makes sense with the csma_driver - NETSTACK_CONF_MAC. */ -#ifndef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS -#define SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS 4 -#endif /* SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS */ - /* SICSLOWPAN_CONF_FRAG specifies if 6lowpan fragmentation should be used or not. Fragmentation is on by default. */ #ifndef SICSLOWPAN_CONF_FRAG diff --git a/core/lib/gcr.c b/core/lib/gcr.c index 1fba2f40b..36ee98ea2 100644 --- a/core/lib/gcr.c +++ b/core/lib/gcr.c @@ -64,13 +64,13 @@ static unsigned char gcr_bits = 0; static unsigned short gcr_val = 0; /* Call before starting encoding or decoding */ -void gcr_init() { +void gcr_init(void) { gcr_val = 0; gcr_bits = 0; } /* Use this to check if encoding / decoding is complete for now */ -unsigned char gcr_finished() { +unsigned char gcr_finished(void) { return gcr_bits == 0; } @@ -100,7 +100,7 @@ void gcr_decode(unsigned char gcr_data) { } /* check if the current decoded stream is correct */ -unsigned char gcr_valid() { +unsigned char gcr_valid(void) { if (gcr_bits >= 10) { unsigned short val = gcr_val & 0x3ff; if ((GCR_decode[val >> 5u] << 4u) == 0xff || diff --git a/core/lib/settings.h b/core/lib/settings.h index e102b8b0b..bef6d0461 100644 --- a/core/lib/settings.h +++ b/core/lib/settings.h @@ -186,7 +186,7 @@ extern settings_status_t settings_delete(settings_key_t key, uint8_t index); typedef eeprom_addr_t settings_iter_t; /** Will return \ref SETTINGS_INVALID_ITER if the settings store is empty. */ -extern settings_iter_t settings_iter_begin(); +extern settings_iter_t settings_iter_begin(void); /** Will return \ref SETTINGS_INVALID_ITER if at the end of settings list. */ extern settings_iter_t settings_iter_next(settings_iter_t iter); diff --git a/core/lib/trickle-timer.c b/core/lib/trickle-timer.c index 2b88f60ef..fd2d7c537 100644 --- a/core/lib/trickle-timer.c +++ b/core/lib/trickle-timer.c @@ -79,7 +79,7 @@ static void double_interval(void *ptr); #if TRICKLE_TIMER_WIDE_RAND /* Returns a 4-byte wide, unsigned random number */ static uint32_t -wide_rand() +wide_rand(void) { return ((uint32_t)random_rand() << 16 | random_rand()); } diff --git a/core/net/http-socket/http-socket.c b/core/net/http-socket/http-socket.c index 758c1473e..b08605213 100644 --- a/core/net/http-socket/http-socket.c +++ b/core/net/http-socket/http-socket.c @@ -324,6 +324,7 @@ parse_url(const char *url, char *host, uint16_t *portptr, char *path) if(host != NULL) { host[i] = 0; } + urlptr++; break; } if(host != NULL) { @@ -349,6 +350,11 @@ parse_url(const char *url, char *host, uint16_t *portptr, char *path) } } + /* check if host is null terminated */ + if(!memchr(host, 0, MAX_HOSTLEN)) { + return 0; + } + /* Find the port. Default is 80. */ port = 80; if(*urlptr == ':') { @@ -412,7 +418,15 @@ event(struct tcp_socket *tcps, void *ptr, tcp_socket_send_str(tcps, " HTTP/1.1\r\n"); tcp_socket_send_str(tcps, "Connection: close\r\n"); tcp_socket_send_str(tcps, "Host: "); + /* If we have IPv6 host, add the '[' and the ']' characters + to the host. As in rfc2732. */ + if(memchr(host, ':', MAX_HOSTLEN)) { + tcp_socket_send_str(tcps, "["); + } tcp_socket_send_str(tcps, host); + if(memchr(host, ':', MAX_HOSTLEN)) { + tcp_socket_send_str(tcps, "]"); + } tcp_socket_send_str(tcps, "\r\n"); if(s->postdata != NULL) { if(s->content_type) { diff --git a/core/net/ip/resolv.c b/core/net/ip/resolv.c index 0dd06104b..a0b40c32d 100644 --- a/core/net/ip/resolv.c +++ b/core/net/ip/resolv.c @@ -111,6 +111,9 @@ strcasecmp(const char *s1, const char *s2) /* TODO: Add case support! */ return strcmp(s1, s2); } +#else +int strcasecmp(const char *s1, const char *s2); +int strncasecmp(const char *s1, const char *s2, size_t n); #endif /* __SDCC */ #define UIP_UDP_BUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN]) @@ -783,9 +786,9 @@ check_entries(void) static void newdata(void) { - static uint8_t nquestions, nanswers; + uint8_t nquestions, nanswers; - static int8_t i; + int8_t i; register struct namemap *namemapptr = NULL; @@ -872,7 +875,7 @@ newdata(void) } return; } else { - static uint8_t nauthrr; + uint8_t nauthrr; PRINTF("resolver: But we are still probing. Waiting...\n"); /* We are still probing. We need to do the mDNS * probe race condition check here and make sure @@ -960,7 +963,7 @@ newdata(void) #endif /* !ARCH_DOESNT_NEED_ALIGNED_STRUCTS */ #if VERBOSE_DEBUG - static char debug_name[40]; + char debug_name[40]; decode_name(queryptr, debug_name, uip_appdata); DEBUG_PRINTF("resolver: Answer %d: \"%s\", type %d, class %d, ttl %d, length %d\n", ++i, debug_name, uip_ntohs(ans->type), @@ -1266,9 +1269,9 @@ remove_trailing_dots(const char *name) { void resolv_query(const char *name) { - static uint8_t i; + uint8_t i; - static uint8_t lseq, lseqi; + uint8_t lseq, lseqi; register struct namemap *nameptr = 0; @@ -1315,7 +1318,7 @@ resolv_query(const char *name) { size_t name_len = strlen(name); - static const char local_suffix[] = "local"; + const char local_suffix[] = "local"; if((name_len > (sizeof(local_suffix) - 1)) && (0 == strcasecmp(name + name_len - (sizeof(local_suffix) - 1), local_suffix))) { @@ -1347,7 +1350,7 @@ resolv_lookup(const char *name, uip_ipaddr_t ** ipaddr) { resolv_status_t ret = RESOLV_STATUS_UNCACHED; - static uint8_t i; + uint8_t i; struct namemap *nameptr; diff --git a/core/net/ip/simple-udp.c b/core/net/ip/simple-udp.c index 8ecd0aaa1..692fea19a 100644 --- a/core/net/ip/simple-udp.c +++ b/core/net/ip/simple-udp.c @@ -119,7 +119,7 @@ simple_udp_register(struct simple_udp_connection *c, PROCESS_CONTEXT_BEGIN(&simple_udp_process); c->udp_conn = udp_new(remote_addr, UIP_HTONS(remote_port), c); - if(c->udp_conn != NULL) { + if(c->udp_conn != NULL && local_port) { udp_bind(c->udp_conn, UIP_HTONS(local_port)); } PROCESS_CONTEXT_END(); diff --git a/core/net/ip/tcpip.c b/core/net/ip/tcpip.c index 00607ba14..df3f0608d 100644 --- a/core/net/ip/tcpip.c +++ b/core/net/ip/tcpip.c @@ -47,6 +47,11 @@ #include "net/ipv6/uip-ds6.h" #endif +#if UIP_CONF_IPV6_RPL +#include "net/rpl/rpl.h" +#include "net/rpl/rpl-private.h" +#endif + #include #define DEBUG DEBUG_NONE @@ -219,7 +224,7 @@ struct uip_conn * tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate) { struct uip_conn *c; - + c = uip_connect(ripaddr, port); if(c == NULL) { return NULL; @@ -227,9 +232,9 @@ tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate) c->appstate.p = PROCESS_CURRENT(); c->appstate.state = appstate; - + tcpip_poll_tcp(c); - + return c; } #endif /* UIP_ACTIVE_OPEN */ @@ -237,7 +242,7 @@ tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate) void tcp_unlisten(uint16_t port) { - static unsigned char i; + unsigned char i; struct listenport *l; l = s.listenports; @@ -255,7 +260,7 @@ tcp_unlisten(uint16_t port) void tcp_listen(uint16_t port) { - static unsigned char i; + unsigned char i; struct listenport *l; l = s.listenports; @@ -300,7 +305,7 @@ udp_new(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate) { struct uip_udp_conn *c; uip_udp_appstate_t *s; - + c = uip_udp_new(ripaddr, port); if(c == NULL) { return NULL; @@ -359,157 +364,157 @@ static void eventhandler(process_event_t ev, process_data_t data) { #if UIP_TCP - static unsigned char i; + unsigned char i; register struct listenport *l; #endif /*UIP_TCP*/ struct process *p; switch(ev) { - case PROCESS_EVENT_EXITED: - /* This is the event we get if a process has exited. We go through + case PROCESS_EVENT_EXITED: + /* This is the event we get if a process has exited. We go through the TCP/IP tables to see if this process had any open connections or listening TCP ports. If so, we'll close those connections. */ - p = (struct process *)data; + p = (struct process *)data; #if UIP_TCP - l = s.listenports; - for(i = 0; i < UIP_LISTENPORTS; ++i) { - if(l->p == p) { - uip_unlisten(l->port); - l->port = 0; - l->p = PROCESS_NONE; - } - ++l; + l = s.listenports; + for(i = 0; i < UIP_LISTENPORTS; ++i) { + if(l->p == p) { + uip_unlisten(l->port); + l->port = 0; + l->p = PROCESS_NONE; } - - { - struct uip_conn *cptr; - - for(cptr = &uip_conns[0]; cptr < &uip_conns[UIP_CONNS]; ++cptr) { - if(cptr->appstate.p == p) { - cptr->appstate.p = PROCESS_NONE; - cptr->tcpstateflags = UIP_CLOSED; - } + ++l; + } + + { + struct uip_conn *cptr; + + for(cptr = &uip_conns[0]; cptr < &uip_conns[UIP_CONNS]; ++cptr) { + if(cptr->appstate.p == p) { + cptr->appstate.p = PROCESS_NONE; + cptr->tcpstateflags = UIP_CLOSED; } } + } #endif /* UIP_TCP */ #if UIP_UDP - { - struct uip_udp_conn *cptr; + { + struct uip_udp_conn *cptr; - for(cptr = &uip_udp_conns[0]; - cptr < &uip_udp_conns[UIP_UDP_CONNS]; ++cptr) { - if(cptr->appstate.p == p) { - cptr->lport = 0; - } + for(cptr = &uip_udp_conns[0]; + cptr < &uip_udp_conns[UIP_UDP_CONNS]; ++cptr) { + if(cptr->appstate.p == p) { + cptr->lport = 0; } } + } #endif /* UIP_UDP */ - break; + break; - case PROCESS_EVENT_TIMER: - /* We get this event if one of our timers have expired. */ - { - /* Check the clock so see if we should call the periodic uIP + case PROCESS_EVENT_TIMER: + /* We get this event if one of our timers have expired. */ + { + /* Check the clock so see if we should call the periodic uIP processing. */ - if(data == &periodic && - etimer_expired(&periodic)) { + if(data == &periodic && + etimer_expired(&periodic)) { #if UIP_TCP - for(i = 0; i < UIP_CONNS; ++i) { - if(uip_conn_active(i)) { - /* Only restart the timer if there are active + for(i = 0; i < UIP_CONNS; ++i) { + if(uip_conn_active(i)) { + /* Only restart the timer if there are active connections. */ - etimer_restart(&periodic); - uip_periodic(i); + etimer_restart(&periodic); + uip_periodic(i); #if NETSTACK_CONF_WITH_IPV6 - tcpip_ipv6_output(); + tcpip_ipv6_output(); #else - if(uip_len > 0) { - PRINTF("tcpip_output from periodic len %d\n", uip_len); - tcpip_output(); - PRINTF("tcpip_output after periodic len %d\n", uip_len); - } -#endif /* NETSTACK_CONF_WITH_IPV6 */ - } + if(uip_len > 0) { + PRINTF("tcpip_output from periodic len %d\n", uip_len); + tcpip_output(); + PRINTF("tcpip_output after periodic len %d\n", uip_len); } +#endif /* NETSTACK_CONF_WITH_IPV6 */ + } + } #endif /* UIP_TCP */ #if UIP_CONF_IP_FORWARD - uip_fw_periodic(); + uip_fw_periodic(); #endif /* UIP_CONF_IP_FORWARD */ - } - + } + #if NETSTACK_CONF_WITH_IPV6 #if UIP_CONF_IPV6_REASSEMBLY - /* - * check the timer for reassembly - */ - if(data == &uip_reass_timer && - etimer_expired(&uip_reass_timer)) { - uip_reass_over(); - tcpip_ipv6_output(); - } + /* + * check the timer for reassembly + */ + if(data == &uip_reass_timer && + etimer_expired(&uip_reass_timer)) { + uip_reass_over(); + tcpip_ipv6_output(); + } #endif /* UIP_CONF_IPV6_REASSEMBLY */ - /* - * check the different timers for neighbor discovery and - * stateless autoconfiguration - */ - /*if(data == &uip_ds6_timer_periodic && + /* + * check the different timers for neighbor discovery and + * stateless autoconfiguration + */ + /*if(data == &uip_ds6_timer_periodic && etimer_expired(&uip_ds6_timer_periodic)) { uip_ds6_periodic(); tcpip_ipv6_output(); }*/ #if !UIP_CONF_ROUTER - if(data == &uip_ds6_timer_rs && - etimer_expired(&uip_ds6_timer_rs)) { - uip_ds6_send_rs(); - tcpip_ipv6_output(); - } + if(data == &uip_ds6_timer_rs && + etimer_expired(&uip_ds6_timer_rs)) { + uip_ds6_send_rs(); + tcpip_ipv6_output(); + } #endif /* !UIP_CONF_ROUTER */ - if(data == &uip_ds6_timer_periodic && - etimer_expired(&uip_ds6_timer_periodic)) { - uip_ds6_periodic(); - tcpip_ipv6_output(); - } + if(data == &uip_ds6_timer_periodic && + etimer_expired(&uip_ds6_timer_periodic)) { + uip_ds6_periodic(); + tcpip_ipv6_output(); + } #endif /* NETSTACK_CONF_WITH_IPV6 */ - } - break; - + } + break; + #if UIP_TCP - case TCP_POLL: - if(data != NULL) { - uip_poll_conn(data); + case TCP_POLL: + if(data != NULL) { + uip_poll_conn(data); #if NETSTACK_CONF_WITH_IPV6 - tcpip_ipv6_output(); + tcpip_ipv6_output(); #else /* NETSTACK_CONF_WITH_IPV6 */ - if(uip_len > 0) { - PRINTF("tcpip_output from tcp poll len %d\n", uip_len); - tcpip_output(); - } -#endif /* NETSTACK_CONF_WITH_IPV6 */ - /* Start the periodic polling, if it isn't already active. */ - start_periodic_tcp_timer(); + if(uip_len > 0) { + PRINTF("tcpip_output from tcp poll len %d\n", uip_len); + tcpip_output(); } - break; +#endif /* NETSTACK_CONF_WITH_IPV6 */ + /* Start the periodic polling, if it isn't already active. */ + start_periodic_tcp_timer(); + } + break; #endif /* UIP_TCP */ #if UIP_UDP - case UDP_POLL: - if(data != NULL) { - uip_udp_periodic_conn(data); + case UDP_POLL: + if(data != NULL) { + uip_udp_periodic_conn(data); #if NETSTACK_CONF_WITH_IPV6 - tcpip_ipv6_output(); + tcpip_ipv6_output(); #else - if(uip_len > 0) { - tcpip_output(); - } -#endif /* UIP_UDP */ + if(uip_len > 0) { + tcpip_output(); } - break; +#endif /* UIP_UDP */ + } + break; #endif /* UIP_UDP */ - case PACKET_INPUT: - packet_input(); - break; + case PACKET_INPUT: + packet_input(); + break; }; } /*---------------------------------------------------------------------------*/ @@ -525,7 +530,7 @@ void tcpip_ipv6_output(void) { uip_ds6_nbr_t *nbr = NULL; - uip_ipaddr_t *nexthop; + uip_ipaddr_t *nexthop = NULL; if(uip_len == 0) { return; @@ -545,14 +550,25 @@ tcpip_ipv6_output(void) if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { /* Next hop determination */ + +#if UIP_CONF_IPV6_RPL && RPL_WITH_NON_STORING + uip_ipaddr_t ipaddr; + /* Look for a RPL Source Route */ + if(rpl_srh_get_next_hop(&ipaddr)) { + nexthop = &ipaddr; + } +#endif /* UIP_CONF_IPV6_RPL && RPL_WITH_NON_STORING */ + nbr = NULL; /* We first check if the destination address is on our immediate link. If so, we simply use the destination address as our nexthop address. */ - if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){ + if(nexthop == NULL && uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){ nexthop = &UIP_IP_BUF->destipaddr; - } else { + } + + if(nexthop == NULL) { uip_ds6_route_t *route; /* Check if we have a route to the destination address. */ route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); @@ -563,25 +579,25 @@ tcpip_ipv6_output(void) nexthop = uip_ds6_defrt_choose(); if(nexthop == NULL) { #ifdef UIP_FALLBACK_INTERFACE - PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n", - uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40)); - if(uip_ext_len > 0) { - extern void remove_ext_hdr(void); - uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40); - remove_ext_hdr(); - /* This should be copied from the ext header... */ - UIP_IP_BUF->proto = proto; - } - /* Inform the other end that the destination is not reachable. If it's - * not informed routes might get lost unexpectedly until there's a need - * to send a new packet to the peer */ - if(UIP_FALLBACK_INTERFACE.output() < 0) { - PRINTF("FALLBACK: output error. Reporting DST UNREACH\n"); - uip_icmp6_error_output(ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 0); - uip_flags = 0; - tcpip_ipv6_output(); - return; - } + PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n", + uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40)); + if(uip_ext_len > 0) { + extern void remove_ext_hdr(void); + uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40); + remove_ext_hdr(); + /* This should be copied from the ext header... */ + UIP_IP_BUF->proto = proto; + } + /* Inform the other end that the destination is not reachable. If it's + * not informed routes might get lost unexpectedly until there's a need + * to send a new packet to the peer */ + if(UIP_FALLBACK_INTERFACE.output() < 0) { + PRINTF("FALLBACK: output error. Reporting DST UNREACH\n"); + uip_icmp6_error_output(ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 0); + uip_flags = 0; + tcpip_ipv6_output(); + return; + } #else PRINTF("tcpip_ipv6_output: Destination off-link but no route\n"); #endif /* !UIP_FALLBACK_INTERFACE */ @@ -636,7 +652,7 @@ tcpip_ipv6_output(void) /* End of next hop determination */ #if UIP_CONF_IPV6_RPL - if(rpl_update_header_final(nexthop)) { + if(!rpl_finalize_header(nexthop)) { uip_clear_buf(); return; } @@ -644,8 +660,9 @@ tcpip_ipv6_output(void) nbr = uip_ds6_nbr_lookup(nexthop); if(nbr == NULL) { #if UIP_ND6_SEND_NA - if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { + if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE, NBR_TABLE_REASON_IPV6_ND, NULL)) == NULL) { uip_clear_buf(); + PRINTF("tcpip_ipv6_output: failed to add neighbor to cache\n"); return; } else { #if UIP_CONF_IPV6_QUEUE_PKT @@ -655,13 +672,13 @@ tcpip_ipv6_output(void) uip_packetqueue_set_buflen(&nbr->packethandle, uip_len); } #endif - /* RFC4861, 7.2.2: - * "If the source address of the packet prompting the solicitation is the - * same as one of the addresses assigned to the outgoing interface, that - * address SHOULD be placed in the IP Source Address of the outgoing - * solicitation. Otherwise, any one of the addresses assigned to the - * interface should be used."*/ - if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){ + /* RFC4861, 7.2.2: + * "If the source address of the packet prompting the solicitation is the + * same as one of the addresses assigned to the outgoing interface, that + * address SHOULD be placed in the IP Source Address of the outgoing + * solicitation. Otherwise, any one of the addresses assigned to the + * interface should be used."*/ + if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){ uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr); } else { uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr); @@ -672,6 +689,7 @@ tcpip_ipv6_output(void) /* Send the first NS try from here (multicast destination IP address). */ } #else /* UIP_ND6_SEND_NA */ + PRINTF("tcpip_ipv6_output: neighbor not in cache\n"); uip_len = 0; return; #endif /* UIP_ND6_SEND_NA */ @@ -747,7 +765,7 @@ void tcpip_uipcall(void) { uip_udp_appstate_t *ts; - + #if UIP_UDP if(uip_conn != NULL) { ts = &uip_conn->appstate; @@ -759,30 +777,30 @@ tcpip_uipcall(void) #endif /* UIP_UDP */ #if UIP_TCP - { - static unsigned char i; - struct listenport *l; - - /* If this is a connection request for a listening port, we must + { + unsigned char i; + struct listenport *l; + + /* If this is a connection request for a listening port, we must mark the connection with the right process ID. */ - if(uip_connected()) { - l = &s.listenports[0]; - for(i = 0; i < UIP_LISTENPORTS; ++i) { - if(l->port == uip_conn->lport && - l->p != PROCESS_NONE) { - ts->p = l->p; - ts->state = NULL; - break; - } - ++l; - } - - /* Start the periodic polling, if it isn't already active. */ - start_periodic_tcp_timer(); - } - } + if(uip_connected()) { + l = &s.listenports[0]; + for(i = 0; i < UIP_LISTENPORTS; ++i) { + if(l->port == uip_conn->lport && + l->p != PROCESS_NONE) { + ts->p = l->p; + ts->state = NULL; + break; + } + ++l; + } + + /* Start the periodic polling, if it isn't already active. */ + start_periodic_tcp_timer(); + } + } #endif /* UIP_TCP */ - + if(ts->p != NULL) { process_post_synch(ts->p, tcpip_event, ts->state); } @@ -791,16 +809,16 @@ tcpip_uipcall(void) PROCESS_THREAD(tcpip_process, ev, data) { PROCESS_BEGIN(); - + #if UIP_TCP - { - static unsigned char i; - - for(i = 0; i < UIP_LISTENPORTS; ++i) { - s.listenports[i].port = 0; - } - s.p = PROCESS_CURRENT(); - } + { + unsigned char i; + + for(i = 0; i < UIP_LISTENPORTS; ++i) { + s.listenports[i].port = 0; + } + s.p = PROCESS_CURRENT(); + } #endif tcpip_event = process_alloc_event(); @@ -813,7 +831,7 @@ PROCESS_THREAD(tcpip_process, ev, data) #ifdef UIP_FALLBACK_INTERFACE UIP_FALLBACK_INTERFACE.init(); #endif -/* initialize RPL if configured for using RPL */ + /* initialize RPL if configured for using RPL */ #if NETSTACK_CONF_WITH_IPV6 && UIP_CONF_IPV6_RPL rpl_init(); #endif /* UIP_CONF_IPV6_RPL */ @@ -822,7 +840,7 @@ PROCESS_THREAD(tcpip_process, ev, data) PROCESS_YIELD(); eventhandler(ev, data); } - + PROCESS_END(); } /*---------------------------------------------------------------------------*/ diff --git a/core/net/ip/uip-debug.c b/core/net/ip/uip-debug.c index ab3ba0765..7804ba4db 100644 --- a/core/net/ip/uip-debug.c +++ b/core/net/ip/uip-debug.c @@ -30,7 +30,7 @@ /** * \file - * A set of debugging tools + * A set of debugging tools for the IP stack * \author * Nicolas Tsiftes * Niclas Finne @@ -92,19 +92,3 @@ uip_debug_ipaddr_print(const uip_ipaddr_t *addr) #endif /* NETSTACK_CONF_WITH_IPV6 */ } /*---------------------------------------------------------------------------*/ -void -uip_debug_lladdr_print(const uip_lladdr_t *addr) -{ - unsigned int i; - if(addr == NULL) { - PRINTA("(NULL LL addr)"); - return; - } - for(i = 0; i < sizeof(uip_lladdr_t); i++) { - if(i > 0) { - PRINTA(":"); - } - PRINTA("%02x", addr->addr[i]); - } -} -/*---------------------------------------------------------------------------*/ diff --git a/core/net/ip/uip-debug.h b/core/net/ip/uip-debug.h index 6ffc1e638..d8e238fe4 100644 --- a/core/net/ip/uip-debug.h +++ b/core/net/ip/uip-debug.h @@ -31,57 +31,27 @@ */ /** * \file - * A set of debugging macros. + * A set of debugging macros for the IP stack * * \author Nicolas Tsiftes * Niclas Finne * Joakim Eriksson + * Simon Duquennoy */ #ifndef UIP_DEBUG_H #define UIP_DEBUG_H +#include "net/net-debug.h" #include "net/ip/uip.h" #include void uip_debug_ipaddr_print(const uip_ipaddr_t *addr); -void uip_debug_lladdr_print(const uip_lladdr_t *addr); - -#define DEBUG_NONE 0 -#define DEBUG_PRINT 1 -#define DEBUG_ANNOTATE 2 -#define DEBUG_FULL DEBUG_ANNOTATE | DEBUG_PRINT - -/* PRINTA will always print if the debug routines are called directly */ -#ifdef __AVR__ -#include -#define PRINTA(FORMAT,args...) printf_P(PSTR(FORMAT),##args) -#else -#define PRINTA(...) printf(__VA_ARGS__) -#endif - -#if (DEBUG) & DEBUG_ANNOTATE -#ifdef __AVR__ -#define ANNOTATE(FORMAT,args...) printf_P(PSTR(FORMAT),##args) -#else -#define ANNOTATE(...) printf(__VA_ARGS__) -#endif -#else -#define ANNOTATE(...) -#endif /* (DEBUG) & DEBUG_ANNOTATE */ #if (DEBUG) & DEBUG_PRINT -#ifdef __AVR__ -#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args) -#else -#define PRINTF(...) printf(__VA_ARGS__) -#endif #define PRINT6ADDR(addr) uip_debug_ipaddr_print(addr) -#define PRINTLLADDR(lladdr) uip_debug_lladdr_print(lladdr) #else -#define PRINTF(...) #define PRINT6ADDR(addr) -#define PRINTLLADDR(lladdr) #endif /* (DEBUG) & DEBUG_PRINT */ -#endif +#endif /* UIP_DEBUG_H */ diff --git a/core/net/ip/uip-udp-packet.c b/core/net/ip/uip-udp-packet.c index 923661709..aa86435f9 100644 --- a/core/net/ip/uip-udp-packet.c +++ b/core/net/ip/uip-udp-packet.c @@ -51,15 +51,13 @@ void uip_udp_packet_send(struct uip_udp_conn *c, const void *data, int len) { #if UIP_UDP - if(data != NULL) { + if(data != NULL && len <= (UIP_BUFSIZE - (UIP_LLH_LEN + UIP_IPUDPH_LEN))) { uip_udp_conn = c; uip_slen = len; - memmove(&uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], data, - len > UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN? - UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN: len); + memmove(&uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], data, len); uip_process(UIP_UDP_SEND_CONN); -#if UIP_CONF_IPV6_MULTICAST +#if UIP_IPV6_MULTICAST /* Let the multicast engine process the datagram before we send it */ if(uip_is_addr_mcast_routable(&uip_udp_conn->ripaddr)) { UIP_MCAST6.out(); diff --git a/core/net/ip/uip.h b/core/net/ip/uip.h index 900bd45fb..12d77ff10 100644 --- a/core/net/ip/uip.h +++ b/core/net/ip/uip.h @@ -1801,6 +1801,13 @@ typedef struct uip_routing_hdr { uint8_t seg_left; } uip_routing_hdr; +/* RPL Source Routing Header */ +typedef struct uip_rpl_srh_hdr { + uint8_t cmpr; /* CmprI and CmprE */ + uint8_t pad; + uint8_t reserved[2]; +} uip_rpl_srh_hdr; + /* fragmentation header */ typedef struct uip_frag_hdr { uint8_t next; diff --git a/core/net/ipv6/multicast/README.md b/core/net/ipv6/multicast/README.md index 2108b92f2..7a33fca0f 100644 --- a/core/net/ipv6/multicast/README.md +++ b/core/net/ipv6/multicast/README.md @@ -98,7 +98,7 @@ In order to extend multicast with a new engine, perform the following steps: - Open `uip-mcast6.h` and add a section in the `#if` spree. This aims to configure the uIPv6 core. More specifically, you need to: * Specify if you want to put RPL in MOP3 by defining - `RPL_CONF_MULTICAST`: 1: MOP 3, 0: non-multicast MOP + `RPL_WITH_MULTICAST`: 1: MOP 3, 0: non-multicast MOP * Define your engine details #define UIP_MCAST6 foo_driver diff --git a/core/net/ipv6/multicast/esmrf.c b/core/net/ipv6/multicast/esmrf.c new file mode 100644 index 000000000..284853a9c --- /dev/null +++ b/core/net/ipv6/multicast/esmrf.c @@ -0,0 +1,406 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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 + * This file shows the implementations of the Enhanced Stateless + * Multicast RPL Forwarding (ESMRF) + * + * It will only work in RPL networks in MOP 3 "Storing with Multicast" + * + * \author + * Khaled Qorany kqorany2@gmail.com + */ + +#include "contiki.h" +#include "contiki-net.h" +#include "net/ipv6/multicast/uip-mcast6.h" +#include "net/ipv6/multicast/uip-mcast6-route.h" +#include "net/ipv6/multicast/uip-mcast6-stats.h" +#include "net/ipv6/multicast/esmrf.h" +#include "net/rpl/rpl.h" +#include "net/ip/uip.h" +#include "net/netstack.h" +#include + +extern uint16_t uip_slen; + +#define DEBUG NONE +#include "net/ip/uip-debug.h" + +#define ESMRF_VERBOSE NONE + +#if DEBUG && ESMRF_VERBOSE +#define VERBOSE_PRINTF(...) PRINTF(__VA_ARGS__) +#define VERBOSE_PRINT_SEED(s) PRINT_SEED(s) +#else +#define VERBOSE_PRINTF(...) +#define VERBOSE_PRINT_SEED(...) +#endif + +/*---------------------------------------------------------------------------*/ +/* Maintain Stats */ +#if UIP_MCAST6_STATS +static struct esmrf_stats stats; + +#define ESMRF_STATS_ADD(x) stats.x++ +#define ESMRF_STATS_INIT() do { memset(&stats, 0, sizeof(stats)); } while(0) +#else /* UIP_MCAST6_STATS */ +#define ESMRF_STATS_ADD(x) +#define ESMRF_STATS_INIT() +#endif +/*---------------------------------------------------------------------------*/ +/* Macros */ +/*---------------------------------------------------------------------------*/ +/* CCI */ +#define ESMRF_FWD_DELAY() NETSTACK_RDC.channel_check_interval() +/* Number of slots in the next 500ms */ +#define ESMRF_INTERVAL_COUNT ((CLOCK_SECOND >> 2) / fwd_delay) +/*---------------------------------------------------------------------------*/ +/* Internal Data */ +/*---------------------------------------------------------------------------*/ +static struct ctimer mcast_periodic; +static uint8_t mcast_len; +static uip_buf_t mcast_buf; +static uint8_t fwd_delay; +static uint8_t fwd_spread; +static struct uip_udp_conn *c; +static uip_ipaddr_t src_ip; +static uip_ipaddr_t des_ip; +/*---------------------------------------------------------------------------*/ +/* uIPv6 Pointers */ +/*---------------------------------------------------------------------------*/ +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) +#define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#define UIP_ICMP_PAYLOAD ((unsigned char *)&uip_buf[uip_l2_l3_icmp_hdr_len]) +#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN]) +/*---------------------------------------------------------------------------*/ +/* Local function prototypes */ +/*---------------------------------------------------------------------------*/ +static void icmp_input(void); +static void icmp_output(void); +static void mcast_fwd(void *p); +int remove_ext_hdr(void); +/*---------------------------------------------------------------------------*/ +/* Internal Data Structures */ +/*---------------------------------------------------------------------------*/ +struct multicast_on_behalf{ /* ICMP message of multicast_on_behalf */ + uint16_t mcast_port; + uip_ipaddr_t mcast_ip; + uint8_t mcast_payload[UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN]; +}; +#define UIP_ICMP_MOB 18 /* Size of multicast_on_behalf ICMP header */ +/*---------------------------------------------------------------------------*/ +/* Temporary Stores */ +/*---------------------------------------------------------------------------*/ +static struct multicast_on_behalf *locmobptr; +static int loclen; +/*---------------------------------------------------------------------------*/ +/* ESMRF ICMPv6 handler declaration */ +UIP_ICMP6_HANDLER(esmrf_icmp_handler, ICMP6_ESMRF, + UIP_ICMP6_HANDLER_CODE_ANY, icmp_input); +/*---------------------------------------------------------------------------*/ +static void +icmp_output() +{ + uint16_t payload_len=0; + rpl_dag_t *dag_t; + + struct multicast_on_behalf *mob; + mob = (struct multicast_on_behalf *)UIP_ICMP_PAYLOAD; + memcpy(&mob->mcast_payload, &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], uip_slen); + + UIP_IP_BUF->vtc = 0x60; + UIP_IP_BUF->tcflow = 0; + UIP_IP_BUF->flow = 0; + UIP_IP_BUF->proto = UIP_PROTO_ICMP6; + UIP_IP_BUF->ttl = ESMRF_IP_HOP_LIMIT; + + mob->mcast_port = (uint16_t) uip_udp_conn->rport; + uip_ipaddr_copy(&mob->mcast_ip, &UIP_IP_BUF->destipaddr); + + payload_len = UIP_ICMP_MOB + uip_slen; + + dag_t = rpl_get_any_dag(); + uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &dag_t->dag_id); + uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr); + + VERBOSE_PRINTF("ESMRF: ICMPv6 Out - Hdr @ %p, payload @ %p to: ", UIP_ICMP_BUF, mob); + PRINT6ADDR(&UIP_IP_BUF->destipaddr); + PRINTF("\n"); + + UIP_IP_BUF->len[0] = (UIP_ICMPH_LEN + payload_len) >> 8; + UIP_IP_BUF->len[1] = (UIP_ICMPH_LEN + payload_len) & 0xff; + + UIP_ICMP_BUF->type = ICMP6_ESMRF; + UIP_ICMP_BUF->icode = ESMRF_ICMP_CODE; + + UIP_ICMP_BUF->icmpchksum = 0; + UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); + + uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + payload_len; + + VERBOSE_PRINTF("ESMRF: ICMPv6 Out - %u bytes, uip_len %u bytes, uip_ext_len %u bytes\n", + payload_len, uip_len, uip_ext_len); + + tcpip_ipv6_output(); + ESMRF_STATS_ADD(icmp_out); + return; +} +/*---------------------------------------------------------------------------*/ +static void +icmp_input() +{ +#if UIP_CONF_IPV6_CHECKS + if(UIP_ICMP_BUF->icode != ESMRF_ICMP_CODE) { + PRINTF("ESMRF: ICMPv6 In, bad ICMP code\n"); + ESMRF_STATS_ADD(icmp_bad); + return; + } + if(UIP_IP_BUF->ttl <= 1) { + PRINTF("ESMRF: ICMPv6 In, bad TTL\n"); + ESMRF_STATS_ADD(icmp_bad); + return; + } +#endif + + remove_ext_hdr(); + + PRINTF("ESMRF: ICMPv6 In from "); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF(" len %u, ext %u\n", uip_len, uip_ext_len); + + ESMRF_STATS_ADD(icmp_in); + + VERBOSE_PRINTF("ESMRF: ICMPv6 In, parse from %p to %p\n", + UIP_ICMP_PAYLOAD, + (uint8_t *)UIP_ICMP_PAYLOAD + uip_len - + uip_l2_l3_icmp_hdr_len); + + + locmobptr = (struct multicast_on_behalf *) UIP_ICMP_PAYLOAD; + loclen = uip_len - (uip_l2_l3_icmp_hdr_len + UIP_ICMP_MOB); + + uip_ipaddr_copy(&src_ip, &UIP_IP_BUF->srcipaddr); + uip_ipaddr_copy(&des_ip, &UIP_IP_BUF->destipaddr); + + /* Extract the original multicast message */ + uip_ipaddr_copy(&c->ripaddr, &locmobptr->mcast_ip); + c->rport = locmobptr->mcast_port; + uip_slen = loclen; + uip_udp_conn=c; + memcpy(&uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], locmobptr->mcast_payload, + loclen > UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN? + UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN: loclen); + + uip_process(UIP_UDP_SEND_CONN); + + memcpy(&mcast_buf, uip_buf, uip_len); + mcast_len = uip_len; + /* pass the packet to our uip_process to check if it is allowed to + * accept this packet or not */ + uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &src_ip); + uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &des_ip); + UIP_UDP_BUF->udpchksum = 0; + + uip_process(UIP_DATA); + + memcpy(uip_buf, &mcast_buf, mcast_len); + uip_len = mcast_len; + /* Return the IP of the original Multicast sender */ + uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &src_ip); + UIP_UDP_BUF->udpchksum = 0; + /* If we have an entry in the multicast routing table, something with + * a higher RPL rank (somewhere down the tree) is a group member */ + if(uip_mcast6_route_lookup(&UIP_IP_BUF->destipaddr)) { + PRINTF("ESMRF: Forward this packet\n"); + /* If we enter here, we will definitely forward */ + tcpip_ipv6_output(); + } + uip_clear_buf(); +} +/*---------------------------------------------------------------------------*/ +static void +mcast_fwd(void *p) +{ + memcpy(uip_buf, &mcast_buf, mcast_len); + uip_len = mcast_len; + UIP_IP_BUF->ttl--; + tcpip_output(NULL); + uip_clear_buf(); +} +/*---------------------------------------------------------------------------*/ +static uint8_t +in() +{ + rpl_dag_t *d; /* Our DODAG */ + uip_ipaddr_t *parent_ipaddr; /* Our pref. parent's IPv6 address */ + const uip_lladdr_t *parent_lladdr; /* Our pref. parent's LL address */ + + /* + * Fetch a pointer to the LL address of our preferred parent + * + * ToDo: This rpl_get_any_dag() call is a dirty replacement of the previous + * rpl_get_dag(RPL_DEFAULT_INSTANCE); + * so that things can compile with the new RPL code. This needs updated to + * read instance ID from the RPL HBHO and use the correct parent accordingly + */ + d = rpl_get_any_dag(); + if(!d) { + PRINTF("ESMRF: No DODAG\n"); + UIP_MCAST6_STATS_ADD(mcast_dropped); + return UIP_MCAST6_DROP; + } + + /* Retrieve our preferred parent's LL address */ + parent_ipaddr = rpl_get_parent_ipaddr(d->preferred_parent); + parent_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(parent_ipaddr); + + if(parent_lladdr == NULL) { + PRINTF("ESMRF: NO Parent exist \n"); + UIP_MCAST6_STATS_ADD(mcast_dropped); + return UIP_MCAST6_DROP; + } + + /* + * We accept a datagram if it arrived from our preferred parent, discard + * otherwise. + */ + if(memcmp(parent_lladdr, packetbuf_addr(PACKETBUF_ADDR_SENDER), + UIP_LLADDR_LEN)) { + PRINTF("ESMRF: Routable in but ESMRF ignored it\n"); + UIP_MCAST6_STATS_ADD(mcast_dropped); + return UIP_MCAST6_DROP; + } + + if(UIP_IP_BUF->ttl <= 1) { + UIP_MCAST6_STATS_ADD(mcast_dropped); + return UIP_MCAST6_DROP; + } + + UIP_MCAST6_STATS_ADD(mcast_in_all); + UIP_MCAST6_STATS_ADD(mcast_in_unique); + + /* If we have an entry in the mcast routing table, something with + * a higher RPL rank (somewhere down the tree) is a group member */ + if(uip_mcast6_route_lookup(&UIP_IP_BUF->destipaddr)) { + /* If we enter here, we will definitely forward */ + UIP_MCAST6_STATS_ADD(mcast_fwd); + + /* + * Add a delay (D) of at least ESMRF_FWD_DELAY() to compensate for how + * contikimac handles broadcasts. We can't start our TX before the sender + * has finished its own. + */ + fwd_delay = ESMRF_FWD_DELAY(); + + /* Finalise D: D = min(ESMRF_FWD_DELAY(), ESMRF_MIN_FWD_DELAY) */ +#if ESMRF_MIN_FWD_DELAY + if(fwd_delay < ESMRF_MIN_FWD_DELAY) { + fwd_delay = ESMRF_MIN_FWD_DELAY; + } +#endif + + if(fwd_delay == 0) { + /* No delay required, send it, do it now, why wait? */ + UIP_IP_BUF->ttl--; + tcpip_output(NULL); + UIP_IP_BUF->ttl++; /* Restore before potential upstack delivery */ + } else { + /* Randomise final delay in [D , D*Spread], step D */ + fwd_spread = ESMRF_INTERVAL_COUNT; + if(fwd_spread > ESMRF_MAX_SPREAD) { + fwd_spread = ESMRF_MAX_SPREAD; + } + if(fwd_spread) { + fwd_delay = fwd_delay * (1 + ((random_rand() >> 11) % fwd_spread)); + } + + memcpy(&mcast_buf, uip_buf, uip_len); + mcast_len = uip_len; + ctimer_set(&mcast_periodic, fwd_delay, mcast_fwd, NULL); + } + PRINTF("ESMRF: %u bytes: fwd in %u [%u]\n", + uip_len, fwd_delay, fwd_spread); + } + + /* Done with this packet unless we are a member of the mcast group */ + if(!uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) { + PRINTF("ESMRF: Not a group member. No further processing\n"); + return UIP_MCAST6_DROP; + } else { + PRINTF("ESMRF: Ours. Deliver to upper layers\n"); + UIP_MCAST6_STATS_ADD(mcast_in_ours); + return UIP_MCAST6_ACCEPT; + } +} +/*---------------------------------------------------------------------------*/ +static void +init() +{ + UIP_MCAST6_STATS_INIT(NULL); + uip_mcast6_route_init(); + /* Register the ICMPv6 input handler */ + uip_icmp6_register_input_handler(&esmrf_icmp_handler); + c = udp_new(NULL, 0, NULL); +} +/*---------------------------------------------------------------------------*/ +static void +out(void) +{ + rpl_dag_t *dag_t; + dag_t = rpl_get_any_dag(); + if (!dag_t){ + PRINTF("ESMRF: There is no DODAG\n"); + return; + } + if(dag_t->rank == 256){ + PRINTF("ESMRF: I am the Root, thus send the multicast packet normally. \n"); + return; + } + else{ + PRINTF("ESMRF: I am not the Root\n"); + PRINTF("Send multicast-on-befalf message (ICMPv6) instead to "); + PRINT6ADDR(&dag_t->dag_id); + PRINTF("\n"); + icmp_output(); + uip_slen=0; + return; + } +} +/*---------------------------------------------------------------------------*/ +const struct uip_mcast6_driver esmrf_driver = { + "ESMRF", + init, + out, + in, +}; +/*---------------------------------------------------------------------------*/ diff --git a/core/net/ipv6/multicast/esmrf.h b/core/net/ipv6/multicast/esmrf.h new file mode 100644 index 000000000..4a12a38cf --- /dev/null +++ b/core/net/ipv6/multicast/esmrf.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2011, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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 + * Header file for the Enhanced Stateless Multicast RPL Forwarding (ESMRF) + * + * \author + * Khaled Qorany kqorany2@gmail.com + */ + +#ifndef ESMRF_H_ +#define ESMRF_H_ + +#include "contiki-conf.h" + +#include +/*---------------------------------------------------------------------------*/ +/* Protocol Constants */ +/*---------------------------------------------------------------------------*/ +#define ESMRF_ICMP_CODE 0 /* ICMPv6 code field */ +#define ESMRF_IP_HOP_LIMIT 0xFF /* Hop limit for ICMP messages */ +/*---------------------------------------------------------------------------*/ +/* Configuration */ +/*---------------------------------------------------------------------------*/ +/* Fmin */ +#ifdef ESMRF_CONF_MIN_FWD_DELAY +#define ESMRF_MIN_FWD_DELAY ESMRF_CONF_MIN_FWD_DELAY +#else +#define ESMRF_MIN_FWD_DELAY 4 +#endif + +/* Max Spread */ +#ifdef ESMRF_CONF_MAX_SPREAD +#define ESMRF_MAX_SPREAD ESMRF_CONF_MAX_SPREAD +#else +#define ESMRF_MAX_SPREAD 4 +#endif +/*---------------------------------------------------------------------------*/ +/* Stats datatype */ +/*---------------------------------------------------------------------------*/ +struct esmrf_stats { + uint16_t mcast_in_unique; + uint16_t mcast_in_all; /* At layer 3 */ + uint16_t mcast_in_ours; /* Unique and we are a group member */ + uint16_t mcast_fwd; /* Forwarded by us but we are not the seed */ + uint16_t mcast_out; /* We are the seed */ + uint16_t mcast_bad; + uint16_t mcast_dropped; + uint16_t icmp_out; + uint16_t icmp_in; + uint16_t icmp_bad; +}; + +#endif /* ESMRF_H_ */ diff --git a/core/net/ipv6/multicast/uip-mcast6-engines.h b/core/net/ipv6/multicast/uip-mcast6-engines.h index f4bff657a..511029d2f 100644 --- a/core/net/ipv6/multicast/uip-mcast6-engines.h +++ b/core/net/ipv6/multicast/uip-mcast6-engines.h @@ -50,6 +50,7 @@ #define UIP_MCAST6_ENGINE_NONE 0 /**< Selecting this disables mcast */ #define UIP_MCAST6_ENGINE_SMRF 1 /**< The SMRF engine */ #define UIP_MCAST6_ENGINE_ROLL_TM 2 /**< The ROLL TM engine */ +#define UIP_MCAST6_ENGINE_ESMRF 3 /**< The ESMRF engine */ #endif /* UIP_MCAST6_ENGINES_H_ */ /** @} */ diff --git a/core/net/ipv6/multicast/uip-mcast6.h b/core/net/ipv6/multicast/uip-mcast6.h index de2003839..211f1128b 100644 --- a/core/net/ipv6/multicast/uip-mcast6.h +++ b/core/net/ipv6/multicast/uip-mcast6.h @@ -63,6 +63,7 @@ #include "net/ipv6/multicast/uip-mcast6-engines.h" #include "net/ipv6/multicast/uip-mcast6-route.h" #include "net/ipv6/multicast/smrf.h" +#include "net/ipv6/multicast/esmrf.h" #include "net/ipv6/multicast/roll-tm.h" #include @@ -147,17 +148,23 @@ struct uip_mcast6_driver { #if UIP_MCAST6_ENGINE /* Enable Multicast hooks in the uip6 core */ -#define UIP_CONF_IPV6_MULTICAST 1 +#define UIP_IPV6_MULTICAST 1 #if UIP_MCAST6_ENGINE == UIP_MCAST6_ENGINE_ROLL_TM -#define RPL_CONF_MULTICAST 0 /* Not used by trickle */ +#define RPL_WITH_MULTICAST 0 /* Not used by trickle */ #define UIP_CONF_IPV6_ROLL_TM 1 /* ROLL Trickle ICMP type support */ #define UIP_MCAST6 roll_tm_driver + #elif UIP_MCAST6_ENGINE == UIP_MCAST6_ENGINE_SMRF -#define RPL_CONF_MULTICAST 1 +#define RPL_WITH_MULTICAST 1 #define UIP_MCAST6 smrf_driver + +#elif UIP_MCAST6_ENGINE == UIP_MCAST6_ENGINE_ESMRF +#define RPL_CONF_MULTICAST 1 +#define UIP_MCAST6 esmrf_driver + #else #error "Multicast Enabled with an Unknown Engine." #error "Check the value of UIP_MCAST6_CONF_ENGINE in conf files." @@ -168,7 +175,7 @@ extern const struct uip_mcast6_driver UIP_MCAST6; /*---------------------------------------------------------------------------*/ /* Configuration Checks */ /*---------------------------------------------------------------------------*/ -#if RPL_CONF_MULTICAST && (!UIP_CONF_IPV6_RPL) +#if RPL_WITH_MULTICAST && (!UIP_CONF_IPV6_RPL) #error "The selected Multicast mode requires UIP_CONF_IPV6_RPL != 0" #error "Check the value of UIP_CONF_IPV6_RPL in conf files." #endif diff --git a/core/net/ipv6/sicslowpan.c b/core/net/ipv6/sicslowpan.c index d0bf14799..8c174b228 100644 --- a/core/net/ipv6/sicslowpan.c +++ b/core/net/ipv6/sicslowpan.c @@ -62,6 +62,7 @@ #include "contiki.h" #include "dev/watchdog.h" +#include "net/link-stats.h" #include "net/ip/tcpip.h" #include "net/ip/uip.h" #include "net/ipv6/uip-ds6.h" @@ -92,12 +93,6 @@ void uip_log(char *msg); #define UIP_LOG(m) #endif /* UIP_LOGGING == 1 */ -#ifdef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS -#define SICSLOWPAN_MAX_MAC_TRANSMISSIONS SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS -#else -#define SICSLOWPAN_MAX_MAC_TRANSMISSIONS 4 -#endif - #ifndef SICSLOWPAN_COMPRESSION #ifdef SICSLOWPAN_CONF_COMPRESSION #define SICSLOWPAN_COMPRESSION SICSLOWPAN_CONF_COMPRESSION @@ -169,6 +164,14 @@ void uip_log(char *msg); #define COMPRESSION_THRESHOLD 0 #endif +/** \brief Fixed size of a frame header. This value is + * used in case framer returns an error or if SICSLOWPAN_USE_FIXED_HDRLEN + * is defined. + */ +#ifndef SICSLOWPAN_FIXED_HDRLEN +#define SICSLOWPAN_FIXED_HDRLEN 21 +#endif + /** \name General variables * @{ */ @@ -452,7 +455,7 @@ rime_sniffer_remove(struct rime_sniffer *s) } static void -set_packet_attrs() +set_packet_attrs(void) { int c = 0; /* set protocol in NETWORK_ID */ @@ -1277,11 +1280,6 @@ output(const uip_lladdr_t *localdest) /* The MAC address of the destination of the packet */ linkaddr_t dest; -#if SICSLOWPAN_CONF_FRAG - /* Number of bytes processed. */ - uint16_t processed_ip_out_len; -#endif /* SICSLOWPAN_CONF_FRAG */ - /* init */ uncomp_hdr_len = 0; packetbuf_hdr_len = 0; @@ -1290,9 +1288,6 @@ output(const uip_lladdr_t *localdest) packetbuf_clear(); packetbuf_ptr = packetbuf_dataptr(); - packetbuf_set_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, - SICSLOWPAN_MAX_MAC_TRANSMISSIONS); - if(callback) { /* call the attribution when the callback comes, but set attributes here ! */ @@ -1345,21 +1340,23 @@ output(const uip_lladdr_t *localdest) /* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_RDC. * We calculate it here only to make a better decision of whether the outgoing packet * needs to be fragmented or not. */ -#define USE_FRAMER_HDRLEN 1 -#if USE_FRAMER_HDRLEN +#ifndef SICSLOWPAN_USE_FIXED_HDRLEN packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest); framer_hdrlen = NETSTACK_FRAMER.length(); if(framer_hdrlen < 0) { /* Framing failed, we assume the maximum header length */ - framer_hdrlen = 21; + framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN; } #else /* USE_FRAMER_HDRLEN */ - framer_hdrlen = 21; + framer_hdrlen = SICSLOWPAN_FIXED_HDRLEN; #endif /* USE_FRAMER_HDRLEN */ max_payload = MAC_MAX_PAYLOAD - framer_hdrlen; if((int)uip_len - (int)uncomp_hdr_len > max_payload - (int)packetbuf_hdr_len) { #if SICSLOWPAN_CONF_FRAG + /* Number of bytes processed. */ + uint16_t processed_ip_out_len; + struct queuebuf *q; uint16_t frag_tag; @@ -1520,6 +1517,9 @@ input(void) uint8_t first_fragment = 0, last_fragment = 0; #endif /*SICSLOWPAN_CONF_FRAG*/ + /* Update link statistics */ + link_stats_input_callback(packetbuf_addr(PACKETBUF_ADDR_SENDER)); + /* init */ uncomp_hdr_len = 0; packetbuf_hdr_len = 0; @@ -1757,8 +1757,8 @@ sicslowpan_init(void) #ifdef SICSLOWPAN_CONF_ADDR_CONTEXT_0 SICSLOWPAN_CONF_ADDR_CONTEXT_0; #else - addr_contexts[0].prefix[0] = 0xaa; - addr_contexts[0].prefix[1] = 0xaa; + addr_contexts[0].prefix[0] = UIP_DS6_DEFAULT_PREFIX_0; + addr_contexts[0].prefix[1] = UIP_DS6_DEFAULT_PREFIX_1; #endif #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 0 */ diff --git a/core/net/ipv6/uip-ds6-nbr.c b/core/net/ipv6/uip-ds6-nbr.c index 0d1220c2c..3ccebddd1 100644 --- a/core/net/ipv6/uip-ds6-nbr.c +++ b/core/net/ipv6/uip-ds6-nbr.c @@ -47,6 +47,7 @@ #include #include #include "lib/list.h" +#include "net/link-stats.h" #include "net/linkaddr.h" #include "net/packetbuf.h" #include "net/ipv6/uip-ds6-nbr.h" @@ -74,25 +75,32 @@ NBR_TABLE_GLOBAL(uip_ds6_nbr_t, ds6_neighbors); void uip_ds6_neighbors_init(void) { + link_stats_init(); nbr_table_register(ds6_neighbors, (nbr_table_callback *)uip_ds6_nbr_rm); } /*---------------------------------------------------------------------------*/ uip_ds6_nbr_t * uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, - uint8_t isrouter, uint8_t state) + uint8_t isrouter, uint8_t state, nbr_table_reason_t reason, + void *data) { - uip_ds6_nbr_t *nbr = nbr_table_add_lladdr(ds6_neighbors, (linkaddr_t*)lladdr); + uip_ds6_nbr_t *nbr = nbr_table_add_lladdr(ds6_neighbors, (linkaddr_t*)lladdr + , reason, data); if(nbr) { uip_ipaddr_copy(&nbr->ipaddr, ipaddr); +#if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER nbr->isrouter = isrouter; +#endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */ nbr->state = state; - #if UIP_CONF_IPV6_QUEUE_PKT +#if UIP_CONF_IPV6_QUEUE_PKT uip_packetqueue_new(&nbr->packethandle); - #endif /* UIP_CONF_IPV6_QUEUE_PKT */ +#endif /* UIP_CONF_IPV6_QUEUE_PKT */ +#if UIP_ND6_SEND_NA /* timers are set separately, for now we put them in expired state */ stimer_set(&nbr->reachable, 0); stimer_set(&nbr->sendns, 0); nbr->nscount = 0; +#endif /* UIP_ND6_SEND_NA */ PRINTF("Adding neighbor with ip addr "); PRINT6ADDR(ipaddr); PRINTF(" link addr "); @@ -111,7 +119,7 @@ uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, } /*---------------------------------------------------------------------------*/ -void +int uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr) { if(nbr != NULL) { @@ -119,9 +127,9 @@ uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr) uip_packetqueue_free(&nbr->packethandle); #endif /* UIP_CONF_IPV6_QUEUE_PKT */ NEIGHBOR_STATE_CHANGED(nbr); - nbr_table_remove(ds6_neighbors, nbr); + return nbr_table_remove(ds6_neighbors, nbr); } - return; + return 0; } /*---------------------------------------------------------------------------*/ @@ -198,6 +206,9 @@ uip_ds6_link_neighbor_callback(int status, int numtx) return; } + /* Update neighbor link statistics */ + link_stats_packet_sent(dest, status, numtx); + /* Call upper-layer callback (e.g. RPL) */ LINK_NEIGHBOR_CALLBACK(dest, status, numtx); #if UIP_DS6_LL_NUD @@ -230,6 +241,7 @@ uip_ds6_link_neighbor_callback(int status, int numtx) #endif /* UIP_DS6_LL_NUD */ } +#if UIP_ND6_SEND_NA /*---------------------------------------------------------------------------*/ /** Periodic processing on neighbors */ void @@ -241,7 +253,7 @@ uip_ds6_neighbor_periodic(void) case NBR_REACHABLE: if(stimer_expired(&nbr->reachable)) { #if UIP_CONF_IPV6_RPL - /* when a neighbor leave it's REACHABLE state and is a default router, + /* when a neighbor leave its REACHABLE state and is a default router, instead of going to STALE state it enters DELAY state in order to force a NUD on it. Otherwise, if there is no upward traffic, the node never knows if the default router is still reachable. This @@ -268,7 +280,6 @@ uip_ds6_neighbor_periodic(void) #endif /* UIP_CONF_IPV6_RPL */ } break; -#if UIP_ND6_SEND_NA case NBR_INCOMPLETE: if(nbr->nscount >= UIP_ND6_MAX_MULTICAST_SOLICIT) { uip_ds6_nbr_rm(nbr); @@ -304,7 +315,6 @@ uip_ds6_neighbor_periodic(void) stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000); } break; -#endif /* UIP_ND6_SEND_NA */ default: break; } @@ -330,5 +340,6 @@ uip_ds6_get_least_lifetime_neighbor(void) } return nbr_expiring; } +#endif /* UIP_ND6_SEND_NA */ /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/core/net/ipv6/uip-ds6-nbr.h b/core/net/ipv6/uip-ds6-nbr.h index 36a202e86..40a17d1e2 100644 --- a/core/net/ipv6/uip-ds6-nbr.h +++ b/core/net/ipv6/uip-ds6-nbr.h @@ -69,12 +69,13 @@ NBR_TABLE_DECLARE(ds6_neighbors); /** \brief An entry in the nbr cache */ typedef struct uip_ds6_nbr { uip_ipaddr_t ipaddr; + uint8_t isrouter; + uint8_t state; +#if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA struct stimer reachable; struct stimer sendns; uint8_t nscount; - uint8_t isrouter; - uint8_t state; - uint16_t link_metric; +#endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA */ #if UIP_CONF_IPV6_QUEUE_PKT struct uip_packetqueue_handle packethandle; #define UIP_DS6_NBR_PACKET_LIFETIME CLOCK_SECOND * 4 @@ -84,9 +85,11 @@ typedef struct uip_ds6_nbr { void uip_ds6_neighbors_init(void); /** \brief Neighbor Cache basic routines */ -uip_ds6_nbr_t *uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, - uint8_t isrouter, uint8_t state); -void uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr); +uip_ds6_nbr_t *uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, + const uip_lladdr_t *lladdr, + uint8_t isrouter, uint8_t state, + nbr_table_reason_t reason, void *data); +int uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr); const uip_lladdr_t *uip_ds6_nbr_get_ll(const uip_ds6_nbr_t *nbr); const uip_ipaddr_t *uip_ds6_nbr_get_ipaddr(const uip_ds6_nbr_t *nbr); uip_ds6_nbr_t *uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr); diff --git a/core/net/ipv6/uip-ds6-route.c b/core/net/ipv6/uip-ds6-route.c index 3f4ac81e7..bb7b7b18e 100644 --- a/core/net/ipv6/uip-ds6-route.c +++ b/core/net/ipv6/uip-ds6-route.c @@ -57,6 +57,7 @@ void NETSTACK_CONF_ROUTING_NEIGHBOR_ADDED_CALLBACK(const linkaddr_t *addr); void NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK(const linkaddr_t *addr); #endif /* NETSTACK_CONF_ROUTING_NEIGHBOR_REMOVED_CALLBACK */ +#if (UIP_CONF_MAX_ROUTES != 0) /* The nbr_routes holds a neighbor table to be able to maintain information about what routes go through what neighbor. This neighbor table is registered with the central nbr-table repository @@ -71,6 +72,11 @@ MEMB(neighborroutememb, struct uip_ds6_route_neighbor_route, UIP_DS6_ROUTE_NB); LIST(routelist); MEMB(routememb, uip_ds6_route_t, UIP_DS6_ROUTE_NB); +static int num_routes = 0; +static void rm_routelist_callback(nbr_table_item_t *ptr); + +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ + /* Default routes are held on the defaultrouterlist and their structures are allocated from the defaultroutermemb memory block.*/ LIST(defaultrouterlist); @@ -80,13 +86,10 @@ MEMB(defaultroutermemb, uip_ds6_defrt_t, UIP_DS6_DEFRT_NB); LIST(notificationlist); #endif -static int num_routes = 0; - #undef DEBUG #define DEBUG DEBUG_NONE #include "net/ip/uip-debug.h" -static void rm_routelist_callback(nbr_table_item_t *ptr); /*---------------------------------------------------------------------------*/ #if DEBUG != DEBUG_NONE static void @@ -156,10 +159,12 @@ uip_ds6_notification_rm(struct uip_ds6_notification *n) void uip_ds6_route_init(void) { +#if (UIP_CONF_MAX_ROUTES != 0) memb_init(&routememb); list_init(routelist); nbr_table_register(nbr_routes, (nbr_table_callback *)rm_routelist_callback); +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ memb_init(&defaultroutermemb); list_init(defaultrouterlist); @@ -168,6 +173,7 @@ uip_ds6_route_init(void) list_init(notificationlist); #endif } +#if (UIP_CONF_MAX_ROUTES != 0) /*---------------------------------------------------------------------------*/ static uip_lladdr_t * uip_ds6_route_nexthop_lladdr(uip_ds6_route_t *route) @@ -179,42 +185,75 @@ uip_ds6_route_nexthop_lladdr(uip_ds6_route_t *route) return NULL; } } +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ /*---------------------------------------------------------------------------*/ uip_ipaddr_t * uip_ds6_route_nexthop(uip_ds6_route_t *route) { +#if (UIP_CONF_MAX_ROUTES != 0) if(route != NULL) { return uip_ds6_nbr_ipaddr_from_lladdr(uip_ds6_route_nexthop_lladdr(route)); } else { return NULL; } +#else /* (UIP_CONF_MAX_ROUTES != 0) */ + return NULL; +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ } /*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_head(void) { +#if (UIP_CONF_MAX_ROUTES != 0) return list_head(routelist); +#else /* (UIP_CONF_MAX_ROUTES != 0) */ + return NULL; +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ } /*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_next(uip_ds6_route_t *r) { +#if (UIP_CONF_MAX_ROUTES != 0) if(r != NULL) { uip_ds6_route_t *n = list_item_next(r); return n; } +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ return NULL; } /*---------------------------------------------------------------------------*/ int +uip_ds6_route_is_nexthop(const uip_ipaddr_t *ipaddr) +{ +#if (UIP_CONF_MAX_ROUTES != 0) + const uip_lladdr_t *lladdr; + lladdr = uip_ds6_nbr_lladdr_from_ipaddr(ipaddr); + + if(lladdr == NULL) { + return 0; + } + + return nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)lladdr) != NULL; +#else /* (UIP_CONF_MAX_ROUTES != 0) */ + return 0; +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ +} +/*---------------------------------------------------------------------------*/ +int uip_ds6_route_num_routes(void) { +#if (UIP_CONF_MAX_ROUTES != 0) return num_routes; +#else /* (UIP_CONF_MAX_ROUTES != 0) */ + return 0; +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ } /*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_lookup(uip_ipaddr_t *addr) { +#if (UIP_CONF_MAX_ROUTES != 0) uip_ds6_route_t *r; uip_ds6_route_t *found_route; uint8_t longestmatch; @@ -261,12 +300,16 @@ uip_ds6_route_lookup(uip_ipaddr_t *addr) } return found_route; +#else /* (UIP_CONF_MAX_ROUTES != 0) */ + return NULL; +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ } /*---------------------------------------------------------------------------*/ uip_ds6_route_t * uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, uip_ipaddr_t *nexthop) { +#if (UIP_CONF_MAX_ROUTES != 0) uip_ds6_route_t *r; struct uip_ds6_route_neighbor_route *nbrr; @@ -307,11 +350,16 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, least recently used one we have. */ if(uip_ds6_route_num_routes() == UIP_DS6_ROUTE_NB) { + uip_ds6_route_t *oldest; + oldest = NULL; +#if UIP_DS6_ROUTE_REMOVE_LEAST_RECENTLY_USED /* Removing the oldest route entry from the route table. The least recently used route is the first route on the list. */ - uip_ds6_route_t *oldest; - - oldest = list_tail(routelist); /* uip_ds6_route_head(); */ + oldest = list_tail(routelist); +#endif + if(oldest == NULL) { + return NULL; + } PRINTF("uip_ds6_route_add: dropping route to "); PRINT6ADDR(&oldest->ipaddr); PRINTF("\n"); @@ -337,7 +385,8 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, initialize this pointer with the list of routing entries that are attached to this neighbor. */ routes = nbr_table_add_lladdr(nbr_routes, - (linkaddr_t *)nexthop_lladdr); + (linkaddr_t *)nexthop_lladdr, + NBR_TABLE_REASON_ROUTE, NULL); if(routes == NULL) { /* This should not happen, as we explicitly deallocated one route table entry above. */ @@ -407,12 +456,17 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ return r; + +#else /* (UIP_CONF_MAX_ROUTES != 0) */ + return NULL; +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ } /*---------------------------------------------------------------------------*/ void uip_ds6_route_rm(uip_ds6_route_t *route) { +#if (UIP_CONF_MAX_ROUTES != 0) struct uip_ds6_route_neighbor_route *neighbor_route; #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); @@ -469,8 +523,11 @@ uip_ds6_route_rm(uip_ds6_route_t *route) #if DEBUG != DEBUG_NONE assert_nbr_routes_list_sane(); #endif /* DEBUG != DEBUG_NONE */ + +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ return; } +#if (UIP_CONF_MAX_ROUTES != 0) /*---------------------------------------------------------------------------*/ static void rm_routelist(struct uip_ds6_route_neighbor_routes *routes) @@ -498,10 +555,12 @@ rm_routelist_callback(nbr_table_item_t *ptr) { rm_routelist((struct uip_ds6_route_neighbor_routes *)ptr); } +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ /*---------------------------------------------------------------------------*/ void uip_ds6_route_rm_by_nexthop(uip_ipaddr_t *nexthop) { +#if (UIP_CONF_MAX_ROUTES != 0) /* Get routing entry list of this neighbor */ const uip_lladdr_t *nexthop_lladdr; struct uip_ds6_route_neighbor_routes *routes; @@ -510,6 +569,7 @@ uip_ds6_route_rm_by_nexthop(uip_ipaddr_t *nexthop) routes = nbr_table_get_from_lladdr(nbr_routes, (linkaddr_t *)nexthop_lladdr); rm_routelist(routes); +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ } /*---------------------------------------------------------------------------*/ uip_ds6_defrt_t * diff --git a/core/net/ipv6/uip-ds6-route.h b/core/net/ipv6/uip-ds6-route.h index 342bfeffa..6855fc2cd 100644 --- a/core/net/ipv6/uip-ds6-route.h +++ b/core/net/ipv6/uip-ds6-route.h @@ -50,7 +50,7 @@ NBR_TABLE_DECLARE(nbr_routes); void uip_ds6_route_init(void); #ifndef UIP_CONF_UIP_DS6_NOTIFICATIONS -#define UIP_DS6_NOTIFICATIONS 1 +#define UIP_DS6_NOTIFICATIONS (UIP_CONF_MAX_ROUTES != 0) #else #define UIP_DS6_NOTIFICATIONS UIP_CONF_UIP_DS6_NOTIFICATIONS #endif @@ -97,11 +97,48 @@ void uip_ds6_notification_rm(struct uip_ds6_notification *n); #ifndef UIP_DS6_ROUTE_STATE_TYPE #define UIP_DS6_ROUTE_STATE_TYPE rpl_route_entry_t /* Needed for the extended route entry state when using ContikiRPL */ +#define RPL_ROUTE_ENTRY_NOPATH_RECEIVED 0x01 +#define RPL_ROUTE_ENTRY_DAO_PENDING 0x02 +#define RPL_ROUTE_ENTRY_DAO_NACK 0x04 + +#define RPL_ROUTE_IS_NOPATH_RECEIVED(route) \ + (((route)->state.state_flags & RPL_ROUTE_ENTRY_NOPATH_RECEIVED) != 0) +#define RPL_ROUTE_SET_NOPATH_RECEIVED(route) do { \ + (route)->state.state_flags |= RPL_ROUTE_ENTRY_NOPATH_RECEIVED; \ + } while(0) +#define RPL_ROUTE_CLEAR_NOPATH_RECEIVED(route) do { \ + (route)->state.state_flags &= ~RPL_ROUTE_ENTRY_NOPATH_RECEIVED; \ + } while(0) + +#define RPL_ROUTE_IS_DAO_PENDING(route) \ + ((route->state.state_flags & RPL_ROUTE_ENTRY_DAO_PENDING) != 0) +#define RPL_ROUTE_SET_DAO_PENDING(route) do { \ + (route)->state.state_flags |= RPL_ROUTE_ENTRY_DAO_PENDING; \ + } while(0) +#define RPL_ROUTE_CLEAR_DAO_PENDING(route) do { \ + (route)->state.state_flags &= ~RPL_ROUTE_ENTRY_DAO_PENDING; \ + } while(0) + +#define RPL_ROUTE_IS_DAO_NACKED(route) \ + ((route->state.state_flags & RPL_ROUTE_ENTRY_DAO_NACK) != 0) +#define RPL_ROUTE_SET_DAO_NACKED(route) do { \ + (route)->state.state_flags |= RPL_ROUTE_ENTRY_DAO_NACK; \ + } while(0) +#define RPL_ROUTE_CLEAR_DAO_NACKED(route) do { \ + (route)->state.state_flags &= ~RPL_ROUTE_ENTRY_DAO_NACK; \ + } while(0) + +#define RPL_ROUTE_CLEAR_DAO(route) do { \ + (route)->state.state_flags &= ~(RPL_ROUTE_ENTRY_DAO_NACK|RPL_ROUTE_ENTRY_DAO_PENDING); \ + } while(0) + +struct rpl_dag; typedef struct rpl_route_entry { uint32_t lifetime; - void *dag; - uint8_t learned_from; - uint8_t nopath_received; + struct rpl_dag *dag; + uint8_t dao_seqno_out; + uint8_t dao_seqno_in; + uint8_t state_flags; } rpl_route_entry_t; #endif /* UIP_DS6_ROUTE_STATE_TYPE */ @@ -166,7 +203,7 @@ uip_ipaddr_t *uip_ds6_route_nexthop(uip_ds6_route_t *); int uip_ds6_route_num_routes(void); uip_ds6_route_t *uip_ds6_route_head(void); uip_ds6_route_t *uip_ds6_route_next(uip_ds6_route_t *); - +int uip_ds6_route_is_nexthop(const uip_ipaddr_t *ipaddr); /** @} */ #endif /* UIP_DS6_ROUTE_H */ diff --git a/core/net/ipv6/uip-ds6.c b/core/net/ipv6/uip-ds6.c index c5e4ed19e..9b690ab8c 100644 --- a/core/net/ipv6/uip-ds6.c +++ b/core/net/ipv6/uip-ds6.c @@ -48,6 +48,7 @@ #include "lib/random.h" #include "net/ipv6/uip-nd6.h" #include "net/ipv6/uip-ds6.h" +#include "net/ipv6/multicast/uip-mcast6.h" #include "net/ip/uip-packetqueue.h" #define DEBUG DEBUG_NONE @@ -186,7 +187,9 @@ uip_ds6_periodic(void) } #endif /* !UIP_CONF_ROUTER */ +#if UIP_ND6_SEND_NA uip_ds6_neighbor_periodic(); +#endif /* UIP_ND6_SEND_RA */ #if UIP_CONF_ROUTER && UIP_ND6_SEND_RA /* Periodic RA sending */ diff --git a/core/net/ipv6/uip-ds6.h b/core/net/ipv6/uip-ds6.h index 1c00a50b0..294eb230c 100644 --- a/core/net/ipv6/uip-ds6.h +++ b/core/net/ipv6/uip-ds6.h @@ -67,6 +67,36 @@ #endif #define UIP_DS6_DEFRT_NB UIP_DS6_DEFRT_NBS + UIP_DS6_DEFRT_NBU +/* Default prefix */ +#ifdef UIP_CONF_DS6_DEFAULT_PREFIX +#define UIP_DS6_DEFAULT_PREFIX UIP_CONF_DS6_DEFAULT_PREFIX +#else +/* From RFC4193, section 3.1: + * | 7 bits |1| 40 bits | 16 bits | 64 bits | + * +--------+-+------------+-----------+----------------------------+ + * | Prefix |L| Global ID | Subnet ID | Interface ID | + * +--------+-+------------+-----------+----------------------------+ + * Prefix FC00::/7 prefix to identify Local IPv6 unicast + * addresses. + * L Set to 1 if the prefix is locally assigned. + * Set to 0 may be defined in the future. See + * Section 3.2 for additional information. + * Global ID 40-bit global identifier used to create a + * globally unique prefix. See Section 3.2 for + * additional information. + * + * We set prefix to 0xfc00 and set the local bit, resulting in 0xfd00. + * For high probability of network uniqueness, Global ID must be generated + * pseudo-randomly. As this is a hard-coded default prefix, we simply use + * a Global ID of 0. For real deployments, make sure to install a pseudo-random + * Global ID, e.g. in a RPL network, by configuring it at the root. + */ +#define UIP_DS6_DEFAULT_PREFIX 0xfd00 +#endif /* UIP_CONF_DS6_DEFAULT_PREFIX */ + +#define UIP_DS6_DEFAULT_PREFIX_0 ((UIP_DS6_DEFAULT_PREFIX >> 8) & 0xff) +#define UIP_DS6_DEFAULT_PREFIX_1 (UIP_DS6_DEFAULT_PREFIX & 0xff) + /* Prefix list */ #define UIP_DS6_PREFIX_NBS 1 #ifndef UIP_CONF_DS6_PREFIX_NBU diff --git a/core/net/ipv6/uip-icmp6.c b/core/net/ipv6/uip-icmp6.c index f48db774a..d246a4d58 100644 --- a/core/net/ipv6/uip-icmp6.c +++ b/core/net/ipv6/uip-icmp6.c @@ -38,7 +38,7 @@ /** * \file * ICMPv6 (RFC 4443) implementation, with message and error handling - * \author Julien Abeille + * \author Julien Abeille * \author Mathilde Durvy */ @@ -120,9 +120,6 @@ uip_icmp6_register_input_handler(uip_icmp6_input_handler_t *handler) static void echo_request_input(void) { -#if UIP_CONF_IPV6_RPL - uint8_t temp_ext_len; -#endif /* UIP_CONF_IPV6_RPL */ /* * we send an echo reply. It is trivial if there was no extension * headers in the request otherwise we need to remove the extension @@ -147,44 +144,27 @@ echo_request_input(void) } if(uip_ext_len > 0) { -#if UIP_CONF_IPV6_RPL - if((temp_ext_len = rpl_invert_header())) { - /* If there were other extension headers*/ - UIP_FIRST_EXT_BUF->next = UIP_PROTO_ICMP6; - if (uip_ext_len != temp_ext_len) { - uip_len -= (uip_ext_len - temp_ext_len); - UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); - UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); - /* move the echo request payload (starting after the icmp header) - * to the new location in the reply. - * The shift is equal to the length of the remaining extension headers present - * Note: UIP_ICMP_BUF still points to the echo request at this stage - */ - memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - (uip_ext_len - temp_ext_len), - (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, - (uip_len - UIP_IPH_LEN - temp_ext_len - UIP_ICMPH_LEN)); - } - uip_ext_len = temp_ext_len; - } else { -#endif /* UIP_CONF_IPV6_RPL */ - /* If there were extension headers*/ - UIP_IP_BUF->proto = UIP_PROTO_ICMP6; - uip_len -= uip_ext_len; - UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); - UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); - /* move the echo request payload (starting after the icmp header) - * to the new location in the reply. - * The shift is equal to the length of the extension headers present - * Note: UIP_ICMP_BUF still points to the echo request at this stage - */ - memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - uip_ext_len, - (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, - (uip_len - UIP_IPH_LEN - UIP_ICMPH_LEN)); - uip_ext_len = 0; -#if UIP_CONF_IPV6_RPL - } -#endif /* UIP_CONF_IPV6_RPL */ + /* Remove extension headers if any */ + UIP_IP_BUF->proto = UIP_PROTO_ICMP6; + uip_len -= uip_ext_len; + UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); + /* move the echo request payload (starting after the icmp header) + * to the new location in the reply. + * The shift is equal to the length of the extension headers present + * Note: UIP_ICMP_BUF still points to the echo request at this stage + */ + memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - uip_ext_len, + (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, + (uip_len - UIP_IPH_LEN - UIP_ICMPH_LEN)); + uip_ext_len = 0; } + + /* Insert RPL extension headers */ +#if UIP_CONF_IPV6_RPL + rpl_insert_header(); +#endif /* UIP_CONF_IPV6_RPL */ + /* Below is important for the correctness of UIP_ICMP_BUF and the * checksum */ @@ -206,23 +186,22 @@ echo_request_input(void) /*---------------------------------------------------------------------------*/ void uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) { - - /* check if originating packet is not an ICMP error*/ - if (uip_ext_len) { - if(UIP_EXT_BUF->next == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){ + /* check if originating packet is not an ICMP error */ + if(uip_ext_len) { + if(UIP_EXT_BUF->next == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128) { uip_clear_buf(); return; } } else { - if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){ + if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128) { uip_clear_buf(); return; } } #if UIP_CONF_IPV6_RPL - uip_ext_len = rpl_invert_header(); -#else /* UIP_CONF_IPV6_RPL */ + rpl_remove_header(); +#else uip_ext_len = 0; #endif /* UIP_CONF_IPV6_RPL */ @@ -231,8 +210,9 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) { uip_len += UIP_IPICMPH_LEN + UIP_ICMP6_ERROR_LEN; - if(uip_len > UIP_LINK_MTU) + if(uip_len > UIP_LINK_MTU) { uip_len = UIP_LINK_MTU; + } memmove((uint8_t *)UIP_ICMP6_ERROR_BUF + uip_ext_len + UIP_ICMP6_ERROR_LEN, (void *)UIP_IP_BUF, uip_len - UIP_IPICMPH_LEN - uip_ext_len - UIP_ICMP6_ERROR_LEN); @@ -280,6 +260,10 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) { UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); +#if UIP_CONF_IPV6_RPL + rpl_insert_header(); +#endif /* UIP_CONF_IPV6_RPL */ + UIP_STAT(++uip_stat.icmp.sent); PRINTF("Sending ICMPv6 ERROR message type %d code %d to ", type, code); @@ -313,6 +297,13 @@ uip_icmp6_send(const uip_ipaddr_t *dest, int type, int code, int payload_len) UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + payload_len; + + UIP_STAT(++uip_stat.icmp.sent); + UIP_STAT(++uip_stat.ip.sent); + +#if UIP_CONF_IPV6_RPL + rpl_insert_header(); +#endif /* UIP_CONF_IPV6_RPL */ tcpip_ipv6_output(); } /*---------------------------------------------------------------------------*/ @@ -321,53 +312,31 @@ echo_reply_input(void) { int ttl; uip_ipaddr_t sender; -#if UIP_CONF_IPV6_RPL - uint8_t temp_ext_len; -#endif /* UIP_CONF_IPV6_RPL */ + + PRINTF("Received Echo Reply from "); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF(" to "); + PRINT6ADDR(&UIP_IP_BUF->destipaddr); + PRINTF("\n"); uip_ipaddr_copy(&sender, &UIP_IP_BUF->srcipaddr); ttl = UIP_IP_BUF->ttl; if(uip_ext_len > 0) { -#if UIP_CONF_IPV6_RPL - if((temp_ext_len = rpl_invert_header())) { - /* If there were other extension headers*/ - UIP_FIRST_EXT_BUF->next = UIP_PROTO_ICMP6; - if (uip_ext_len != temp_ext_len) { - uip_len -= (uip_ext_len - temp_ext_len); - UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); - UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); - /* move the echo reply payload (starting after the icmp - * header) to the new location in the reply. The shift is - * equal to the length of the remaining extension headers - * present Note: UIP_ICMP_BUF still points to the echo reply - * at this stage - */ - memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - (uip_ext_len - temp_ext_len), - (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, - (uip_len - UIP_IPH_LEN - temp_ext_len - UIP_ICMPH_LEN)); - } - uip_ext_len = temp_ext_len; - uip_len -= uip_ext_len; - } else { -#endif /* UIP_CONF_IPV6_RPL */ - /* If there were extension headers*/ - UIP_IP_BUF->proto = UIP_PROTO_ICMP6; - uip_len -= uip_ext_len; - UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); - UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); - /* move the echo reply payload (starting after the icmp header) - * to the new location in the reply. The shift is equal to the - * length of the extension headers present Note: UIP_ICMP_BUF - * still points to the echo request at this stage - */ - memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - uip_ext_len, - (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, - (uip_len - UIP_IPH_LEN - UIP_ICMPH_LEN)); - uip_ext_len = 0; -#if UIP_CONF_IPV6_RPL - } -#endif /* UIP_CONF_IPV6_RPL */ + /* Remove extension headers if any */ + UIP_IP_BUF->proto = UIP_PROTO_ICMP6; + uip_len -= uip_ext_len; + UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); + /* move the echo reply payload (starting after the icmp header) + * to the new location in the reply. The shift is equal to the + * length of the extension headers present Note: UIP_ICMP_BUF + * still points to the echo request at this stage + */ + memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - uip_ext_len, + (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, + (uip_len - UIP_IPH_LEN - UIP_ICMPH_LEN)); + uip_ext_len = 0; } /* Call all registered applications to let them know an echo reply diff --git a/core/net/ipv6/uip-icmp6.h b/core/net/ipv6/uip-icmp6.h index 5633791fd..2fd1c8fbf 100644 --- a/core/net/ipv6/uip-icmp6.h +++ b/core/net/ipv6/uip-icmp6.h @@ -69,6 +69,7 @@ #define ICMP6_PRIV_EXP_200 200 /**< Private Experimentation */ #define ICMP6_PRIV_EXP_201 201 /**< Private Experimentation */ #define ICMP6_ROLL_TM ICMP6_PRIV_EXP_200 /**< ROLL Trickle Multicast */ +#define ICMP6_ESMRF ICMP6_PRIV_EXP_201 /**< ESMRF Multicast */ /** @} */ diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index 143cfe369..218507228 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -135,11 +135,13 @@ static uip_ds6_prefix_t *prefix; /** Pointer to a prefix list entry */ #if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER /*------------------------------------------------------------------*/ /* Copy link-layer address from LLAO option to a word-aligned uip_lladdr_t */ -static void -extract_lladdr_aligned(uip_lladdr_t *dest) { +static int +extract_lladdr_from_llao_aligned(uip_lladdr_t *dest) { if(dest != NULL && nd6_opt_llao != NULL) { memcpy(dest, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN); + return 1; } + return 0; } #endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */ /*------------------------------------------------------------------*/ @@ -199,16 +201,23 @@ ns_input(void) goto discard; } else { #endif /*UIP_CONF_IPV6_CHECKS */ + uip_lladdr_t lladdr_aligned; + extract_lladdr_from_llao_aligned(&lladdr_aligned); nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); if(nbr == NULL) { - uip_lladdr_t lladdr_aligned; - extract_lladdr_aligned(&lladdr_aligned); - uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE); + uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, + 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); } else { - uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr); + const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr); + if(lladdr == NULL) { + goto discard; + } if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr, UIP_LLADDR_LEN) != 0) { - memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], UIP_LLADDR_LEN); + if(nbr_table_update_lladdr((const linkaddr_t *)lladdr, (const linkaddr_t *)&lladdr_aligned, 1) == 0) { + /* failed to update the lladdr */ + goto discard; + } nbr->state = NBR_STALE; } else { if(nbr->state == NBR_INCOMPLETE) { @@ -427,6 +436,7 @@ na_input(void) uint8_t is_router; uint8_t is_solicited; uint8_t is_override; + uip_lladdr_t lladdr_aligned; PRINTF("Received NA from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); @@ -489,23 +499,29 @@ na_input(void) PRINTF("NA received is bad\n"); goto discard; } else { - uip_lladdr_t *lladdr; + const uip_lladdr_t *lladdr; nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr); - lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr); if(nbr == NULL) { goto discard; } - if(nd6_opt_llao != 0) { + lladdr = uip_ds6_nbr_get_ll(nbr); + if(lladdr == NULL) { + goto discard; + } + if(nd6_opt_llao != NULL) { is_llchange = - memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], (void *)lladdr, + memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr, UIP_LLADDR_LEN); } if(nbr->state == NBR_INCOMPLETE) { - if(nd6_opt_llao == NULL) { + if(nd6_opt_llao == NULL || !extract_lladdr_from_llao_aligned(&lladdr_aligned)) { goto discard; } - memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], - UIP_LLADDR_LEN); + if(nbr_table_update_lladdr((const linkaddr_t *)lladdr, (const linkaddr_t *)&lladdr_aligned, 1) == 0) { + /* failed to update the lladdr */ + goto discard; + } + if(is_solicited) { nbr->state = NBR_REACHABLE; nbr->nscount = 0; @@ -517,27 +533,29 @@ na_input(void) nbr->state = NBR_STALE; } nbr->isrouter = is_router; - } else { + } else { /* NBR is not INCOMPLETE */ if(!is_override && is_llchange) { if(nbr->state == NBR_REACHABLE) { nbr->state = NBR_STALE; } goto discard; } else { - if(is_override || (!is_override && nd6_opt_llao != 0 && !is_llchange) - || nd6_opt_llao == 0) { - if(nd6_opt_llao != 0) { - memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], - UIP_LLADDR_LEN); + /** + * If this is an cache override, or same lladdr, or no llao - + * do updates of nbr states. + */ + if(is_override || !is_llchange || nd6_opt_llao == NULL) { + if(nd6_opt_llao != NULL && is_llchange) { + if(!extract_lladdr_from_llao_aligned(&lladdr_aligned) || + nbr_table_update_lladdr((const linkaddr_t *) lladdr, (const linkaddr_t *) &lladdr_aligned, 1) == 0) { + /* failed to update the lladdr */ + goto discard; + } } if(is_solicited) { nbr->state = NBR_REACHABLE; /* reachable time is stored in ms */ stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000); - } else { - if(nd6_opt_llao != 0 && is_llchange) { - nbr->state = NBR_STALE; - } } } } @@ -631,17 +649,23 @@ rs_input(void) } else { #endif /*UIP_CONF_IPV6_CHECKS */ uip_lladdr_t lladdr_aligned; - extract_lladdr_aligned(&lladdr_aligned); + extract_lladdr_from_llao_aligned(&lladdr_aligned); if((nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr)) == NULL) { /* we need to add the neighbor */ - uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE); + uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, + 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); } else { /* If LL address changed, set neighbor state to stale */ + const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr); + if(lladdr == NULL) { + goto discard; + } if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], - uip_ds6_nbr_get_ll(nbr), UIP_LLADDR_LEN) != 0) { + lladdr, UIP_LLADDR_LEN) != 0) { uip_ds6_nbr_t nbr_data = *nbr; uip_ds6_nbr_rm(nbr); - nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 0, NBR_STALE); + nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, + 0, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); nbr->reachable = nbr_data.reachable; nbr->sendns = nbr_data.sendns; nbr->nscount = nbr_data.nscount; @@ -823,6 +847,8 @@ uip_nd6_rs_output(void) void ra_input(void) { + uip_lladdr_t lladdr_aligned; + PRINTF("Received RA from "); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF(" to "); @@ -867,19 +893,28 @@ ra_input(void) PRINTF("Processing SLLAO option in RA\n"); nd6_opt_llao = (uint8_t *) UIP_ND6_OPT_HDR_BUF; nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr); + if(!extract_lladdr_from_llao_aligned(&lladdr_aligned)) { + /* failed to extract llao - discard packet */ + goto discard; + } if(nbr == NULL) { - uip_lladdr_t lladdr_aligned; - extract_lladdr_aligned(&lladdr_aligned); - nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, 1, NBR_STALE); + nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr, &lladdr_aligned, + 1, NBR_STALE, NBR_TABLE_REASON_IPV6_ND, NULL); } else { - uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr); + const uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr); + if(lladdr == NULL) { + goto discard; + } if(nbr->state == NBR_INCOMPLETE) { nbr->state = NBR_STALE; } if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], lladdr, UIP_LLADDR_LEN) != 0) { - memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], - UIP_LLADDR_LEN); + /* change of link layer address */ + if(nbr_table_update_lladdr((const linkaddr_t *)lladdr, (const linkaddr_t *)&lladdr_aligned, 1) == 0) { + /* failed to update the lladdr */ + goto discard; + } nbr->state = NBR_STALE; } nbr->isrouter = 1; diff --git a/core/net/ipv6/uip6.c b/core/net/ipv6/uip6.c index 5cbf39203..94f4dfcf9 100644 --- a/core/net/ipv6/uip6.c +++ b/core/net/ipv6/uip6.c @@ -79,6 +79,11 @@ #include "net/ipv6/uip-ds6.h" #include "net/ipv6/multicast/uip-mcast6.h" +#if UIP_CONF_IPV6_RPL +#include "rpl/rpl.h" +#include "rpl/rpl-private.h" +#endif + #include /*---------------------------------------------------------------------------*/ @@ -88,10 +93,6 @@ #define DEBUG DEBUG_NONE #include "net/ip/uip-debug.h" -#if UIP_CONF_IPV6_RPL -#include "rpl/rpl.h" -#endif /* UIP_CONF_IPV6_RPL */ - #if UIP_LOGGING == 1 #include void uip_log(char *msg); @@ -207,11 +208,6 @@ uint8_t uip_flags; /* uip_conn always points to the current connection (set to NULL for UDP). */ struct uip_conn *uip_conn; -/* Temporary variables. */ -#if (UIP_TCP || UIP_UDP) -static uint8_t c; -#endif - #if UIP_ACTIVE_OPEN || UIP_UDP /* Keeps track of the last port used for a new connection. */ static uint16_t lastport; @@ -256,8 +252,6 @@ static uint8_t iss[4]; /* Temporary variables. */ uint8_t uip_acc32[4]; -static uint8_t opt; -static uint16_t tmp16; #endif /* UIP_TCP */ /** @} */ @@ -432,6 +426,7 @@ uip_udpchksum(void) void uip_init(void) { + int c; uip_ds6_init(); uip_icmp6_init(); @@ -456,7 +451,7 @@ uip_init(void) } #endif /* UIP_UDP */ -#if UIP_CONF_IPV6_MULTICAST +#if UIP_IPV6_MULTICAST UIP_MCAST6.init(); #endif } @@ -466,9 +461,10 @@ struct uip_conn * uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport) { register struct uip_conn *conn, *cconn; + int c; /* Find an unused local port. */ - again: + again: ++lastport; if(lastport >= 32000) { @@ -560,10 +556,11 @@ remove_ext_hdr(void) struct uip_udp_conn * uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport) { + int c; register struct uip_udp_conn *conn; /* Find an unused local port. */ - again: + again: ++lastport; if(lastport >= 32000) { @@ -605,6 +602,7 @@ uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport) void uip_unlisten(uint16_t port) { + int c; for(c = 0; c < UIP_LISTENPORTS; ++c) { if(uip_listenports[c] == port) { uip_listenports[c] = 0; @@ -616,6 +614,7 @@ uip_unlisten(uint16_t port) void uip_listen(uint16_t port) { + int c; for(c = 0; c < UIP_LISTENPORTS; ++c) { if(uip_listenports[c] == 0) { uip_listenports[c] = port; @@ -787,7 +786,7 @@ uip_reass(void) return 0; } - /* If we have come this far, we have a full packet in the + /* If we have come this far, we have a full packet in the buffer, so we copy it to uip_buf. We also reset the timer. */ uip_reass_on = 0; etimer_stop(&uip_reass_timer); @@ -811,7 +810,7 @@ uip_reass(void) void uip_reass_over(void) { - /* to late, we abandon the reassembly of the packet */ + /* to late, we abandon the reassembly of the packet */ uip_reass_on = 0; etimer_stop(&uip_reass_timer); @@ -859,77 +858,77 @@ uip_add_rcv_nxt(uint16_t n) static uint8_t ext_hdr_options_process(void) { - /* - * Length field in the extension header: length of the header in units of - * 8 bytes, excluding the first 8 bytes - * length field in an option : the length of data in the option - */ + /* + * Length field in the extension header: length of the header in units of + * 8 bytes, excluding the first 8 bytes + * length field in an option : the length of data in the option + */ uip_ext_opt_offset = 2; while(uip_ext_opt_offset < ((UIP_EXT_BUF->len << 3) + 8)) { switch(UIP_EXT_HDR_OPT_BUF->type) { - /* - * for now we do not support any options except padding ones - * PAD1 does not make sense as the header must be 8bytes aligned, - * hence we can only have + /* + * for now we do not support any options except padding ones + * PAD1 does not make sense as the header must be 8bytes aligned, + * hence we can only have + */ + case UIP_EXT_HDR_OPT_PAD1: + PRINTF("Processing PAD1 option\n"); + uip_ext_opt_offset += 1; + break; + case UIP_EXT_HDR_OPT_PADN: + PRINTF("Processing PADN option\n"); + uip_ext_opt_offset += UIP_EXT_HDR_OPT_PADN_BUF->opt_len + 2; + break; + case UIP_EXT_HDR_OPT_RPL: + /* Fixes situation when a node that is not using RPL + * joins a network which does. The received packages will include the + * RPL header and processed by the "default" case of the switch + * (0x63 & 0xC0 = 0x40). Hence, the packet is discarded as the header + * is considered invalid. + * Using this fix, the header is ignored, and the next header (if + * present) is processed. */ - case UIP_EXT_HDR_OPT_PAD1: - PRINTF("Processing PAD1 option\n"); - uip_ext_opt_offset += 1; - break; - case UIP_EXT_HDR_OPT_PADN: - PRINTF("Processing PADN option\n"); - uip_ext_opt_offset += UIP_EXT_HDR_OPT_PADN_BUF->opt_len + 2; - break; - case UIP_EXT_HDR_OPT_RPL: - /* Fixes situation when a node that is not using RPL - * joins a network which does. The received packages will include the - * RPL header and processed by the "default" case of the switch - * (0x63 & 0xC0 = 0x40). Hence, the packet is discarded as the header - * is considered invalid. - * Using this fix, the header is ignored, and the next header (if - * present) is processed. - */ #if UIP_CONF_IPV6_RPL - PRINTF("Processing RPL option\n"); - if(rpl_verify_header(uip_ext_opt_offset)) { - PRINTF("RPL Option Error: Dropping Packet\n"); + PRINTF("Processing RPL option\n"); + if(rpl_verify_hbh_header(uip_ext_opt_offset)) { + PRINTF("RPL Option Error: Dropping Packet\n"); + return 1; + } +#endif /* UIP_CONF_IPV6_RPL */ + uip_ext_opt_offset += (UIP_EXT_HDR_OPT_BUF->len) + 2; + return 0; + default: + /* + * check the two highest order bits of the option + * - 00 skip over this option and continue processing the header. + * - 01 discard the packet. + * - 10 discard the packet and, regardless of whether or not the + * packet's Destination Address was a multicast address, send an + * ICMP Parameter Problem, Code 2, message to the packet's + * Source Address, pointing to the unrecognized Option Type. + * - 11 discard the packet and, only if the packet's Destination + * Address was not a multicast address, send an ICMP Parameter + * Problem, Code 2, message to the packet's Source Address, + * pointing to the unrecognized Option Type. + */ + PRINTF("MSB %x\n", UIP_EXT_HDR_OPT_BUF->type); + switch(UIP_EXT_HDR_OPT_BUF->type & 0xC0) { + case 0: + break; + case 0x40: + return 1; + case 0xC0: + if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { return 1; } -#endif /* UIP_CONF_IPV6_RPL */ - uip_ext_opt_offset += (UIP_EXT_HDR_OPT_BUF->len) + 2; - return 0; - default: - /* - * check the two highest order bits of the option - * - 00 skip over this option and continue processing the header. - * - 01 discard the packet. - * - 10 discard the packet and, regardless of whether or not the - * packet's Destination Address was a multicast address, send an - * ICMP Parameter Problem, Code 2, message to the packet's - * Source Address, pointing to the unrecognized Option Type. - * - 11 discard the packet and, only if the packet's Destination - * Address was not a multicast address, send an ICMP Parameter - * Problem, Code 2, message to the packet's Source Address, - * pointing to the unrecognized Option Type. - */ - PRINTF("MSB %x\n", UIP_EXT_HDR_OPT_BUF->type); - switch(UIP_EXT_HDR_OPT_BUF->type & 0xC0) { - case 0: - break; - case 0x40: - return 1; - case 0xC0: - if(uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { - return 1; - } - case 0x80: - uip_icmp6_error_output(ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, - (uint32_t)UIP_IPH_LEN + uip_ext_len + uip_ext_opt_offset); - return 2; - } - /* in the cases were we did not discard, update ext_opt* */ - uip_ext_opt_offset += UIP_EXT_HDR_OPT_BUF->len + 2; - break; + case 0x80: + uip_icmp6_error_output(ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION, + (uint32_t)UIP_IPH_LEN + uip_ext_len + uip_ext_opt_offset); + return 2; + } + /* in the cases were we did not discard, update ext_opt* */ + uip_ext_opt_offset += UIP_EXT_HDR_OPT_BUF->len + 2; + break; } } return 0; @@ -941,6 +940,9 @@ void uip_process(uint8_t flag) { #if UIP_TCP + int c; + uint16_t tmp16; + uint8_t opt; register struct uip_conn *uip_connr = uip_conn; #endif /* UIP_TCP */ #if UIP_UDP @@ -1039,33 +1041,33 @@ uip_process(uint8_t flag) */ UIP_STAT(++uip_stat.tcp.rexmit); switch(uip_connr->tcpstateflags & UIP_TS_MASK) { - case UIP_SYN_RCVD: - /* In the SYN_RCVD state, we should retransmit our SYNACK. */ - goto tcp_send_synack; + case UIP_SYN_RCVD: + /* In the SYN_RCVD state, we should retransmit our SYNACK. */ + goto tcp_send_synack; #if UIP_ACTIVE_OPEN - case UIP_SYN_SENT: - /* In the SYN_SENT state, we retransmit out SYN. */ - UIP_TCP_BUF->flags = 0; - goto tcp_send_syn; + case UIP_SYN_SENT: + /* In the SYN_SENT state, we retransmit out SYN. */ + UIP_TCP_BUF->flags = 0; + goto tcp_send_syn; #endif /* UIP_ACTIVE_OPEN */ - case UIP_ESTABLISHED: - /* - * In the ESTABLISHED state, we call upon the application - * to do the actual retransmit after which we jump into - * the code for sending out the packet (the apprexmit - * label). - */ - uip_flags = UIP_REXMIT; - UIP_APPCALL(); - goto apprexmit; + case UIP_ESTABLISHED: + /* + * In the ESTABLISHED state, we call upon the application + * to do the actual retransmit after which we jump into + * the code for sending out the packet (the apprexmit + * label). + */ + uip_flags = UIP_REXMIT; + UIP_APPCALL(); + goto apprexmit; - case UIP_FIN_WAIT_1: - case UIP_CLOSING: - case UIP_LAST_ACK: - /* In all these states we should retransmit a FINACK. */ - goto tcp_send_finack; + case UIP_FIN_WAIT_1: + case UIP_CLOSING: + case UIP_LAST_ACK: + /* In all these states we should retransmit a FINACK. */ + goto tcp_send_finack; } } } else if((uip_connr->tcpstateflags & UIP_TS_MASK) == UIP_ESTABLISHED) { @@ -1162,20 +1164,20 @@ uip_process(uint8_t flag) uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_HBHO; #endif /* UIP_CONF_IPV6_CHECKS */ switch(ext_hdr_options_process()) { - case 0: - /* continue */ - uip_next_hdr = &UIP_EXT_BUF->next; - uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; - break; - case 1: - PRINTF("Dropping packet after extension header processing\n"); - /* silently discard */ - goto drop; - case 2: - PRINTF("Sending error message after extension header processing\n"); - /* send icmp error message (created in ext_hdr_options_process) - * and discard*/ - goto send; + case 0: + /* continue */ + uip_next_hdr = &UIP_EXT_BUF->next; + uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; + break; + case 1: + PRINTF("Dropping packet after extension header processing\n"); + /* silently discard */ + goto drop; + case 2: + PRINTF("Sending error message after extension header processing\n"); + /* send icmp error message (created in ext_hdr_options_process) + * and discard*/ + goto send; } } @@ -1190,7 +1192,7 @@ uip_process(uint8_t flag) * All multicast engines must hook in here. After this function returns, we * expect UIP_BUF to be unmodified */ -#if UIP_CONF_IPV6_MULTICAST +#if UIP_IPV6_MULTICAST if(uip_is_addr_mcast_routable(&UIP_IP_BUF->destipaddr)) { if(UIP_MCAST6.in() == UIP_MCAST6_ACCEPT) { /* Deliver up the stack */ @@ -1200,7 +1202,7 @@ uip_process(uint8_t flag) goto drop; } } -#endif /* UIP_IPV6_CONF_MULTICAST */ +#endif /* UIP_IPV6_MULTICAST */ /* TBD Some Parameter problem messages */ if(!uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr) && @@ -1227,9 +1229,9 @@ uip_process(uint8_t flag) } #if UIP_CONF_IPV6_RPL - if(rpl_update_header_empty()) { + if(!rpl_update_header()) { /* Packet can not be forwarded */ - PRINTF("RPL Forward Option Error\n"); + PRINTF("RPL header update error\n"); goto drop; } #endif /* UIP_CONF_IPV6_RPL */ @@ -1274,51 +1276,51 @@ uip_process(uint8_t flag) uip_ext_bitmap = 0; #endif /* UIP_CONF_ROUTER */ -#if UIP_CONF_IPV6_MULTICAST +#if UIP_IPV6_MULTICAST process: #endif while(1) { switch(*uip_next_hdr){ #if UIP_TCP - case UIP_PROTO_TCP: - /* TCP, for both IPv4 and IPv6 */ - goto tcp_input; + case UIP_PROTO_TCP: + /* TCP, for both IPv4 and IPv6 */ + goto tcp_input; #endif /* UIP_TCP */ #if UIP_UDP - case UIP_PROTO_UDP: - /* UDP, for both IPv4 and IPv6 */ - goto udp_input; + case UIP_PROTO_UDP: + /* UDP, for both IPv4 and IPv6 */ + goto udp_input; #endif /* UIP_UDP */ - case UIP_PROTO_ICMP6: - /* ICMPv6 */ - goto icmp6_input; - case UIP_PROTO_HBHO: - PRINTF("Processing hbh header\n"); - /* Hop by hop option header */ + case UIP_PROTO_ICMP6: + /* ICMPv6 */ + goto icmp6_input; + case UIP_PROTO_HBHO: + PRINTF("Processing hbh header\n"); + /* Hop by hop option header */ #if UIP_CONF_IPV6_CHECKS - /* Hop by hop option header. If we saw one HBH already, drop */ - if(uip_ext_bitmap & UIP_EXT_HDR_BITMAP_HBHO) { - goto bad_hdr; - } else { - uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_HBHO; - } + /* Hop by hop option header. If we saw one HBH already, drop */ + if(uip_ext_bitmap & UIP_EXT_HDR_BITMAP_HBHO) { + goto bad_hdr; + } else { + uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_HBHO; + } #endif /*UIP_CONF_IPV6_CHECKS*/ - switch(ext_hdr_options_process()) { - case 0: - /*continue*/ - uip_next_hdr = &UIP_EXT_BUF->next; - uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; - break; - case 1: - /*silently discard*/ - goto drop; - case 2: - /* send icmp error message (created in ext_hdr_options_process) - * and discard*/ - goto send; - } + switch(ext_hdr_options_process()) { + case 0: + /*continue*/ + uip_next_hdr = &UIP_EXT_BUF->next; + uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; break; + case 1: + /*silently discard*/ + goto drop; + case 2: + /* send icmp error message (created in ext_hdr_options_process) + * and discard*/ + goto send; + } + break; case UIP_PROTO_DESTO: #if UIP_CONF_IPV6_CHECKS /* Destination option header. if we saw two already, drop */ @@ -1334,76 +1336,81 @@ uip_process(uint8_t flag) } #endif /*UIP_CONF_IPV6_CHECKS*/ switch(ext_hdr_options_process()) { - case 0: - /*continue*/ - uip_next_hdr = &UIP_EXT_BUF->next; - uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; - break; - case 1: - /*silently discard*/ - goto drop; - case 2: - /* send icmp error message (created in ext_hdr_options_process) - * and discard*/ - goto send; - } - break; - case UIP_PROTO_ROUTING: -#if UIP_CONF_IPV6_CHECKS - /* Routing header. If we saw one already, drop */ - if(uip_ext_bitmap & UIP_EXT_HDR_BITMAP_ROUTING) { - goto bad_hdr; - } else { - uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_ROUTING; - } -#endif /*UIP_CONF_IPV6_CHECKS*/ - /* - * Routing Header length field is in units of 8 bytes, excluding - * As per RFC2460 section 4.4, if routing type is unrecognized: - * if segments left = 0, ignore the header - * if segments left > 0, discard packet and send icmp error pointing - * to the routing type - */ - - PRINTF("Processing Routing header\n"); - if(UIP_ROUTING_BUF->seg_left > 0) { - uip_icmp6_error_output(ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, UIP_IPH_LEN + uip_ext_len + 2); - UIP_STAT(++uip_stat.ip.drop); - UIP_LOG("ip6: unrecognized routing type"); - goto send; - } - uip_next_hdr = &UIP_EXT_BUF->next; - uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; - break; - case UIP_PROTO_FRAG: - /* Fragmentation header:call the reassembly function, then leave */ -#if UIP_CONF_IPV6_REASSEMBLY - PRINTF("Processing frag header\n"); - uip_len = uip_reass(); - if(uip_len == 0) { + case 0: + /*continue*/ + uip_next_hdr = &UIP_EXT_BUF->next; + uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; + break; + case 1: + /*silently discard*/ goto drop; - } - if(uip_reassflags & UIP_REASS_FLAG_ERROR_MSG){ - /* we are not done with reassembly, this is an error message */ + case 2: + /* send icmp error message (created in ext_hdr_options_process) + * and discard*/ goto send; } - /*packet is reassembled, reset the next hdr to the beginning - of the IP header and restart the parsing of the reassembled pkt*/ - PRINTF("Processing reassembled packet\n"); - uip_ext_len = 0; - uip_ext_bitmap = 0; - uip_next_hdr = &UIP_IP_BUF->proto; break; + case UIP_PROTO_ROUTING: +#if UIP_CONF_IPV6_CHECKS + /* Routing header. If we saw one already, drop */ + if(uip_ext_bitmap & UIP_EXT_HDR_BITMAP_ROUTING) { + goto bad_hdr; + } else { + uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_ROUTING; + } +#endif /*UIP_CONF_IPV6_CHECKS*/ + /* + * Routing Header length field is in units of 8 bytes, excluding + * As per RFC2460 section 4.4, if routing type is unrecognized: + * if segments left = 0, ignore the header + * if segments left > 0, discard packet and send icmp error pointing + * to the routing type + */ + + PRINTF("Processing Routing header\n"); + if(UIP_ROUTING_BUF->seg_left > 0) { +#if UIP_CONF_IPV6_RPL && RPL_WITH_NON_STORING + if(rpl_process_srh_header()) { + goto send; /* Proceed to forwarding */ + } +#endif /* UIP_CONF_IPV6_RPL && RPL_WITH_NON_STORING */ + uip_icmp6_error_output(ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, UIP_IPH_LEN + uip_ext_len + 2); + UIP_STAT(++uip_stat.ip.drop); + UIP_LOG("ip6: unrecognized routing type"); + goto send; + } + uip_next_hdr = &UIP_EXT_BUF->next; + uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; + break; + case UIP_PROTO_FRAG: + /* Fragmentation header:call the reassembly function, then leave */ +#if UIP_CONF_IPV6_REASSEMBLY + PRINTF("Processing frag header\n"); + uip_len = uip_reass(); + if(uip_len == 0) { + goto drop; + } + if(uip_reassflags & UIP_REASS_FLAG_ERROR_MSG){ + /* we are not done with reassembly, this is an error message */ + goto send; + } + /*packet is reassembled, reset the next hdr to the beginning + of the IP header and restart the parsing of the reassembled pkt*/ + PRINTF("Processing reassembled packet\n"); + uip_ext_len = 0; + uip_ext_bitmap = 0; + uip_next_hdr = &UIP_IP_BUF->proto; + break; #else /* UIP_CONF_IPV6_REASSEMBLY */ - UIP_STAT(++uip_stat.ip.drop); - UIP_STAT(++uip_stat.ip.fragerr); - UIP_LOG("ip: fragment dropped."); - goto drop; + UIP_STAT(++uip_stat.ip.drop); + UIP_STAT(++uip_stat.ip.fragerr); + UIP_LOG("ip: fragment dropped."); + goto drop; #endif /* UIP_CONF_IPV6_REASSEMBLY */ - case UIP_PROTO_NONE: - goto drop; - default: - goto bad_hdr; + case UIP_PROTO_NONE: + goto drop; + default: + goto bad_hdr; } } bad_hdr: @@ -1470,9 +1477,10 @@ uip_process(uint8_t flag) #if UIP_UDP /* UDP input processing. */ - udp_input: + udp_input: remove_ext_hdr(); + UIP_IP_BUF->proto = UIP_PROTO_UDP; PRINTF("Receiving UDP packet\n"); @@ -1481,8 +1489,6 @@ uip_process(uint8_t flag) work. If the application sets uip_slen, it has a packet to send. */ #if UIP_UDP_CHECKSUMS - uip_len = uip_len - UIP_IPUDPH_LEN; - uip_appdata = &uip_buf[UIP_IPUDPH_LEN + UIP_LLH_LEN]; /* XXX hack: UDP/IPv6 receivers should drop packets with UDP checksum 0. Here, we explicitly receive UDP packets with checksum 0. This is to be able to debug code that for one reason or @@ -1495,8 +1501,6 @@ uip_process(uint8_t flag) uip_udpchksum()); goto drop; } -#else /* UIP_UDP_CHECKSUMS */ - uip_len = uip_len - UIP_IPUDPH_LEN; #endif /* UIP_UDP_CHECKSUMS */ /* Make sure that the UDP destination port number is not zero. */ @@ -1528,24 +1532,22 @@ uip_process(uint8_t flag) PRINTF("udp: no matching connection found\n"); UIP_STAT(++uip_stat.udp.drop); -#if UIP_UDP_SEND_UNREACH_NOPORT uip_icmp6_error_output(ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOPORT, 0); goto send; -#else - goto drop; -#endif - udp_found: + udp_found: PRINTF("In udp_found\n"); UIP_STAT(++uip_stat.udp.recv); + uip_len = uip_len - UIP_IPUDPH_LEN; + uip_appdata = &uip_buf[UIP_IPUDPH_LEN + UIP_LLH_LEN]; uip_conn = NULL; uip_flags = UIP_NEWDATA; uip_sappdata = uip_appdata = &uip_buf[UIP_IPUDPH_LEN + UIP_LLH_LEN]; uip_slen = 0; UIP_UDP_APPCALL(); - udp_send: + udp_send: PRINTF("In udp_send\n"); if(uip_slen == 0) { @@ -1590,9 +1592,10 @@ uip_process(uint8_t flag) #if UIP_TCP /* TCP input processing. */ - tcp_input: + tcp_input: remove_ext_hdr(); + UIP_IP_BUF->proto = UIP_PROTO_TCP; UIP_STAT(++uip_stat.tcp.recv); PRINTF("Receiving TCP packet\n"); @@ -1644,7 +1647,7 @@ uip_process(uint8_t flag) /* No matching connection found, so we send a RST packet. */ UIP_STAT(++uip_stat.tcp.synrst); - reset: + reset: PRINTF("In reset\n"); /* We do not send resets in response to resets. */ if(UIP_TCP_BUF->flags & TCP_RST) { @@ -1699,7 +1702,7 @@ uip_process(uint8_t flag) /* This label will be jumped to if we matched the incoming packet with a connection in LISTEN. In that case, we should create a new connection and send a SYNACK in return. */ - found_listen: + found_listen: PRINTF("In found listen\n"); /* First we check if there are any connections avaliable. Unused connections are kept in the same table as used connections, but @@ -1789,13 +1792,13 @@ uip_process(uint8_t flag) /* Our response will be a SYNACK. */ #if UIP_ACTIVE_OPEN - tcp_send_synack: + tcp_send_synack: UIP_TCP_BUF->flags = TCP_ACK; - tcp_send_syn: + tcp_send_syn: UIP_TCP_BUF->flags |= TCP_SYN; #else /* UIP_ACTIVE_OPEN */ - tcp_send_synack: + tcp_send_synack: UIP_TCP_BUF->flags = TCP_SYN | TCP_ACK; #endif /* UIP_ACTIVE_OPEN */ @@ -1810,7 +1813,7 @@ uip_process(uint8_t flag) goto tcp_send; /* This label will be jumped to if we found an active connection. */ - found: + found: PRINTF("In found\n"); uip_conn = uip_connr; uip_flags = 0; @@ -1904,96 +1907,96 @@ uip_process(uint8_t flag) /* Do different things depending on in what state the connection is. */ switch(uip_connr->tcpstateflags & UIP_TS_MASK) { - /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not + /* CLOSED and LISTEN are not handled here. CLOSE_WAIT is not implemented, since we force the application to close when the peer sends a FIN (hence the application goes directly from ESTABLISHED to LAST_ACK). */ - case UIP_SYN_RCVD: - /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and + case UIP_SYN_RCVD: + /* In SYN_RCVD we have sent out a SYNACK in response to a SYN, and we are waiting for an ACK that acknowledges the data we sent out the last time. Therefore, we want to have the UIP_ACKDATA flag set. If so, we enter the ESTABLISHED state. */ - if(uip_flags & UIP_ACKDATA) { - uip_connr->tcpstateflags = UIP_ESTABLISHED; - uip_flags = UIP_CONNECTED; - uip_connr->len = 0; - if(uip_len > 0) { - uip_flags |= UIP_NEWDATA; - uip_add_rcv_nxt(uip_len); - } - uip_slen = 0; - UIP_APPCALL(); - goto appsend; + if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_ESTABLISHED; + uip_flags = UIP_CONNECTED; + uip_connr->len = 0; + if(uip_len > 0) { + uip_flags |= UIP_NEWDATA; + uip_add_rcv_nxt(uip_len); } - /* We need to retransmit the SYNACK */ - if((UIP_TCP_BUF->flags & TCP_CTL) == TCP_SYN) { - goto tcp_send_synack; - } - goto drop; + uip_slen = 0; + UIP_APPCALL(); + goto appsend; + } + /* We need to retransmit the SYNACK */ + if((UIP_TCP_BUF->flags & TCP_CTL) == TCP_SYN) { + goto tcp_send_synack; + } + goto drop; #if UIP_ACTIVE_OPEN - case UIP_SYN_SENT: - /* In SYN_SENT, we wait for a SYNACK that is sent in response to + case UIP_SYN_SENT: + /* In SYN_SENT, we wait for a SYNACK that is sent in response to our SYN. The rcv_nxt is set to sequence number in the SYNACK plus one, and we send an ACK. We move into the ESTABLISHED state. */ - if((uip_flags & UIP_ACKDATA) && - (UIP_TCP_BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) { + if((uip_flags & UIP_ACKDATA) && + (UIP_TCP_BUF->flags & TCP_CTL) == (TCP_SYN | TCP_ACK)) { - /* Parse the TCP MSS option, if present. */ - if((UIP_TCP_BUF->tcpoffset & 0xf0) > 0x50) { - for(c = 0; c < ((UIP_TCP_BUF->tcpoffset >> 4) - 5) << 2 ;) { - opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c]; - if(opt == TCP_OPT_END) { - /* End of options. */ - break; - } else if(opt == TCP_OPT_NOOP) { - ++c; - /* NOP option. */ - } else if(opt == TCP_OPT_MSS && - uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { - /* An MSS option with the right option length. */ - tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | + /* Parse the TCP MSS option, if present. */ + if((UIP_TCP_BUF->tcpoffset & 0xf0) > 0x50) { + for(c = 0; c < ((UIP_TCP_BUF->tcpoffset >> 4) - 5) << 2 ;) { + opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c]; + if(opt == TCP_OPT_END) { + /* End of options. */ + break; + } else if(opt == TCP_OPT_NOOP) { + ++c; + /* NOP option. */ + } else if(opt == TCP_OPT_MSS && + uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) { + /* An MSS option with the right option length. */ + tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) | uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c]; - uip_connr->initialmss = + uip_connr->initialmss = uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16; - /* And we are done processing options. */ - break; - } else { - /* All other options have a length field, so that we easily + /* And we are done processing options. */ + break; + } else { + /* All other options have a length field, so that we easily can skip past them. */ - if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { - /* If the length field is zero, the options are malformed + if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) { + /* If the length field is zero, the options are malformed and we don't process them further. */ - break; - } - c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; + break; } + c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c]; } } - uip_connr->tcpstateflags = UIP_ESTABLISHED; - uip_connr->rcv_nxt[0] = UIP_TCP_BUF->seqno[0]; - uip_connr->rcv_nxt[1] = UIP_TCP_BUF->seqno[1]; - uip_connr->rcv_nxt[2] = UIP_TCP_BUF->seqno[2]; - uip_connr->rcv_nxt[3] = UIP_TCP_BUF->seqno[3]; - uip_add_rcv_nxt(1); - uip_flags = UIP_CONNECTED | UIP_NEWDATA; - uip_connr->len = 0; - uip_clear_buf(); - uip_slen = 0; - UIP_APPCALL(); - goto appsend; } - /* Inform the application that the connection failed */ - uip_flags = UIP_ABORT; + uip_connr->tcpstateflags = UIP_ESTABLISHED; + uip_connr->rcv_nxt[0] = UIP_TCP_BUF->seqno[0]; + uip_connr->rcv_nxt[1] = UIP_TCP_BUF->seqno[1]; + uip_connr->rcv_nxt[2] = UIP_TCP_BUF->seqno[2]; + uip_connr->rcv_nxt[3] = UIP_TCP_BUF->seqno[3]; + uip_add_rcv_nxt(1); + uip_flags = UIP_CONNECTED | UIP_NEWDATA; + uip_connr->len = 0; + uip_clear_buf(); + uip_slen = 0; UIP_APPCALL(); - /* The connection is closed after we send the RST */ - uip_conn->tcpstateflags = UIP_CLOSED; - goto reset; + goto appsend; + } + /* Inform the application that the connection failed */ + uip_flags = UIP_ABORT; + UIP_APPCALL(); + /* The connection is closed after we send the RST */ + uip_conn->tcpstateflags = UIP_CLOSED; + goto reset; #endif /* UIP_ACTIVE_OPEN */ - case UIP_ESTABLISHED: - /* In the ESTABLISHED state, we call upon the application to feed + case UIP_ESTABLISHED: + /* In the ESTABLISHED state, we call upon the application to feed data into the uip_buf. If the UIP_ACKDATA flag is set, the application should put new data into the buffer, otherwise we are retransmitting an old segment, and the application should put that @@ -2004,56 +2007,56 @@ uip_process(uint8_t flag) state. We require that there is no outstanding data; otherwise the sequence numbers will be screwed up. */ - if(UIP_TCP_BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) { - if(uip_outstanding(uip_connr)) { - goto drop; - } - uip_add_rcv_nxt(1 + uip_len); - uip_flags |= UIP_CLOSE; - if(uip_len > 0) { - uip_flags |= UIP_NEWDATA; - } - UIP_APPCALL(); - uip_connr->len = 1; - uip_connr->tcpstateflags = UIP_LAST_ACK; - uip_connr->nrtx = 0; + if(UIP_TCP_BUF->flags & TCP_FIN && !(uip_connr->tcpstateflags & UIP_STOPPED)) { + if(uip_outstanding(uip_connr)) { + goto drop; + } + uip_add_rcv_nxt(1 + uip_len); + uip_flags |= UIP_CLOSE; + if(uip_len > 0) { + uip_flags |= UIP_NEWDATA; + } + UIP_APPCALL(); + uip_connr->len = 1; + uip_connr->tcpstateflags = UIP_LAST_ACK; + uip_connr->nrtx = 0; tcp_send_finack: - UIP_TCP_BUF->flags = TCP_FIN | TCP_ACK; - goto tcp_send_nodata; - } + UIP_TCP_BUF->flags = TCP_FIN | TCP_ACK; + goto tcp_send_nodata; + } - /* Check the URG flag. If this is set, the segment carries urgent + /* Check the URG flag. If this is set, the segment carries urgent data that we must pass to the application. */ - if((UIP_TCP_BUF->flags & TCP_URG) != 0) { + if((UIP_TCP_BUF->flags & TCP_URG) != 0) { #if UIP_URGDATA > 0 - uip_urglen = (UIP_TCP_BUF->urgp[0] << 8) | UIP_TCP_BUF->urgp[1]; - if(uip_urglen > uip_len) { - /* There is more urgent data in the next segment to come. */ - uip_urglen = uip_len; - } - uip_add_rcv_nxt(uip_urglen); - uip_len -= uip_urglen; - uip_urgdata = uip_appdata; - uip_appdata += uip_urglen; - } else { - uip_urglen = 0; -#else /* UIP_URGDATA > 0 */ - uip_appdata = ((char *)uip_appdata) + ((UIP_TCP_BUF->urgp[0] << 8) | UIP_TCP_BUF->urgp[1]); - uip_len -= (UIP_TCP_BUF->urgp[0] << 8) | UIP_TCP_BUF->urgp[1]; -#endif /* UIP_URGDATA > 0 */ + uip_urglen = (UIP_TCP_BUF->urgp[0] << 8) | UIP_TCP_BUF->urgp[1]; + if(uip_urglen > uip_len) { + /* There is more urgent data in the next segment to come. */ + uip_urglen = uip_len; } + uip_add_rcv_nxt(uip_urglen); + uip_len -= uip_urglen; + uip_urgdata = uip_appdata; + uip_appdata += uip_urglen; + } else { + uip_urglen = 0; +#else /* UIP_URGDATA > 0 */ + uip_appdata = ((char *)uip_appdata) + ((UIP_TCP_BUF->urgp[0] << 8) | UIP_TCP_BUF->urgp[1]); + uip_len -= (UIP_TCP_BUF->urgp[0] << 8) | UIP_TCP_BUF->urgp[1]; +#endif /* UIP_URGDATA > 0 */ + } - /* If uip_len > 0 we have TCP data in the packet, and we flag this + /* If uip_len > 0 we have TCP data in the packet, and we flag this by setting the UIP_NEWDATA flag and update the sequence number we acknowledge. If the application has stopped the dataflow using uip_stop(), we must not accept any data packets from the remote host. */ - if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) { - uip_flags |= UIP_NEWDATA; - uip_add_rcv_nxt(uip_len); - } + if(uip_len > 0 && !(uip_connr->tcpstateflags & UIP_STOPPED)) { + uip_flags |= UIP_NEWDATA; + uip_add_rcv_nxt(uip_len); + } - /* Check if the available buffer space advertised by the other end + /* Check if the available buffer space advertised by the other end is smaller than the initial MSS for this connection. If so, we set the current MSS to the window size to ensure that the application does not send more data than the other end can @@ -2064,15 +2067,15 @@ uip_process(uint8_t flag) of data. This data will not be acknowledged by the receiver, and the application will retransmit it. This is called the "persistent timer" and uses the retransmission mechanim. - */ - tmp16 = ((uint16_t)UIP_TCP_BUF->wnd[0] << 8) + (uint16_t)UIP_TCP_BUF->wnd[1]; - if(tmp16 > uip_connr->initialmss || - tmp16 == 0) { - tmp16 = uip_connr->initialmss; - } - uip_connr->mss = tmp16; + */ + tmp16 = ((uint16_t)UIP_TCP_BUF->wnd[0] << 8) + (uint16_t)UIP_TCP_BUF->wnd[1]; + if(tmp16 > uip_connr->initialmss || + tmp16 == 0) { + tmp16 = uip_connr->initialmss; + } + uip_connr->mss = tmp16; - /* If this packet constitutes an ACK for outstanding data (flagged + /* If this packet constitutes an ACK for outstanding data (flagged by the UIP_ACKDATA flag, we should call the application since it might want to send more data. If the incoming packet had data from the peer (as flagged by the UIP_NEWDATA flag), the @@ -2088,166 +2091,166 @@ uip_process(uint8_t flag) put into the uip_appdata and the length of the data should be put into uip_len. If the application don't have any data to send, uip_len must be set to 0. */ - if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) { - uip_slen = 0; - UIP_APPCALL(); + if(uip_flags & (UIP_NEWDATA | UIP_ACKDATA)) { + uip_slen = 0; + UIP_APPCALL(); appsend: - if(uip_flags & UIP_ABORT) { - uip_slen = 0; - uip_connr->tcpstateflags = UIP_CLOSED; - UIP_TCP_BUF->flags = TCP_RST | TCP_ACK; - goto tcp_send_nodata; - } + if(uip_flags & UIP_ABORT) { + uip_slen = 0; + uip_connr->tcpstateflags = UIP_CLOSED; + UIP_TCP_BUF->flags = TCP_RST | TCP_ACK; + goto tcp_send_nodata; + } - if(uip_flags & UIP_CLOSE) { - uip_slen = 0; - uip_connr->len = 1; - uip_connr->tcpstateflags = UIP_FIN_WAIT_1; - uip_connr->nrtx = 0; - UIP_TCP_BUF->flags = TCP_FIN | TCP_ACK; - goto tcp_send_nodata; - } + if(uip_flags & UIP_CLOSE) { + uip_slen = 0; + uip_connr->len = 1; + uip_connr->tcpstateflags = UIP_FIN_WAIT_1; + uip_connr->nrtx = 0; + UIP_TCP_BUF->flags = TCP_FIN | TCP_ACK; + goto tcp_send_nodata; + } - /* If uip_slen > 0, the application has data to be sent. */ - if(uip_slen > 0) { + /* If uip_slen > 0, the application has data to be sent. */ + if(uip_slen > 0) { - /* If the connection has acknowledged data, the contents of + /* If the connection has acknowledged data, the contents of the ->len variable should be discarded. */ - if((uip_flags & UIP_ACKDATA) != 0) { - uip_connr->len = 0; - } + if((uip_flags & UIP_ACKDATA) != 0) { + uip_connr->len = 0; + } - /* If the ->len variable is non-zero the connection has + /* If the ->len variable is non-zero the connection has already data in transit and cannot send anymore right now. */ - if(uip_connr->len == 0) { + if(uip_connr->len == 0) { - /* The application cannot send more than what is allowed by + /* The application cannot send more than what is allowed by the mss (the minumum of the MSS and the available window). */ - if(uip_slen > uip_connr->mss) { - uip_slen = uip_connr->mss; - } + if(uip_slen > uip_connr->mss) { + uip_slen = uip_connr->mss; + } - /* Remember how much data we send out now so that we know + /* Remember how much data we send out now so that we know when everything has been acknowledged. */ - uip_connr->len = uip_slen; - } else { + uip_connr->len = uip_slen; + } else { - /* If the application already had unacknowledged data, we + /* If the application already had unacknowledged data, we make sure that the application does not send (i.e., retransmit) out more than it previously sent out. */ - uip_slen = uip_connr->len; - } + uip_slen = uip_connr->len; } - uip_connr->nrtx = 0; + } + uip_connr->nrtx = 0; apprexmit: - uip_appdata = uip_sappdata; + uip_appdata = uip_sappdata; - /* If the application has data to be sent, or if the incoming + /* If the application has data to be sent, or if the incoming packet had new data in it, we must send out a packet. */ - if(uip_slen > 0 && uip_connr->len > 0) { - /* Add the length of the IP and TCP headers. */ - uip_len = uip_connr->len + UIP_TCPIP_HLEN; - /* We always set the ACK flag in response packets. */ - UIP_TCP_BUF->flags = TCP_ACK | TCP_PSH; - /* Send the packet. */ - goto tcp_send_noopts; - } - /* If there is no data to send, just send out a pure ACK if + if(uip_slen > 0 && uip_connr->len > 0) { + /* Add the length of the IP and TCP headers. */ + uip_len = uip_connr->len + UIP_TCPIP_HLEN; + /* We always set the ACK flag in response packets. */ + UIP_TCP_BUF->flags = TCP_ACK | TCP_PSH; + /* Send the packet. */ + goto tcp_send_noopts; + } + /* If there is no data to send, just send out a pure ACK if there is newdata. */ - if(uip_flags & UIP_NEWDATA) { - uip_len = UIP_TCPIP_HLEN; - UIP_TCP_BUF->flags = TCP_ACK; - goto tcp_send_noopts; - } + if(uip_flags & UIP_NEWDATA) { + uip_len = UIP_TCPIP_HLEN; + UIP_TCP_BUF->flags = TCP_ACK; + goto tcp_send_noopts; } - goto drop; - case UIP_LAST_ACK: - /* We can close this connection if the peer has acknowledged our + } + goto drop; + case UIP_LAST_ACK: + /* We can close this connection if the peer has acknowledged our FIN. This is indicated by the UIP_ACKDATA flag. */ - if(uip_flags & UIP_ACKDATA) { - uip_connr->tcpstateflags = UIP_CLOSED; - uip_flags = UIP_CLOSE; - UIP_APPCALL(); - } - break; + if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_CLOSED; + uip_flags = UIP_CLOSE; + UIP_APPCALL(); + } + break; - case UIP_FIN_WAIT_1: - /* The application has closed the connection, but the remote host + case UIP_FIN_WAIT_1: + /* The application has closed the connection, but the remote host hasn't closed its end yet. Thus we do nothing but wait for a FIN from the other side. */ - if(uip_len > 0) { - uip_add_rcv_nxt(uip_len); - } - if(UIP_TCP_BUF->flags & TCP_FIN) { - if(uip_flags & UIP_ACKDATA) { - uip_connr->tcpstateflags = UIP_TIME_WAIT; - uip_connr->timer = 0; - uip_connr->len = 0; - } else { - uip_connr->tcpstateflags = UIP_CLOSING; - } - uip_add_rcv_nxt(1); - uip_flags = UIP_CLOSE; - UIP_APPCALL(); - goto tcp_send_ack; - } else if(uip_flags & UIP_ACKDATA) { - uip_connr->tcpstateflags = UIP_FIN_WAIT_2; - uip_connr->len = 0; - goto drop; - } - if(uip_len > 0) { - goto tcp_send_ack; - } - goto drop; - - case UIP_FIN_WAIT_2: - if(uip_len > 0) { - uip_add_rcv_nxt(uip_len); - } - if(UIP_TCP_BUF->flags & TCP_FIN) { - uip_connr->tcpstateflags = UIP_TIME_WAIT; - uip_connr->timer = 0; - uip_add_rcv_nxt(1); - uip_flags = UIP_CLOSE; - UIP_APPCALL(); - goto tcp_send_ack; - } - if(uip_len > 0) { - goto tcp_send_ack; - } - goto drop; - - case UIP_TIME_WAIT: - goto tcp_send_ack; - - case UIP_CLOSING: + if(uip_len > 0) { + uip_add_rcv_nxt(uip_len); + } + if(UIP_TCP_BUF->flags & TCP_FIN) { if(uip_flags & UIP_ACKDATA) { uip_connr->tcpstateflags = UIP_TIME_WAIT; uip_connr->timer = 0; + uip_connr->len = 0; + } else { + uip_connr->tcpstateflags = UIP_CLOSING; } + uip_add_rcv_nxt(1); + uip_flags = UIP_CLOSE; + UIP_APPCALL(); + goto tcp_send_ack; + } else if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_FIN_WAIT_2; + uip_connr->len = 0; + goto drop; + } + if(uip_len > 0) { + goto tcp_send_ack; + } + goto drop; + + case UIP_FIN_WAIT_2: + if(uip_len > 0) { + uip_add_rcv_nxt(uip_len); + } + if(UIP_TCP_BUF->flags & TCP_FIN) { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + uip_add_rcv_nxt(1); + uip_flags = UIP_CLOSE; + UIP_APPCALL(); + goto tcp_send_ack; + } + if(uip_len > 0) { + goto tcp_send_ack; + } + goto drop; + + case UIP_TIME_WAIT: + goto tcp_send_ack; + + case UIP_CLOSING: + if(uip_flags & UIP_ACKDATA) { + uip_connr->tcpstateflags = UIP_TIME_WAIT; + uip_connr->timer = 0; + } } goto drop; /* We jump here when we are ready to send the packet, and just want to set the appropriate TCP sequence numbers in the TCP header. */ - tcp_send_ack: + tcp_send_ack: UIP_TCP_BUF->flags = TCP_ACK; - tcp_send_nodata: + tcp_send_nodata: uip_len = UIP_IPTCPH_LEN; - tcp_send_noopts: + tcp_send_noopts: UIP_TCP_BUF->tcpoffset = (UIP_TCPH_LEN / 4) << 4; /* We're done with the input processing. We are now ready to send a reply. Our job is to fill in all the fields of the TCP and IP headers before calculating the checksum and finally send the packet. */ - tcp_send: + tcp_send: PRINTF("In tcp_send\n"); UIP_TCP_BUF->ackno[0] = uip_connr->rcv_nxt[0]; @@ -2280,7 +2283,7 @@ uip_process(uint8_t flag) UIP_TCP_BUF->wnd[1] = ((UIP_RECEIVE_WINDOW) & 0xff); } - tcp_send_noconn: + tcp_send_noconn: UIP_IP_BUF->proto = UIP_PROTO_TCP; UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; @@ -2296,21 +2299,21 @@ uip_process(uint8_t flag) #endif /* UIP_TCP */ #if UIP_UDP - ip_send_nolen: + ip_send_nolen: #endif UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0x00; UIP_IP_BUF->flow = 0x00; - send: + send: PRINTF("Sending packet with length %d (%d)\n", uip_len, - (UIP_IP_BUF->len[0] << 8) | UIP_IP_BUF->len[1]); + (UIP_IP_BUF->len[0] << 8) | UIP_IP_BUF->len[1]); UIP_STAT(++uip_stat.ip.sent); /* Return and let the caller do the actual transmission. */ uip_flags = 0; return; - drop: + drop: uip_clear_buf(); uip_ext_bitmap = 0; uip_flags = 0; @@ -2336,8 +2339,8 @@ uip_send(const void *data, int len) if(uip_sappdata != NULL) { copylen = MIN(len, UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN - - (int)((char *)uip_sappdata - - (char *)&uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN])); + (int)((char *)uip_sappdata - + (char *)&uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN])); } else { copylen = MIN(len, UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN); } @@ -2346,7 +2349,7 @@ uip_send(const void *data, int len) if(data != uip_sappdata) { if(uip_sappdata == NULL) { memcpy((char *)&uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN], - (data), uip_slen); + (data), uip_slen); } else { memcpy(uip_sappdata, (data), uip_slen); } diff --git a/core/net/link-stats.c b/core/net/link-stats.c new file mode 100644 index 000000000..a2f99e729 --- /dev/null +++ b/core/net/link-stats.c @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2015, SICS Swedish ICT. + * 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. + * + * + * Authors: Simon Duquennoy + */ + +#include "contiki.h" +#include "sys/clock.h" +#include "net/packetbuf.h" +#include "net/nbr-table.h" +#include "net/link-stats.h" +#include + +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/* Half time for the freshness counter, in minutes */ +#define FRESHNESS_HALF_LIFE 20 +/* Statistics are fresh if the freshness counter is FRESHNESS_TARGET or more */ +#define FRESHNESS_TARGET 4 +/* Maximum value for the freshness counter */ +#define FRESHNESS_MAX 16 +/* Statistics with no update in FRESHNESS_EXPIRATION_TIMEOUT is not fresh */ +#define FRESHNESS_EXPIRATION_TIME (10 * 60 * CLOCK_SECOND) + +/* EWMA (exponential moving average) used to maintain statistics over time */ +#define EWMA_SCALE 100 +#define EWMA_ALPHA 15 +#define EWMA_BOOTSTRAP_ALPHA 30 + +/* ETX fixed point divisor. 128 is the value used by RPL (RFC 6551 and RFC 6719) */ +#define ETX_DIVISOR LINK_STATS_ETX_DIVISOR +/* Number of Tx used to update the ETX EWMA in case of no-ACK */ +#define ETX_NOACK_PENALTY 10 +/* Initial ETX value */ +#define ETX_INIT 2 + +/* Per-neighbor link statistics table */ +NBR_TABLE(struct link_stats, link_stats); + +/* Called every FRESHNESS_HALF_LIFE minutes */ +struct ctimer periodic_timer; + +/* Used to initialize ETX before any transmission occurs. In order to + * infer the initial ETX from the RSSI of previously received packets, use: */ +/* #define LINK_STATS_CONF_INIT_ETX(stats) guess_etx_from_rssi(stats) */ + +#ifdef LINK_STATS_CONF_INIT_ETX +#define LINK_STATS_INIT_ETX(stats) LINK_STATS_CONF_INIT_ETX(stats) +#else /* LINK_STATS_INIT_ETX */ +#define LINK_STATS_INIT_ETX(stats) (ETX_INIT * ETX_DIVISOR) +#endif /* LINK_STATS_INIT_ETX */ + +/*---------------------------------------------------------------------------*/ +/* Returns the neighbor's link stats */ +const struct link_stats * +link_stats_from_lladdr(const linkaddr_t *lladdr) +{ + return nbr_table_get_from_lladdr(link_stats, lladdr); +} +/*---------------------------------------------------------------------------*/ +/* Are the statistics fresh? */ +int +link_stats_is_fresh(const struct link_stats *stats) +{ + return (stats != NULL) + && clock_time() - stats->last_tx_time < FRESHNESS_EXPIRATION_TIME + && stats->freshness >= FRESHNESS_TARGET; +} +/*---------------------------------------------------------------------------*/ +uint16_t +guess_etx_from_rssi(const struct link_stats *stats) +{ + if(stats != NULL) { + if(stats->rssi == 0) { + return ETX_INIT * ETX_DIVISOR; + } else { + /* A rough estimate of PRR from RSSI, as a linear function where: + * RSSI >= -60 results in PRR of 1 + * RSSI <= -90 results in PRR of 0 + * prr = (bounded_rssi - RSSI_LOW) / (RSSI_DIFF) + * etx = ETX_DIVOSOR / ((bounded_rssi - RSSI_LOW) / RSSI_DIFF) + * etx = (RSSI_DIFF * ETX_DIVOSOR) / (bounded_rssi - RSSI_LOW) + * */ +#define ETX_INIT_MAX 3 +#define RSSI_HIGH -60 +#define RSSI_LOW -90 +#define RSSI_DIFF (RSSI_HIGH - RSSI_LOW) + uint16_t etx; + int16_t bounded_rssi = stats->rssi; + bounded_rssi = MIN(bounded_rssi, RSSI_HIGH); + bounded_rssi = MAX(bounded_rssi, RSSI_LOW + 1); + etx = RSSI_DIFF * ETX_DIVISOR / (bounded_rssi - RSSI_LOW); + return MIN(etx, ETX_INIT_MAX * ETX_DIVISOR); + } + } + return 0xffff; +} +/*---------------------------------------------------------------------------*/ +/* Packet sent callback. Updates stats for transmissions to lladdr */ +void +link_stats_packet_sent(const linkaddr_t *lladdr, int status, int numtx) +{ + struct link_stats *stats; + uint16_t packet_etx; + uint8_t ewma_alpha; + + if(status != MAC_TX_OK && status != MAC_TX_NOACK) { + /* Do not penalize the ETX when collisions or transmission errors occur. */ + return; + } + + stats = nbr_table_get_from_lladdr(link_stats, lladdr); + if(stats == NULL) { + /* Add the neighbor */ + stats = nbr_table_add_lladdr(link_stats, lladdr, NBR_TABLE_REASON_LINK_STATS, NULL); + if(stats != NULL) { + stats->etx = LINK_STATS_INIT_ETX(stats); + } else { + return; /* No space left, return */ + } + } + + /* Update last timestamp and freshness */ + stats->last_tx_time = clock_time(); + stats->freshness = MIN(stats->freshness + numtx, FRESHNESS_MAX); + + /* ETX used for this update */ + packet_etx = ((status == MAC_TX_NOACK) ? ETX_NOACK_PENALTY : numtx) * ETX_DIVISOR; + /* ETX alpha used for this update */ + ewma_alpha = link_stats_is_fresh(stats) ? EWMA_ALPHA : EWMA_BOOTSTRAP_ALPHA; + + /* Compute EWMA and update ETX */ + stats->etx = ((uint32_t)stats->etx * (EWMA_SCALE - ewma_alpha) + + (uint32_t)packet_etx * ewma_alpha) / EWMA_SCALE; +} +/*---------------------------------------------------------------------------*/ +/* Packet input callback. Updates statistics for receptions on a given link */ +void +link_stats_input_callback(const linkaddr_t *lladdr) +{ + struct link_stats *stats; + int16_t packet_rssi = packetbuf_attr(PACKETBUF_ATTR_RSSI); + + stats = nbr_table_get_from_lladdr(link_stats, lladdr); + if(stats == NULL) { + /* Add the neighbor */ + stats = nbr_table_add_lladdr(link_stats, lladdr, NBR_TABLE_REASON_LINK_STATS, NULL); + if(stats != NULL) { + /* Initialize */ + stats->rssi = packet_rssi; + stats->etx = LINK_STATS_INIT_ETX(stats); + } + return; + } + + /* Update RSSI EWMA */ + stats->rssi = ((int32_t)stats->rssi * (EWMA_SCALE - EWMA_ALPHA) + + (int32_t)packet_rssi * EWMA_ALPHA) / EWMA_SCALE; +} +/*---------------------------------------------------------------------------*/ +/* Periodic timer called every FRESHNESS_HALF_LIFE minutes */ +static void +periodic(void *ptr) +{ + /* Age (by halving) freshness counter of all neighbors */ + struct link_stats *stats; + ctimer_reset(&periodic_timer); + for(stats = nbr_table_head(link_stats); stats != NULL; stats = nbr_table_next(link_stats, stats)) { + stats->freshness >>= 1; + } +} +/*---------------------------------------------------------------------------*/ +/* Initializes link-stats module */ +void +link_stats_init(void) +{ + nbr_table_register(link_stats, NULL); + ctimer_set(&periodic_timer, 60 * CLOCK_SECOND * FRESHNESS_HALF_LIFE, + periodic, NULL); +} diff --git a/core/net/link-stats.h b/core/net/link-stats.h new file mode 100644 index 000000000..d28a1c1a4 --- /dev/null +++ b/core/net/link-stats.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015, SICS Swedish ICT. + * 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. + * + * + * Authors: Simon Duquennoy + */ + +#ifndef LINK_STATS_H_ +#define LINK_STATS_H_ + +#include "core/net/linkaddr.h" + +/* ETX fixed point divisor. 128 is the value used by RPL (RFC 6551 and RFC 6719) */ +#ifdef LINK_STATS_CONF_ETX_DIVISOR +#define LINK_STATS_ETX_DIVISOR LINK_STATS_CONF_ETX_DIVISOR +#else /* LINK_STATS_CONF_ETX_DIVISOR */ +#define LINK_STATS_ETX_DIVISOR 128 +#endif /* LINK_STATS_CONF_ETX_DIVISOR */ + +/* All statistics of a given link */ +struct link_stats { + uint16_t etx; /* ETX using ETX_DIVISOR as fixed point divisor */ + int16_t rssi; /* RSSI (received signal strength) */ + uint8_t freshness; /* Freshness of the statistics */ + clock_time_t last_tx_time; /* Last Tx timestamp */ +}; + +/* Returns the neighbor's link statistics */ +const struct link_stats *link_stats_from_lladdr(const linkaddr_t *lladdr); +/* Are the statistics fresh? */ +int link_stats_is_fresh(const struct link_stats *stats); + +/* Initializes link-stats module */ +void link_stats_init(void); +/* Packet sent callback. Updates statistics for transmissions on a given link */ +void link_stats_packet_sent(const linkaddr_t *lladdr, int status, int numtx); +/* Packet input callback. Updates statistics for receptions on a given link */ +void link_stats_input_callback(const linkaddr_t *lladdr); + +#endif /* LINK_STATS_H_ */ diff --git a/core/net/llsec/README.md b/core/net/llsec/README.md new file mode 100644 index 000000000..a5ac5854e --- /dev/null +++ b/core/net/llsec/README.md @@ -0,0 +1,5 @@ +Link layer security is implemented as a new netstack layer, which is located in between the MAC and the NETWORK layer. The interface of LLSEC drivers is defined in [llsec.h](llsec.h). Additionally, LLSEC drivers may define a special [FRAMER](../mac/framer.h), which calls the actual FRAMER underneath. By default, the LLSEC driver `nullsec` is used, which does nothing. + +# TODO + +* Most main files do not call LLSEC.init, yet \ No newline at end of file diff --git a/core/net/llsec/anti-replay.c b/core/net/llsec/anti-replay.c index 7c392bff7..a59f6b4c8 100644 --- a/core/net/llsec/anti-replay.c +++ b/core/net/llsec/anti-replay.c @@ -45,6 +45,9 @@ #include "net/llsec/anti-replay.h" #include "net/packetbuf.h" +#include "net/llsec/llsec802154.h" + +#if LLSEC802154_USES_FRAME_COUNTER /* This node's current frame counter value */ static uint32_t counter; @@ -107,5 +110,6 @@ anti_replay_was_replayed(struct anti_replay_info *info) } } /*---------------------------------------------------------------------------*/ +#endif /* LLSEC802154_USES_FRAME_COUNTER */ /** @} */ diff --git a/core/net/llsec/ccm-star-packetbuf.c b/core/net/llsec/ccm-star-packetbuf.c index 61e681b1c..d5d077301 100644 --- a/core/net/llsec/ccm-star-packetbuf.c +++ b/core/net/llsec/ccm-star-packetbuf.c @@ -41,8 +41,11 @@ #include "llsec/ccm-star-packetbuf.h" #include "net/linkaddr.h" #include "net/packetbuf.h" +#include "net/llsec/llsec802154.h" #include +#if LLSEC802154_USES_AUX_HEADER && LLSEC802154_USES_FRAME_COUNTER + /*---------------------------------------------------------------------------*/ static const uint8_t * get_extended_address(const linkaddr_t *addr) @@ -76,3 +79,4 @@ ccm_star_packetbuf_set_nonce(uint8_t *nonce, int forward) nonce[12] = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL); } /*---------------------------------------------------------------------------*/ +#endif /* LLSEC802154_USES_AUX_HEADER && LLSEC802154_USES_FRAME_COUNTER */ diff --git a/core/net/llsec/llsec802154.h b/core/net/llsec/llsec802154.h index 2ccd30515..acbba1f9d 100644 --- a/core/net/llsec/llsec802154.h +++ b/core/net/llsec/llsec802154.h @@ -56,28 +56,13 @@ #include "net/mac/frame802154.h" #include "net/ip/uip.h" -#ifdef LLSEC802154_CONF_SECURITY_LEVEL -#define LLSEC802154_SECURITY_LEVEL LLSEC802154_CONF_SECURITY_LEVEL -#else /* LLSEC802154_CONF_SECURITY_LEVEL */ -#define LLSEC802154_SECURITY_LEVEL FRAME802154_SECURITY_LEVEL_NONE -#endif /* LLSEC802154_CONF_SECURITY_LEVEL */ +#ifdef LLSEC802154_CONF_ENABLED +#define LLSEC802154_ENABLED LLSEC802154_CONF_ENABLED +#else /* LLSEC802154_CONF_ENABLED */ +#define LLSEC802154_ENABLED 0 +#endif /* LLSEC802154_CONF_ENABLED */ -#if ((LLSEC802154_SECURITY_LEVEL < 0) || (LLSEC802154_SECURITY_LEVEL > 7)) -#error "unsupported security level" -#endif - -#define LLSEC802154_SECURITY_LEVEL_MIC (LLSEC802154_SECURITY_LEVEL & 3) -#if LLSEC802154_SECURITY_LEVEL_MIC -#define LLSEC802154_MIC_LENGTH (2 << LLSEC802154_SECURITY_LEVEL_MIC) -#else -#define LLSEC802154_MIC_LENGTH 0 -#endif - -#ifdef LLSEC802154_CONF_USES_ENCRYPTION -#define LLSEC802154_USES_ENCRYPTION LLSEC802154_CONF_USES_ENCRYPTION -#else /* LLSEC802154_CONF_USES_ENCRYPTION */ -#define LLSEC802154_USES_ENCRYPTION (LLSEC802154_SECURITY_LEVEL & (1 << 2)) -#endif /* LLSEC802154_CONF_USES_ENCRYPTION */ +#define LLSEC802154_MIC_LEN(sec_lvl) (2 << (sec_lvl & 3)) #ifdef LLSEC802154_CONF_USES_EXPLICIT_KEYS #define LLSEC802154_USES_EXPLICIT_KEYS LLSEC802154_CONF_USES_EXPLICIT_KEYS @@ -88,9 +73,15 @@ #ifdef LLSEC802154_CONF_USES_FRAME_COUNTER #define LLSEC802154_USES_FRAME_COUNTER LLSEC802154_CONF_USES_FRAME_COUNTER #else /* LLSEC802154_CONF_USES_FRAME_COUNTER */ -#define LLSEC802154_USES_FRAME_COUNTER (LLSEC802154_SECURITY_LEVEL != FRAME802154_SECURITY_LEVEL_NONE) +#define LLSEC802154_USES_FRAME_COUNTER LLSEC802154_ENABLED #endif /* LLSEC802154_CONF_USES_FRAME_COUNTER */ +#ifdef LLSEC802154_CONF_USES_AUX_HEADER +#define LLSEC802154_USES_AUX_HEADER LLSEC802154_CONF_USES_AUX_HEADER +#else /* LLSEC802154_CONF_USES_AUX_HEADER */ +#define LLSEC802154_USES_AUX_HEADER LLSEC802154_ENABLED +#endif /* LLSEC802154_CONF_USES_AUX_HEADER */ + #if UIP_BYTE_ORDER == UIP_LITTLE_ENDIAN #define LLSEC802154_HTONS(n) (n) #define LLSEC802154_HTONL(n) (n) diff --git a/core/net/llsec/noncoresec/README.md b/core/net/llsec/noncoresec/README.md new file mode 100644 index 000000000..00ca46f15 --- /dev/null +++ b/core/net/llsec/noncoresec/README.md @@ -0,0 +1,21 @@ +`noncoresec` is a noncompromise-resilient 802.15.4 security implementation, which uses a network-wide key. Add these lines to your `project_conf.h` to enable `noncoresec`: + +```c +#undef LLSEC802154_CONF_ENABLED +#define LLSEC802154_CONF_ENABLED 1 +#undef NETSTACK_CONF_FRAMER +#define NETSTACK_CONF_FRAMER noncoresec_framer +#undef NETSTACK_CONF_LLSEC +#define NETSTACK_CONF_LLSEC noncoresec_driver +#undef NONCORESEC_CONF_SEC_LVL +#define NONCORESEC_CONF_SEC_LVL 1 +``` +`NONCORESEC_CONF_SEC_LVL` defines the length of MICs and whether encryption is enabled or not. + +Setting the network-wide key works as follows: +```c +#define NONCORESEC_CONF_KEY { 0x00 , 0x01 , 0x02 , 0x03 , \ + 0x04 , 0x05 , 0x06 , 0x07 , \ + 0x08 , 0x09 , 0x0A , 0x0B , \ + 0x0C , 0x0D , 0x0E , 0x0F } +``` diff --git a/core/net/llsec/noncoresec/noncoresec.c b/core/net/llsec/noncoresec/noncoresec.c index e18a7d734..f9d442651 100644 --- a/core/net/llsec/noncoresec/noncoresec.c +++ b/core/net/llsec/noncoresec/noncoresec.c @@ -47,7 +47,6 @@ #include "net/llsec/llsec802154.h" #include "net/llsec/ccm-star-packetbuf.h" #include "net/mac/frame802154.h" -#include "net/mac/framer-802154.h" #include "net/netstack.h" #include "net/packetbuf.h" #include "net/nbr-table.h" @@ -55,7 +54,22 @@ #include "lib/ccm-star.h" #include -#define WITH_ENCRYPTION (LLSEC802154_SECURITY_LEVEL & (1 << 2)) +#ifdef NONCORESEC_CONF_DECORATED_FRAMER +#define DECORATED_FRAMER NONCORESEC_CONF_DECORATED_FRAMER +#else /* NONCORESEC_CONF_DECORATED_FRAMER */ +#define DECORATED_FRAMER framer_802154 +#endif /* NONCORESEC_CONF_DECORATED_FRAMER */ + +extern const struct framer DECORATED_FRAMER; + +#ifdef NONCORESEC_CONF_SEC_LVL +#define SEC_LVL NONCORESEC_CONF_SEC_LVL +#else /* NONCORESEC_CONF_SEC_LVL */ +#define SEC_LVL 2 +#endif /* NONCORESEC_CONF_SEC_LVL */ + +#define WITH_ENCRYPTION (SEC_LVL & (1 << 2)) +#define MIC_LEN LLSEC802154_MIC_LEN(SEC_LVL) #ifdef NONCORESEC_CONF_KEY #define NONCORESEC_KEY NONCORESEC_CONF_KEY @@ -76,6 +90,8 @@ #define PRINTF(...) #endif /* DEBUG */ +#if LLSEC802154_USES_AUX_HEADER && SEC_LVL && LLSEC802154_USES_FRAME_COUNTER + /* network-wide CCM* key */ static uint8_t key[16] = NONCORESEC_KEY; NBR_TABLE(struct anti_replay_info, anti_replay_table); @@ -91,7 +107,7 @@ aead(uint8_t hdrlen, int forward) uint8_t *a; uint8_t a_len; uint8_t *result; - uint8_t generated_mic[LLSEC802154_MIC_LENGTH]; + uint8_t generated_mic[MIC_LEN]; uint8_t *mic; ccm_star_packetbuf_set_nonce(nonce, forward); @@ -113,30 +129,29 @@ aead(uint8_t hdrlen, int forward) CCM_STAR.aead(nonce, m, m_len, a, a_len, - result, LLSEC802154_MIC_LENGTH, + result, MIC_LEN, forward); if(forward) { - packetbuf_set_datalen(packetbuf_datalen() + LLSEC802154_MIC_LENGTH); + packetbuf_set_datalen(packetbuf_datalen() + MIC_LEN); return 1; } else { - return (memcmp(generated_mic, mic, LLSEC802154_MIC_LENGTH) == 0); + return (memcmp(generated_mic, mic, MIC_LEN) == 0); } } /*---------------------------------------------------------------------------*/ static void add_security_header(void) { - if(!packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) { - packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME); - packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, LLSEC802154_SECURITY_LEVEL); - anti_replay_set_counter(); - } + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME); + packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, SEC_LVL); } /*---------------------------------------------------------------------------*/ static void send(mac_callback_t sent, void *ptr) { + add_security_header(); + anti_replay_set_counter(); NETSTACK_MAC.send(sent, ptr); } /*---------------------------------------------------------------------------*/ @@ -145,8 +160,7 @@ create(void) { int result; - add_security_header(); - result = framer_802154.create(); + result = DECORATED_FRAMER.create(); if(result == FRAMER_FAILED) { return result; } @@ -163,12 +177,12 @@ parse(void) const linkaddr_t *sender; struct anti_replay_info* info; - result = framer_802154.parse(); + result = DECORATED_FRAMER.parse(); if(result == FRAMER_FAILED) { return result; } - if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) != LLSEC802154_SECURITY_LEVEL) { + if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) != SEC_LVL) { PRINTF("noncoresec: received frame with wrong security level\n"); return FRAMER_FAILED; } @@ -178,17 +192,17 @@ parse(void) return FRAMER_FAILED; } - packetbuf_set_datalen(packetbuf_datalen() - LLSEC802154_MIC_LENGTH); + packetbuf_set_datalen(packetbuf_datalen() - MIC_LEN); if(!aead(result, 0)) { - PRINTF("noncoresec: received unauthentic frame %"PRIu32"\n", + PRINTF("noncoresec: received unauthentic frame %lu\n", anti_replay_get_counter()); return FRAMER_FAILED; } info = nbr_table_get_from_lladdr(anti_replay_table, sender); if(!info) { - info = nbr_table_add_lladdr(anti_replay_table, sender); + info = nbr_table_add_lladdr(anti_replay_table, sender, NBR_TABLE_REASON_LLSEC, NULL); if(!info) { PRINTF("noncoresec: could not get nbr_table_item\n"); return FRAMER_FAILED; @@ -214,7 +228,7 @@ parse(void) anti_replay_init_info(info); } else { if(anti_replay_was_replayed(info)) { - PRINTF("noncoresec: received replayed frame %"PRIu32"\n", + PRINTF("noncoresec: received replayed frame %lu\n", anti_replay_get_counter()); return FRAMER_FAILED; } @@ -233,7 +247,7 @@ static int length(void) { add_security_header(); - return framer_802154.length() + LLSEC802154_MIC_LENGTH; + return DECORATED_FRAMER.length() + MIC_LEN; } /*---------------------------------------------------------------------------*/ static void @@ -256,5 +270,6 @@ const struct framer noncoresec_framer = { parse }; /*---------------------------------------------------------------------------*/ +#endif /* LLSEC802154_USES_AUX_HEADER && SEC_LVL && LLSEC802154_USES_FRAME_COUNTER */ /** @} */ diff --git a/core/net/mac/contikimac/contikimac.c b/core/net/mac/contikimac/contikimac.c index 1a99720fd..ea5713921 100644 --- a/core/net/mac/contikimac/contikimac.c +++ b/core/net/mac/contikimac/contikimac.c @@ -540,6 +540,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, rtimer_clock_t t0; #if WITH_PHASE_OPTIMIZATION rtimer_clock_t encounter_time = 0; + uint8_t is_known_receiver = 0; #endif int strobes; uint8_t got_strobe_ack = 0; diff --git a/core/net/mac/csma.c b/core/net/mac/csma.c index 4de46be19..eea86b4e8 100644 --- a/core/net/mac/csma.c +++ b/core/net/mac/csma.c @@ -63,26 +63,35 @@ #define PRINTF(...) #endif /* DEBUG */ -#ifndef CSMA_MAX_BACKOFF_EXPONENT -#ifdef CSMA_CONF_MAX_BACKOFF_EXPONENT -#define CSMA_MAX_BACKOFF_EXPONENT CSMA_CONF_MAX_BACKOFF_EXPONENT -#else -#define CSMA_MAX_BACKOFF_EXPONENT 3 -#endif /* CSMA_CONF_MAX_BACKOFF_EXPONENT */ -#endif /* CSMA_MAX_BACKOFF_EXPONENT */ +/* Constants of the IEEE 802.15.4 standard */ -#ifndef CSMA_MAX_MAC_TRANSMISSIONS -#ifdef CSMA_CONF_MAX_MAC_TRANSMISSIONS -#define CSMA_MAX_MAC_TRANSMISSIONS CSMA_CONF_MAX_MAC_TRANSMISSIONS +/* macMinBE: Initial backoff exponent. Range 0--CSMA_MAX_BE */ +#ifdef CSMA_CONF_MIN_BE +#define CSMA_MIN_BE CSMA_CONF_MIN_BE #else -#define CSMA_MAX_MAC_TRANSMISSIONS 3 -#endif /* CSMA_CONF_MAX_MAC_TRANSMISSIONS */ -#endif /* CSMA_MAX_MAC_TRANSMISSIONS */ +#define CSMA_MIN_BE 0 +#endif -#if CSMA_MAX_MAC_TRANSMISSIONS < 1 -#error CSMA_CONF_MAX_MAC_TRANSMISSIONS must be at least 1. -#error Change CSMA_CONF_MAX_MAC_TRANSMISSIONS in contiki-conf.h or in your Makefile. -#endif /* CSMA_CONF_MAX_MAC_TRANSMISSIONS < 1 */ +/* macMaxBE: Maximum backoff exponent. Range 3--8 */ +#ifdef CSMA_CONF_MAX_BE +#define CSMA_MAX_BE CSMA_CONF_MAX_BE +#else +#define CSMA_MAX_BE 4 +#endif + +/* macMaxCSMABackoffs: Maximum number of backoffs in case of channel busy/collision. Range 0--5 */ +#ifdef CSMA_CONF_MAX_BACKOFF +#define CSMA_MAX_BACKOFF CSMA_CONF_MAX_BACKOFF +#else +#define CSMA_MAX_BACKOFF 5 +#endif + +/* macMaxFrameRetries: Maximum number of re-transmissions attampts. Range 0--7 */ +#ifdef CSMA_CONF_MAX_FRAME_RETRIES +#define CSMA_MAX_MAX_FRAME_RETRIES CSMA_CONF_MAX_FRAME_RETRIES +#else +#define CSMA_MAX_MAX_FRAME_RETRIES 7 +#endif /* Packet metadata */ struct qbuf_metadata { @@ -97,7 +106,7 @@ struct neighbor_queue { linkaddr_t addr; struct ctimer transmit_timer; uint8_t transmissions; - uint8_t collisions, deferrals; + uint8_t collisions; LIST_STRUCT(queued_packet_list); }; @@ -123,7 +132,6 @@ LIST(neighbor_list); static void packet_sent(void *ptr, int status, int num_transmissions); static void transmit_packet_list(void *ptr); - /*---------------------------------------------------------------------------*/ static struct neighbor_queue * neighbor_queue_from_addr(const linkaddr_t *addr) @@ -139,18 +147,18 @@ neighbor_queue_from_addr(const linkaddr_t *addr) } /*---------------------------------------------------------------------------*/ static clock_time_t -default_timebase(void) +backoff_period(void) { clock_time_t time; /* The retransmission time must be proportional to the channel check interval of the underlying radio duty cycling layer. */ time = NETSTACK_RDC.channel_check_interval(); - /* If the radio duty cycle has no channel check interval (i.e., it - does not turn the radio off), we make the retransmission time - proportional to the configured MAC channel check rate. */ + /* If the radio duty cycle has no channel check interval, we use + * the default in IEEE 802.15.4: aUnitBackoffPeriod which is + * 20 symbols i.e. 320 usec. That is, 1/3125 second. */ if(time == 0) { - time = CLOCK_SECOND / NETSTACK_RDC_CHANNEL_CHECK_RATE; + time = MAX(CLOCK_SECOND / 3125, 1); } return time; } @@ -171,10 +179,28 @@ transmit_packet_list(void *ptr) } /*---------------------------------------------------------------------------*/ static void +schedule_transmission(struct neighbor_queue *n) +{ + clock_time_t delay; + int backoff_exponent; /* BE in IEEE 802.15.4 */ + + backoff_exponent = MIN(n->collisions, CSMA_MAX_BE); + + /* Compute max delay as per IEEE 802.15.4: 2^BE-1 backoff periods */ + delay = ((1 << backoff_exponent) - 1) * backoff_period(); + if(delay > 0) { + /* Pick a time for next transmission */ + delay = random_rand() % delay; + } + + PRINTF("csma: scheduling transmission in %u ticks, NB=%u, BE=%u\n", + (unsigned)delay, n->collisions, backoff_exponent); + ctimer_set(&n->transmit_timer, delay, transmit_packet_list, n); +} +/*---------------------------------------------------------------------------*/ +static void free_packet(struct neighbor_queue *n, struct rdc_buf_list *p, int status) { - clock_time_t tx_delay; - if(p != NULL) { /* Remove packet from list and deallocate */ list_remove(n->queued_packet_list, p); @@ -187,11 +213,9 @@ free_packet(struct neighbor_queue *n, struct rdc_buf_list *p, int status) if(list_head(n->queued_packet_list) != NULL) { /* There is a next packet. We reset current tx information */ n->transmissions = 0; - n->collisions = 0; - n->deferrals = 0; - /* Set a timer for next transmissions */ - tx_delay = (status == MAC_TX_OK) ? 0 : default_timebase(); - ctimer_set(&n->transmit_timer, tx_delay, transmit_packet_list, n); + n->collisions = CSMA_MIN_BE; + /* Schedule next transmissions */ + schedule_transmission(n); } else { /* This was the last packet in the queue, we free the neighbor */ ctimer_stop(&n->transmit_timer); @@ -202,34 +226,103 @@ free_packet(struct neighbor_queue *n, struct rdc_buf_list *p, int status) } /*---------------------------------------------------------------------------*/ static void +tx_done(int status, struct rdc_buf_list *q, struct neighbor_queue *n) +{ + mac_callback_t sent; + struct qbuf_metadata *metadata; + void *cptr; + + metadata = (struct qbuf_metadata *)q->ptr; + sent = metadata->sent; + cptr = metadata->cptr; + + switch(status) { + case MAC_TX_OK: + PRINTF("csma: rexmit ok %d\n", n->transmissions); + break; + case MAC_TX_COLLISION: + case MAC_TX_NOACK: + PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n", + status, n->transmissions, n->collisions); + break; + default: + PRINTF("csma: rexmit failed %d: %d\n", n->transmissions, status); + break; + } + + free_packet(n, q, status); + mac_call_sent_callback(sent, cptr, status, n->transmissions); +} +/*---------------------------------------------------------------------------*/ +static void +rexmit(struct rdc_buf_list *q, struct neighbor_queue *n) +{ + schedule_transmission(n); + /* This is needed to correctly attribute energy that we spent + transmitting this packet. */ + queuebuf_update_attr_from_packetbuf(q->buf); +} +/*---------------------------------------------------------------------------*/ +static void +collision(struct rdc_buf_list *q, struct neighbor_queue *n, + int num_transmissions) +{ + struct qbuf_metadata *metadata; + + metadata = (struct qbuf_metadata *)q->ptr; + + n->collisions += num_transmissions; + + if(n->collisions > CSMA_MAX_BACKOFF) { + n->collisions = CSMA_MIN_BE; + /* Increment to indicate a next retry */ + n->transmissions++; + } + + if(n->transmissions >= metadata->max_transmissions) { + tx_done(MAC_TX_COLLISION, q, n); + } else { + PRINTF("csma: rexmit collision %d\n", n->transmissions); + rexmit(q, n); + } +} +/*---------------------------------------------------------------------------*/ +static void +noack(struct rdc_buf_list *q, struct neighbor_queue *n, int num_transmissions) +{ + struct qbuf_metadata *metadata; + + metadata = (struct qbuf_metadata *)q->ptr; + + n->collisions = CSMA_MIN_BE; + n->transmissions += num_transmissions; + + if(n->transmissions >= metadata->max_transmissions) { + tx_done(MAC_TX_NOACK, q, n); + } else { + PRINTF("csma: rexmit noack %d\n", n->transmissions); + rexmit(q, n); + } +} +/*---------------------------------------------------------------------------*/ +static void +tx_ok(struct rdc_buf_list *q, struct neighbor_queue *n, int num_transmissions) +{ + n->collisions = CSMA_MIN_BE; + n->transmissions += num_transmissions; + tx_done(MAC_TX_OK, q, n); +} +/*---------------------------------------------------------------------------*/ +static void packet_sent(void *ptr, int status, int num_transmissions) { struct neighbor_queue *n; struct rdc_buf_list *q; - struct qbuf_metadata *metadata; - clock_time_t time = 0; - mac_callback_t sent; - void *cptr; - int num_tx; - int backoff_exponent; - int backoff_transmissions; n = ptr; if(n == NULL) { return; } - switch(status) { - case MAC_TX_OK: - case MAC_TX_NOACK: - n->transmissions += num_transmissions; - break; - case MAC_TX_COLLISION: - n->collisions += num_transmissions; - break; - case MAC_TX_DEFERRED: - n->deferrals += num_transmissions; - break; - } /* Find out what packet this callback refers to */ for(q = list_head(n->queued_packet_list); @@ -240,78 +333,30 @@ packet_sent(void *ptr, int status, int num_transmissions) } } - if(q != NULL) { - metadata = (struct qbuf_metadata *)q->ptr; + if(q == NULL) { + PRINTF("csma: seqno %d not found\n", + packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)); + return; + } else if(q->ptr == NULL) { + PRINTF("csma: no metadata\n"); + return; + } - if(metadata != NULL) { - sent = metadata->sent; - cptr = metadata->cptr; - num_tx = n->transmissions; - if(status == MAC_TX_COLLISION || - status == MAC_TX_NOACK) { - - /* If the transmission was not performed because of a - collision or noack, we must retransmit the packet. */ - - switch(status) { - case MAC_TX_COLLISION: - PRINTF("csma: rexmit collision %d\n", n->transmissions); - break; - case MAC_TX_NOACK: - PRINTF("csma: rexmit noack %d\n", n->transmissions); - break; - default: - PRINTF("csma: rexmit err %d, %d\n", status, n->transmissions); - } - - /* The retransmission time must be proportional to the channel - check interval of the underlying radio duty cycling layer. */ - time = default_timebase(); - - /* The retransmission time uses a truncated exponential backoff - * so that the interval between the transmissions increase with - * each retransmit. */ - backoff_exponent = num_tx; - - /* Truncate the exponent if needed. */ - if(backoff_exponent > CSMA_MAX_BACKOFF_EXPONENT) { - backoff_exponent = CSMA_MAX_BACKOFF_EXPONENT; - } - - /* Proceed to exponentiation. */ - backoff_transmissions = 1 << backoff_exponent; - - /* Pick a time for next transmission, within the interval: - * [time, time + 2^backoff_exponent * time[ */ - time = time + (random_rand() % (backoff_transmissions * time)); - - if(n->transmissions < metadata->max_transmissions) { - PRINTF("csma: retransmitting with time %lu %p\n", time, q); - ctimer_set(&n->transmit_timer, time, - transmit_packet_list, n); - /* This is needed to correctly attribute energy that we spent - transmitting this packet. */ - queuebuf_update_attr_from_packetbuf(q->buf); - } else { - PRINTF("csma: drop with status %d after %d transmissions, %d collisions\n", - status, n->transmissions, n->collisions); - free_packet(n, q, status); - mac_call_sent_callback(sent, cptr, status, num_tx); - } - } else { - if(status == MAC_TX_OK) { - PRINTF("csma: rexmit ok %d\n", n->transmissions); - } else { - PRINTF("csma: rexmit failed %d: %d\n", n->transmissions, status); - } - free_packet(n, q, status); - mac_call_sent_callback(sent, cptr, status, num_tx); - } - } else { - PRINTF("csma: no metadata\n"); - } - } else { - PRINTF("csma: seqno %d not found\n", packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)); + switch(status) { + case MAC_TX_OK: + tx_ok(q, n, num_transmissions); + break; + case MAC_TX_NOACK: + noack(q, n, num_transmissions); + break; + case MAC_TX_COLLISION: + collision(q, n, num_transmissions); + break; + case MAC_TX_DEFERRED: + break; + default: + tx_done(status, q, n); + break; } } /*---------------------------------------------------------------------------*/ @@ -346,8 +391,7 @@ send_packet(mac_callback_t sent, void *ptr) /* Init neighbor entry */ linkaddr_copy(&n->addr, addr); n->transmissions = 0; - n->collisions = 0; - n->deferrals = 0; + n->collisions = CSMA_MIN_BE; /* Init packet list for this neighbor */ LIST_STRUCT_INIT(n, queued_packet_list); /* Add neighbor to the list */ @@ -368,7 +412,7 @@ send_packet(mac_callback_t sent, void *ptr) /* Neighbor and packet successfully allocated */ if(packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS) == 0) { /* Use default configuration for max transmissions */ - metadata->max_transmissions = CSMA_MAX_MAC_TRANSMISSIONS; + metadata->max_transmissions = CSMA_MAX_MAX_FRAME_RETRIES + 1; } else { metadata->max_transmissions = packetbuf_attr(PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS); @@ -389,7 +433,7 @@ send_packet(mac_callback_t sent, void *ptr) list_length(n->queued_packet_list), memb_numfree(&packet_memb)); /* If q is the first packet in the neighbor's queue, send asap */ if(list_head(n->queued_packet_list) == q) { - ctimer_set(&n->transmit_timer, 0, transmit_packet_list, n); + schedule_transmission(n); } return; } diff --git a/core/net/mac/frame802154.c b/core/net/mac/frame802154.c index c2982a014..77727ab47 100644 --- a/core/net/mac/frame802154.c +++ b/core/net/mac/frame802154.c @@ -102,7 +102,7 @@ addr_len(uint8_t mode) } } /*----------------------------------------------------------------------------*/ -#if LLSEC802154_USES_EXPLICIT_KEYS +#if LLSEC802154_USES_AUX_HEADER && LLSEC802154_USES_EXPLICIT_KEYS static uint8_t get_key_id_len(uint8_t key_id_mode) { @@ -117,7 +117,7 @@ get_key_id_len(uint8_t key_id_mode) return 0; } } -#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ +#endif /* LLSEC802154_USES_AUX_HEADER && LLSEC802154_USES_EXPLICIT_KEYS */ /*---------------------------------------------------------------------------*/ /* Get current PAN ID */ uint16_t @@ -317,7 +317,7 @@ field_len(frame802154_t *p, field_length_t *flen) flen->dest_addr_len = addr_len(p->fcf.dest_addr_mode & 3); flen->src_addr_len = addr_len(p->fcf.src_addr_mode & 3); -#if LLSEC802154_SECURITY_LEVEL +#if LLSEC802154_USES_AUX_HEADER /* Aux security header */ if(p->fcf.security_enabled & 1) { flen->aux_sec_len = 1; /* FCF + possibly frame counter and key ID */ @@ -333,7 +333,7 @@ field_len(frame802154_t *p, field_length_t *flen) #endif /* LLSEC802154_USES_EXPLICIT_KEYS */ ; } -#endif /* LLSEC802154_SECURITY_LEVEL */ +#endif /* LLSEC802154_USES_AUX_HEADER */ } /*----------------------------------------------------------------------------*/ /** @@ -418,7 +418,7 @@ frame802154_create(frame802154_t *p, uint8_t *buf) for(c = flen.src_addr_len; c > 0; c--) { buf[pos++] = p->src_addr[c - 1]; } -#if LLSEC802154_SECURITY_LEVEL +#if LLSEC802154_USES_AUX_HEADER /* Aux header */ if(flen.aux_sec_len) { buf[pos++] = p->aux_hdr.security_control.security_level @@ -447,7 +447,7 @@ frame802154_create(frame802154_t *p, uint8_t *buf) } #endif /* LLSEC802154_USES_EXPLICIT_KEYS */ } -#endif /* LLSEC802154_SECURITY_LEVEL */ +#endif /* LLSEC802154_USES_AUX_HEADER */ return (int)pos; } @@ -570,7 +570,7 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf) pf->src_pid = 0; } -#if LLSEC802154_SECURITY_LEVEL +#if LLSEC802154_USES_AUX_HEADER if(fcf.security_enabled) { pf->aux_hdr.security_control.security_level = p[0] & 7; #if LLSEC802154_USES_EXPLICIT_KEYS @@ -599,7 +599,7 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf) } #endif /* LLSEC802154_USES_EXPLICIT_KEYS */ } -#endif /* LLSEC802154_SECURITY_LEVEL */ +#endif /* LLSEC802154_USES_AUX_HEADER */ /* header length */ c = p - data; diff --git a/core/net/mac/frame802154e-ie.c b/core/net/mac/frame802154e-ie.c index 55c397631..db0118889 100644 --- a/core/net/mac/frame802154e-ie.c +++ b/core/net/mac/frame802154e-ie.c @@ -41,7 +41,7 @@ #include "net/mac/frame802154e-ie.h" #define DEBUG DEBUG_NONE -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /* c.f. IEEE 802.15.4e Table 4b */ enum ieee802154e_header_ie_id { diff --git a/core/net/mac/framer-802154.c b/core/net/mac/framer-802154.c index 14ccc5aa3..7e524afb1 100644 --- a/core/net/mac/framer-802154.c +++ b/core/net/mac/framer-802154.c @@ -98,7 +98,7 @@ create_frame(int type, int do_create) /* Insert IEEE 802.15.4 version bits. */ params.fcf.frame_version = FRAME802154_VERSION; -#if LLSEC802154_SECURITY_LEVEL +#if LLSEC802154_USES_AUX_HEADER if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) { params.fcf.security_enabled = 1; } @@ -116,7 +116,7 @@ create_frame(int type, int do_create) params.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX); params.aux_hdr.key_source.u16[0] = packetbuf_attr(PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1); #endif /* LLSEC802154_USES_EXPLICIT_KEYS */ -#endif /* LLSEC802154_SECURITY_LEVEL */ +#endif /* LLSEC802154_USES_AUX_HEADER */ /* Increment and set the data sequence number. */ if(!do_create) { @@ -238,7 +238,7 @@ parse(void) packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq); #endif -#if LLSEC802154_SECURITY_LEVEL +#if LLSEC802154_USES_AUX_HEADER if(frame.fcf.security_enabled) { packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, frame.aux_hdr.security_control.security_level); #if LLSEC802154_USES_FRAME_COUNTER @@ -251,7 +251,7 @@ parse(void) packetbuf_set_attr(PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1, frame.aux_hdr.key_source.u16[0]); #endif /* LLSEC802154_USES_EXPLICIT_KEYS */ } -#endif /* LLSEC802154_SECURITY_LEVEL */ +#endif /* LLSEC802154_USES_AUX_HEADER */ PRINTF("15.4-IN: %2X", frame.fcf.frame_type); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); diff --git a/core/net/mac/phase.c b/core/net/mac/phase.c index 47b7e7cf3..d7ded2428 100644 --- a/core/net/mac/phase.c +++ b/core/net/mac/phase.c @@ -122,7 +122,7 @@ phase_update(const linkaddr_t *neighbor, rtimer_clock_t time, } else { /* No matching phase was found, so we allocate a new one. */ if(mac_status == MAC_TX_OK && e == NULL) { - e = nbr_table_add_lladdr(nbr_phase, neighbor); + e = nbr_table_add_lladdr(nbr_phase, neighbor, NBR_TABLE_REASON_MAC, NULL); if(e) { e->time = time; #if PHASE_DRIFT_CORRECT diff --git a/core/net/mac/rdc.h b/core/net/mac/rdc.h index 827e6970a..d017ddfb6 100644 --- a/core/net/mac/rdc.h +++ b/core/net/mac/rdc.h @@ -43,6 +43,7 @@ #include "contiki-conf.h" #include "net/mac/mac.h" +#include "net/llsec/llsec802154.h" #ifdef RDC_CONF_WITH_DUPLICATE_DETECTION #define RDC_WITH_DUPLICATE_DETECTION RDC_CONF_WITH_DUPLICATE_DETECTION @@ -51,7 +52,7 @@ frame because it has seen its sequence number already. Replay protection should be implemented at the LLSEC layer where the authenticity of frames is verified. */ -#define RDC_WITH_DUPLICATE_DETECTION !LLSEC802154_CONF_SECURITY_LEVEL +#define RDC_WITH_DUPLICATE_DETECTION !LLSEC802154_ENABLED #endif /* RDC_CONF_WITH_DUPLICATE_DETECTION */ /* List of packets to be sent by RDC layer */ diff --git a/core/net/mac/tsch/README.md b/core/net/mac/tsch/README.md index ffd6dc789..0b7c54ef3 100644 --- a/core/net/mac/tsch/README.md +++ b/core/net/mac/tsch/README.md @@ -36,6 +36,9 @@ It has been tested on the following platforms: * NXP JN516x (`jn516x`, tested on hardware) * Tmote Sky (`sky`, tested on hardware and in cooja) * Zolertia Z1 (`z1`, tested in cooja only) + * CC2538DK (`cc2538dk`, tested on hardware) + * Zolertia Zoul (`zoul`, tested on hardware) + * CC2650 (`srf06-cc26xx`, tested on hardware) This implementation was present at the ETSI Plugtest event in Prague in July 2015, and did successfully inter-operate with all @@ -76,7 +79,7 @@ Orchestra is implemented in: A simple TSCH+RPL example is included under `examples/ipv6/rpl-tsch`. To use TSCH, first make sure your platform supports it. -Currently, `jn516x`, `sky` and `z1` are the supported platforms. +Currently, `jn516x`, `sky`, `z1`, `cc2538dk`, `zoul` and `srf06-cc26xx` are the supported platforms. To add your own, we refer the reader to the next section. To add TSCH to your application, first include the TSCH module from your makefile with: @@ -128,8 +131,8 @@ To configure TSCH, see the macros in `.h` files under `core/net/mac/tsch/` and r To include TSCH standard-compliant security, set the following: ``` /* Enable security */ -#undef LLSEC802154_CONF_SECURITY_LEVEL -#define LLSEC802154_CONF_SECURITY_LEVEL 1 +#undef LLSEC802154_CONF_ENABLED +#define LLSEC802154_CONF_ENABLED 1 /* TSCH uses explicit keys to identify k1 and k2 */ #undef LLSEC802154_CONF_USES_EXPLICIT_KEYS #define LLSEC802154_CONF_USES_EXPLICIT_KEYS 1 @@ -162,7 +165,7 @@ Finally, one can also implement his own scheduler, centralized or distributed, b ## Porting TSCH to a new platform Porting TSCH to a new platform requires a few new features in the radio driver, a number of timing-related configuration paramters. -The easiest is probably to start from one of the existing port: `jn516x`, `sky`, `z1`. +The easiest is probably to start from one of the existing port: `jn516x`, `sky`, `z1`, `cc2538dk`, `zoul`, `srf06-cc26xx`. ### Radio features required for TSCH diff --git a/core/net/mac/tsch/tsch-adaptive-timesync.c b/core/net/mac/tsch/tsch-adaptive-timesync.c index 0b4601621..08d4df2ee 100644 --- a/core/net/mac/tsch/tsch-adaptive-timesync.c +++ b/core/net/mac/tsch/tsch-adaptive-timesync.c @@ -86,12 +86,16 @@ timesync_entry_add(int32_t val, uint32_t time_delta) static void timesync_learn_drift_ticks(uint32_t time_delta_asn, int32_t drift_ticks) { - /* should fit in 32-bit unsigned integer */ - uint32_t time_delta_ticks = time_delta_asn * tsch_timing[tsch_ts_timeslot_length]; + /* should fit in a 32-bit integer */ + int32_t time_delta_ticks = time_delta_asn * tsch_timing[tsch_ts_timeslot_length]; int32_t real_drift_ticks = drift_ticks + compensated_ticks; int32_t last_drift_ppm = (int32_t)((int64_t)real_drift_ticks * TSCH_DRIFT_UNIT / time_delta_ticks); drift_ppm = timesync_entry_add(last_drift_ppm, time_delta_ticks); + + TSCH_LOG_ADD(tsch_log_message, + snprintf(log->message, sizeof(log->message), + "drift %ld", drift_ppm / 256)); } /*---------------------------------------------------------------------------*/ /* Either reset or update the neighbor's drift */ diff --git a/core/net/mac/tsch/tsch-conf.h b/core/net/mac/tsch/tsch-conf.h index bd9726042..d8d58f0ff 100644 --- a/core/net/mac/tsch/tsch-conf.h +++ b/core/net/mac/tsch/tsch-conf.h @@ -53,6 +53,8 @@ #define TSCH_HOPPING_SEQUENCE_4_16 (uint8_t[]){ 20, 26, 25, 26, 15, 15, 25, 20, 26, 15, 26, 25, 20, 15, 20, 25 } /* 4 channels, sequence length 4 */ #define TSCH_HOPPING_SEQUENCE_4_4 (uint8_t[]){ 15, 25, 26, 20 } +/* 2 channels, sequence length 2 */ +#define TSCH_HOPPING_SEQUENCE_2_2 (uint8_t[]){ 20, 25 } /* 1 channel, sequence length 1 */ #define TSCH_HOPPING_SEQUENCE_1_1 (uint8_t[]){ 20 } @@ -120,7 +122,7 @@ #define TSCH_DEFAULT_TS_TIMESLOT_LENGTH 10000 #elif TSCH_CONF_DEFAULT_TIMESLOT_LENGTH == 15000 -/* Default timeslot timing for platfroms requiring 15ms slots */ +/* Default timeslot timing for platforms requiring 15ms slots */ #define TSCH_DEFAULT_TS_CCA_OFFSET 1800 #define TSCH_DEFAULT_TS_CCA 128 @@ -135,7 +137,7 @@ #define TSCH_DEFAULT_TS_MAX_TX 4256 #define TSCH_DEFAULT_TS_TIMESLOT_LENGTH 15000 -#elif TSCH_CONF_DEFAULT_TIMESLOT_LENGTH == 65000 +#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 or z1 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, @@ -175,4 +177,25 @@ #define TSCH_ADAPTIVE_TIMESYNC 0 #endif +/* HW frame filtering enabled */ +#ifdef TSCH_CONF_HW_FRAME_FILTERING +#define TSCH_HW_FRAME_FILTERING TSCH_CONF_HW_FRAME_FILTERING +#else /* TSCH_CONF_HW_FRAME_FILTERING */ +#define TSCH_HW_FRAME_FILTERING 1 +#endif /* TSCH_CONF_HW_FRAME_FILTERING */ + +/* Keep radio always on within TSCH timeslot (1) or turn it off between packet and ACK? (0) */ +#ifdef TSCH_CONF_RADIO_ON_DURING_TIMESLOT +#define TSCH_RADIO_ON_DURING_TIMESLOT TSCH_CONF_RADIO_ON_DURING_TIMESLOT +#else +#define TSCH_RADIO_ON_DURING_TIMESLOT 0 +#endif + +/* How long to scan each channel in the scanning phase */ +#ifdef TSCH_CONF_CHANNEL_SCAN_DURATION +#define TSCH_CHANNEL_SCAN_DURATION TSCH_CONF_CHANNEL_SCAN_DURATION +#else +#define TSCH_CHANNEL_SCAN_DURATION CLOCK_SECOND +#endif + #endif /* __TSCH_CONF_H__ */ diff --git a/core/net/mac/tsch/tsch-log.c b/core/net/mac/tsch/tsch-log.c index bfb033e9d..8ab23215b 100644 --- a/core/net/mac/tsch/tsch-log.c +++ b/core/net/mac/tsch/tsch-log.c @@ -56,7 +56,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" #if TSCH_LOG_LEVEL >= 2 /* Skip this file for log levels 0 or 1 */ @@ -84,11 +84,15 @@ tsch_log_process_pending(void) } while((log_index = ringbufindex_peek_get(&log_ringbuf)) != -1) { struct tsch_log_t *log = &log_array[log_index]; - struct tsch_slotframe *sf = tsch_schedule_get_slotframe_by_handle(log->link->slotframe_handle); - printf("TSCH: {asn-%x.%lx link-%u-%u-%u-%u ch-%u} ", - log->asn.ms1b, log->asn.ls4b, - log->link->slotframe_handle, sf ? sf->size.val : 0, log->link->timeslot, log->link->channel_offset, - tsch_calculate_channel(&log->asn, log->link->channel_offset)); + if(log->link == NULL) { + printf("TSCH: {asn-%x.%lx link-NULL} ", log->asn.ms1b, log->asn.ls4b); + } else { + struct tsch_slotframe *sf = tsch_schedule_get_slotframe_by_handle(log->link->slotframe_handle); + printf("TSCH: {asn-%x.%lx link-%u-%u-%u-%u ch-%u} ", + log->asn.ms1b, log->asn.ls4b, + log->link->slotframe_handle, sf ? sf->size.val : 0, log->link->timeslot, log->link->channel_offset, + tsch_calculate_channel(&log->asn, log->link->channel_offset)); + } switch(log->type) { case tsch_log_tx: printf("%s-%u-%u %u tx %d, st %d-%d", @@ -103,7 +107,7 @@ tsch_log_process_pending(void) break; case tsch_log_rx: printf("%s-%u-%u %u rx %d", - log->rx.is_unicast == 0 ? "bc" : "uc", log->rx.is_data, log->tx.sec_level, + log->rx.is_unicast == 0 ? "bc" : "uc", log->rx.is_data, log->rx.sec_level, log->rx.datalen, log->rx.src); if(log->rx.drift_used) { diff --git a/core/net/mac/tsch/tsch-packet.c b/core/net/mac/tsch/tsch-packet.c index dbfad6082..17601d054 100644 --- a/core/net/mac/tsch/tsch-packet.c +++ b/core/net/mac/tsch/tsch-packet.c @@ -60,7 +60,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /*---------------------------------------------------------------------------*/ /* Construct enhanced ACK packet and return ACK length */ @@ -94,7 +94,7 @@ tsch_packet_create_eack(uint8_t *buf, int buf_size, p.src_pid = IEEE802154_PANID; linkaddr_copy((linkaddr_t *)&p.src_addr, &linkaddr_node_addr); #endif -#if TSCH_SECURITY_ENABLED +#if LLSEC802154_ENABLED if(tsch_is_pan_secured) { p.fcf.security_enabled = 1; p.aux_hdr.security_control.security_level = TSCH_SECURITY_KEY_SEC_LEVEL_ACK; @@ -103,7 +103,7 @@ tsch_packet_create_eack(uint8_t *buf, int buf_size, p.aux_hdr.security_control.frame_counter_size = 1; p.aux_hdr.key_index = TSCH_SECURITY_KEY_INDEX_ACK; } -#endif /* TSCH_SECURITY_ENABLED */ +#endif /* LLSEC802154_ENABLED */ if((curr_len = frame802154_create(&p, buf)) == 0) { return 0; @@ -166,13 +166,13 @@ tsch_packet_parse_eack(const uint8_t *buf, int buf_size, if(frame->fcf.ie_list_present) { int mic_len = 0; -#if TSCH_SECURITY_ENABLED +#if LLSEC802154_ENABLED /* Check if there is space for the security MIC (if any) */ mic_len = tsch_security_mic_len(frame); if(buf_size < curr_len + mic_len) { return 0; } -#endif /* TSCH_SECURITY_ENABLED */ +#endif /* LLSEC802154_ENABLED */ /* Parse information elements. We need to substract the MIC length, as the exact payload len is needed while parsing */ if((ret = frame802154e_parse_information_elements(buf + curr_len, buf_size - curr_len - mic_len, ies)) == -1) { return 0; @@ -222,7 +222,7 @@ tsch_packet_create_eb(uint8_t *buf, int buf_size, uint8_t seqno, p.dest_addr[0] = 0xff; p.dest_addr[1] = 0xff; -#if TSCH_SECURITY_ENABLED +#if LLSEC802154_ENABLED if(tsch_is_pan_secured) { p.fcf.security_enabled = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) > 0; p.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL); @@ -231,7 +231,7 @@ tsch_packet_create_eb(uint8_t *buf, int buf_size, uint8_t seqno, p.aux_hdr.security_control.frame_counter_size = 1; p.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX); } -#endif /* TSCH_SECURITY_ENABLED */ +#endif /* LLSEC802154_ENABLED */ if((curr_len = frame802154_create(&p, buf)) == 0) { return 0; @@ -387,14 +387,14 @@ tsch_packet_parse_eb(const uint8_t *buf, int buf_size, if(frame->fcf.ie_list_present) { /* Calculate space needed for the security MIC, if any, before attempting to parse IEs */ int mic_len = 0; -#if TSCH_SECURITY_ENABLED +#if LLSEC802154_ENABLED if(!frame_without_mic) { mic_len = tsch_security_mic_len(frame); if(buf_size < curr_len + mic_len) { return 0; } } -#endif /* TSCH_SECURITY_ENABLED */ +#endif /* LLSEC802154_ENABLED */ /* Parse information elements. We need to substract the MIC length, as the exact payload len is needed while parsing */ if((ret = frame802154e_parse_information_elements(buf + curr_len, buf_size - curr_len - mic_len, ies)) == -1) { diff --git a/core/net/mac/tsch/tsch-packet.h b/core/net/mac/tsch/tsch-packet.h index 24f533a88..c48bd479b 100644 --- a/core/net/mac/tsch/tsch-packet.h +++ b/core/net/mac/tsch/tsch-packet.h @@ -36,6 +36,7 @@ /********** Includes **********/ #include "contiki.h" +#include "net/packetbuf.h" #include "net/mac/tsch/tsch-private.h" #include "net/mac/frame802154.h" #include "net/mac/frame802154e-ie.h" @@ -81,7 +82,7 @@ by default, useful in case of duplicate seqno */ /********** Constants *********/ /* Max TSCH packet lenght */ -#define TSCH_PACKET_MAX_LEN 127 +#define TSCH_PACKET_MAX_LEN MIN(127,PACKETBUF_SIZE) /********** Functions *********/ diff --git a/core/net/mac/tsch/tsch-queue.c b/core/net/mac/tsch/tsch-queue.c index afe868030..e3f60f45c 100644 --- a/core/net/mac/tsch/tsch-queue.c +++ b/core/net/mac/tsch/tsch-queue.c @@ -61,7 +61,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /* Check if TSCH_QUEUE_NUM_PER_NEIGHBOR is power of two */ #if (TSCH_QUEUE_NUM_PER_NEIGHBOR & (TSCH_QUEUE_NUM_PER_NEIGHBOR - 1)) != 0 @@ -302,14 +302,17 @@ tsch_queue_free_packet(struct tsch_packet *p) /*---------------------------------------------------------------------------*/ /* Flush all neighbor queues */ void -tsch_queue_flush_all(void) +tsch_queue_reset(void) { /* Deallocate unneeded neighbors */ if(!tsch_is_locked()) { struct tsch_neighbor *n = list_head(neighbor_list); while(n != NULL) { struct tsch_neighbor *next_n = list_item_next(n); + /* Flush queue */ tsch_queue_flush_nbr_queue(n); + /* Reset backoff exponent */ + tsch_queue_backoff_reset(n); n = next_n; } } @@ -379,6 +382,7 @@ tsch_queue_get_packet_for_dest_addr(const linkaddr_t *addr, struct tsch_link *li } return NULL; } +/*---------------------------------------------------------------------------*/ /* Returns the head packet of any neighbor queue with zero backoff counter. * Writes pointer to the neighbor in *n */ struct tsch_packet * diff --git a/core/net/mac/tsch/tsch-queue.h b/core/net/mac/tsch/tsch-queue.h index b4061be23..676619a3a 100644 --- a/core/net/mac/tsch/tsch-queue.h +++ b/core/net/mac/tsch/tsch-queue.h @@ -39,6 +39,7 @@ #include "lib/ringbufindex.h" #include "net/linkaddr.h" #include "net/mac/tsch/tsch-schedule.h" +#include "net/mac/mac.h" /******** Configuration *******/ @@ -166,8 +167,8 @@ int tsch_queue_packet_count(const linkaddr_t *addr); struct tsch_packet *tsch_queue_remove_packet_from_queue(struct tsch_neighbor *n); /* Free a packet */ void tsch_queue_free_packet(struct tsch_packet *p); -/* Flush all neighbor queues */ -void tsch_queue_flush_all(void); +/* Reset neighbor queues */ +void tsch_queue_reset(void); /* Deallocate neighbors with empty queue */ void tsch_queue_free_unused_neighbors(void); /* Is the neighbor queue empty? */ diff --git a/core/net/mac/tsch/tsch-rpl.c b/core/net/mac/tsch/tsch-rpl.c index 772c886b3..4558c4366 100644 --- a/core/net/mac/tsch/tsch-rpl.c +++ b/core/net/mac/tsch/tsch-rpl.c @@ -51,7 +51,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /*---------------------------------------------------------------------------*/ /* To use, set #define TSCH_CALLBACK_JOINING_NETWORK tsch_rpl_callback_joining_network */ @@ -73,7 +73,7 @@ tsch_rpl_callback_leaving_network(void) } /*---------------------------------------------------------------------------*/ /* Set TSCH EB period based on current RPL DIO period. - * To use, set #define RPL_CALLBACK_PARENT_SWITCH tsch_rpl_callback_new_dio_interval */ + * To use, set #define RPL_CALLBACK_NEW_DIO_INTERVAL tsch_rpl_callback_new_dio_interval */ void tsch_rpl_callback_new_dio_interval(uint8_t dio_interval) { diff --git a/core/net/mac/tsch/tsch-schedule.c b/core/net/mac/tsch/tsch-schedule.c index 8b15e0faf..0a61b5f12 100644 --- a/core/net/mac/tsch/tsch-schedule.c +++ b/core/net/mac/tsch/tsch-schedule.c @@ -60,7 +60,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /* Pre-allocated space for links */ MEMB(link_memb, struct tsch_link, TSCH_SCHEDULE_MAX_LINKS); @@ -191,6 +191,7 @@ tsch_schedule_add_link(struct tsch_slotframe *slotframe, l = memb_alloc(&link_memb); if(l == NULL) { PRINTF("TSCH-schedule:! add_link memb_alloc failed\n"); + tsch_release_lock(); } else { static int current_link_handle = 0; struct tsch_neighbor *n; diff --git a/core/net/mac/tsch/tsch-security.c b/core/net/mac/tsch/tsch-security.c index e7439c519..6d862e19e 100644 --- a/core/net/mac/tsch/tsch-security.c +++ b/core/net/mac/tsch/tsch-security.c @@ -58,7 +58,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /* The two keys K1 and K2 from 6TiSCH minimal configuration * K1: well-known, used for EBs diff --git a/core/net/mac/tsch/tsch-security.h b/core/net/mac/tsch/tsch-security.h index 694afa78e..42f18e8d9 100644 --- a/core/net/mac/tsch/tsch-security.h +++ b/core/net/mac/tsch/tsch-security.h @@ -39,22 +39,23 @@ #include "net/mac/tsch/tsch-asn.h" #include "net/mac/tsch/tsch-private.h" #include "net/mac/frame802154.h" +#include "net/llsec/llsec802154.h" #include "net/mac/frame802154e-ie.h" /******** Configuration *******/ /* To enable TSCH security: - * - set LLSEC802154_CONF_SECURITY_LEVEL + * - set LLSEC802154_CONF_ENABLED * - set LLSEC802154_CONF_USES_EXPLICIT_KEYS * - unset LLSEC802154_CONF_USES_FRAME_COUNTER * */ -#define TSCH_SECURITY_ENABLED (LLSEC802154_CONF_SECURITY_LEVEL != 0) -#if TSCH_SECURITY_ENABLED && !LLSEC802154_CONF_USES_EXPLICIT_KEYS -#error TSCH_SECURITY_ENABLED set but LLSEC802154_CONF_USES_EXPLICIT_KEYS unset -#endif /* TSCH_SECURITY_ENABLED */ -#if TSCH_SECURITY_ENABLED && LLSEC802154_CONF_USES_FRAME_COUNTER -#error TSCH_SECURITY_ENABLED set but LLSEC802154_CONF_USES_FRAME_COUNTER set -#endif /* TSCH_SECURITY_ENABLED */ + +#if LLSEC802154_ENABLED && !LLSEC802154_USES_EXPLICIT_KEYS +#error LLSEC802154_ENABLED set but LLSEC802154_USES_EXPLICIT_KEYS unset +#endif /* LLSEC802154_ENABLED */ +#if LLSEC802154_ENABLED && LLSEC802154_USES_FRAME_COUNTER +#error LLSEC802154_ENABLED set but LLSEC802154_USES_FRAME_COUNTER set +#endif /* LLSEC802154_ENABLED */ /* K1, defined in 6TiSCH minimal, is well-known (offers no security) and used for EBs only */ #ifdef TSCH_SECURITY_CONF_K1 diff --git a/core/net/mac/tsch/tsch-slot-operation.c b/core/net/mac/tsch/tsch-slot-operation.c index 3174787c2..be83da4ab 100644 --- a/core/net/mac/tsch/tsch-slot-operation.c +++ b/core/net/mac/tsch/tsch-slot-operation.c @@ -36,6 +36,7 @@ * \author * Simon Duquennoy * Beshr Al Nahas + * Atis Elsts * */ @@ -59,7 +60,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /* TSCH debug macros, i.e. to set LEDs or GPIOs on various TSCH * timeslot events */ @@ -109,6 +110,18 @@ #define RTIMER_GUARD 2u #endif +enum tsch_radio_state_on_cmd { + TSCH_RADIO_CMD_ON_START_OF_TIMESLOT, + TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT, + TSCH_RADIO_CMD_ON_FORCE, +}; + +enum tsch_radio_state_off_cmd { + TSCH_RADIO_CMD_OFF_END_OF_TIMESLOT, + TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT, + TSCH_RADIO_CMD_OFF_FORCE, +}; + /* A ringbuf storing outgoing packets after they were dequeued. * Will be processed layer by tsch_tx_process_pending */ struct ringbufindex dequeued_ringbuf; @@ -370,6 +383,68 @@ update_neighbor_state(struct tsch_neighbor *n, struct tsch_packet *p, return in_queue; } /*---------------------------------------------------------------------------*/ +/** + * This function turns on the radio. Its semantics is dependent on + * the value of TSCH_RADIO_ON_DURING_TIMESLOT constant: + * - if enabled, the radio is turned on at the start of the slot + * - if disabled, the radio is turned on within the slot, + * directly before the packet Rx guard time and ACK Rx guard time. + */ +static void +tsch_radio_on(enum tsch_radio_state_on_cmd command) +{ + int do_it = 0; + switch(command) { + case TSCH_RADIO_CMD_ON_START_OF_TIMESLOT: + if(TSCH_RADIO_ON_DURING_TIMESLOT) { + do_it = 1; + } + break; + case TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT: + if(!TSCH_RADIO_ON_DURING_TIMESLOT) { + do_it = 1; + } + break; + case TSCH_RADIO_CMD_ON_FORCE: + do_it = 1; + break; + } + if(do_it) { + NETSTACK_RADIO.on(); + } +} +/*---------------------------------------------------------------------------*/ +/** + * This function turns off the radio. In the same way as for tsch_radio_on(), + * it depends on the value of TSCH_RADIO_ON_DURING_TIMESLOT constant: + * - if enabled, the radio is turned off at the end of the slot + * - if disabled, the radio is turned off within the slot, + * directly after Tx'ing or Rx'ing a packet or Tx'ing an ACK. + */ +static void +tsch_radio_off(enum tsch_radio_state_off_cmd command) +{ + int do_it = 0; + switch(command) { + case TSCH_RADIO_CMD_OFF_END_OF_TIMESLOT: + if(TSCH_RADIO_ON_DURING_TIMESLOT) { + do_it = 1; + } + break; + case TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT: + if(!TSCH_RADIO_ON_DURING_TIMESLOT) { + do_it = 1; + } + break; + case TSCH_RADIO_CMD_OFF_FORCE: + do_it = 1; + break; + } + if(do_it) { + NETSTACK_RADIO.off(); + } +} +/*---------------------------------------------------------------------------*/ static PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t)) { @@ -404,10 +479,10 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t)) } else { /* packet payload */ static void *packet; -#if TSCH_SECURITY_ENABLED +#if LLSEC802154_ENABLED /* encrypted payload */ static uint8_t encrypted_packet[TSCH_PACKET_MAX_LEN]; -#endif /* TSCH_SECURITY_ENABLED */ +#endif /* LLSEC802154_ENABLED */ /* packet payload length */ static uint8_t packet_len; /* packet seqno */ @@ -434,7 +509,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t)) packet_ready = 1; } -#if TSCH_SECURITY_ENABLED +#if LLSEC802154_ENABLED if(tsch_is_pan_secured) { /* If we are going to encrypt, we need to generate the output in a separate buffer and keep * the original untouched. This is to allow for future retransmissions. */ @@ -445,7 +520,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t)) packet = encrypted_packet; } } -#endif /* TSCH_SECURITY_ENABLED */ +#endif /* LLSEC802154_ENABLED */ /* prepare packet to send: copy to radio buffer */ if(packet_ready && NETSTACK_RADIO.prepare(packet, packet_len) == 0) { /* 0 means success */ @@ -456,7 +531,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t)) /* delay before CCA */ TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start, TS_CCA_OFFSET, "cca"); TSCH_DEBUG_TX_EVENT(); - NETSTACK_RADIO.on(); + 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); @@ -480,7 +555,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t)) /* limit tx_time to its max value */ tx_duration = MIN(tx_duration, tsch_timing[tsch_ts_max_tx]); /* turn tadio off -- will turn on again to wait for ACK if needed */ - NETSTACK_RADIO.off(); + tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT); if(mac_tx_status == RADIO_TX_OK) { if(!is_broadcast) { @@ -488,35 +563,39 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t)) int ack_len; rtimer_clock_t ack_start_time; int is_time_source; - radio_value_t radio_rx_mode; struct ieee802154_ies ack_ies; uint8_t ack_hdrlen; frame802154_t frame; +#if TSCH_HW_FRAME_FILTERING + radio_value_t radio_rx_mode; /* Entering promiscuous mode so that the radio accepts the enhanced ACK */ NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode); NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode & (~RADIO_RX_MODE_ADDRESS_FILTER)); +#endif /* TSCH_HW_FRAME_FILTERING */ /* Unicast: wait for ack after tx: sleep until ack time */ TSCH_SCHEDULE_AND_YIELD(pt, t, current_slot_start, tsch_timing[tsch_ts_tx_offset] + tx_duration + tsch_timing[tsch_ts_rx_ack_delay] - RADIO_DELAY_BEFORE_RX, "TxBeforeAck"); TSCH_DEBUG_TX_EVENT(); - NETSTACK_RADIO.on(); + tsch_radio_on(TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT); /* Wait for ACK to come */ 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]); TSCH_DEBUG_TX_EVENT(); - ack_start_time = RTIMER_NOW(); + ack_start_time = RTIMER_NOW() - RADIO_DELAY_BEFORE_DETECT; /* Wait for ACK to finish */ BUSYWAIT_UNTIL_ABS(!NETSTACK_RADIO.receiving_packet(), ack_start_time, tsch_timing[tsch_ts_max_ack]); TSCH_DEBUG_TX_EVENT(); - NETSTACK_RADIO.off(); + tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT); +#if TSCH_HW_FRAME_FILTERING /* Leaving promiscuous mode */ NETSTACK_RADIO.get_value(RADIO_PARAM_RX_MODE, &radio_rx_mode); NETSTACK_RADIO.set_value(RADIO_PARAM_RX_MODE, radio_rx_mode | RADIO_RX_MODE_ADDRESS_FILTER); +#endif /* TSCH_HW_FRAME_FILTERING */ /* Read ack frame */ ack_len = NETSTACK_RADIO.read((void *)ackbuf, sizeof(ackbuf)); @@ -530,7 +609,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t)) ack_len = 0; } -#if TSCH_SECURITY_ENABLED +#if LLSEC802154_ENABLED if(ack_len != 0) { if(!tsch_security_parse_frame(ackbuf, ack_hdrlen, ack_len - ack_hdrlen - tsch_security_mic_len(&frame), &frame, ¤t_neighbor->addr, ¤t_asn)) { @@ -544,7 +623,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t)) snprintf(log->message, sizeof(log->message), "!failed to parse ACK")); } -#endif /* TSCH_SECURITY_ENABLED */ +#endif /* LLSEC802154_ENABLED */ } if(ack_len != 0) { @@ -584,6 +663,8 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t)) } } + tsch_radio_off(TSCH_RADIO_CMD_OFF_END_OF_TIMESLOT); + current_packet->transmissions++; current_packet->ret = mac_tx_status; @@ -604,7 +685,11 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t)) log->tx.drift = drift_correction; log->tx.drift_used = is_drift_correction_used; log->tx.is_data = ((((uint8_t *)(queuebuf_dataptr(current_packet->qb)))[0]) & 7) == FRAME802154_DATAFRAME; +#if LLSEC802154_ENABLED log->tx.sec_level = queuebuf_attr(current_packet->qb, PACKETBUF_ATTR_SECURITY_LEVEL); +#else /* LLSEC802154_ENABLED */ + log->tx.sec_level = 0; +#endif /* LLSEC802154_ENABLED */ log->tx.dest = TSCH_LOG_ID_FROM_LINKADDR(queuebuf_addr(current_packet->qb, PACKETBUF_ADDR_RECEIVER)); ); @@ -663,32 +748,26 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t)) TSCH_DEBUG_RX_EVENT(); /* Start radio for at least guard time */ - NETSTACK_RADIO.on(); - packet_seen = NETSTACK_RADIO.receiving_packet(); + tsch_radio_on(TSCH_RADIO_CMD_ON_WITHIN_TIMESLOT); + 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()), current_slot_start, tsch_timing[tsch_ts_rx_offset] + tsch_timing[tsch_ts_rx_wait]); } - if(packet_seen) { + if(!packet_seen) { + /* no packets on air */ + tsch_radio_off(TSCH_RADIO_CMD_OFF_FORCE); + } else { TSCH_DEBUG_RX_EVENT(); /* Save packet timestamp */ rx_start_time = RTIMER_NOW() - RADIO_DELAY_BEFORE_DETECT; - } - if(!NETSTACK_RADIO.receiving_packet() && !NETSTACK_RADIO.pending_packet()) { - NETSTACK_RADIO.off(); - /* no packets on air */ - } else { + /* Wait until packet is received, turn radio off */ 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(); - NETSTACK_RADIO.off(); - -#if TSCH_RESYNC_WITH_SFD_TIMESTAMPS - /* At the end of the reception, get an more accurate estimate of SFD arrival time */ - NETSTACK_RADIO.get_object(RADIO_PARAM_LAST_PACKET_TIMESTAMP, &rx_start_time, sizeof(rtimer_clock_t)); -#endif + tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT); if(NETSTACK_RADIO.pending_packet()) { static int frame_valid; @@ -696,9 +775,9 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t)) static frame802154_t frame; radio_value_t radio_last_rssi; - NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_RSSI, &radio_last_rssi); /* Read packet */ current_input->len = NETSTACK_RADIO.read((void *)current_input->payload, TSCH_PACKET_MAX_LEN); + NETSTACK_RADIO.get_value(RADIO_PARAM_LAST_RSSI, &radio_last_rssi); current_input->rx_asn = current_asn; current_input->rssi = (signed)radio_last_rssi; header_len = frame802154_parse((uint8_t *)current_input->payload, current_input->len, &frame); @@ -706,9 +785,14 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t)) frame802154_check_dest_panid(&frame) && frame802154_extract_linkaddr(&frame, &source_address, &destination_address); +#if TSCH_RESYNC_WITH_SFD_TIMESTAMPS + /* At the end of the reception, get an more accurate estimate of SFD arrival time */ + NETSTACK_RADIO.get_object(RADIO_PARAM_LAST_PACKET_TIMESTAMP, &rx_start_time, sizeof(rtimer_clock_t)); +#endif + packet_duration = TSCH_PACKET_DURATION(current_input->len); -#if TSCH_SECURITY_ENABLED +#if LLSEC802154_ENABLED /* Decrypt and verify incoming frame */ if(frame_valid) { if(tsch_security_parse_frame( @@ -727,17 +811,17 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t)) "!failed to parse frame %u %u", header_len, current_input->len)); frame_valid = 0; } -#endif /* TSCH_SECURITY_ENABLED */ +#endif /* LLSEC802154_ENABLED */ if(frame_valid) { if(linkaddr_cmp(&destination_address, &linkaddr_node_addr) || linkaddr_cmp(&destination_address, &linkaddr_null)) { int do_nack = 0; - estimated_drift = ((int32_t)expected_rx_time - (int32_t)rx_start_time); + estimated_drift = RTIMER_CLOCK_DIFF(expected_rx_time, rx_start_time); #if TSCH_TIMESYNC_REMOVE_JITTER /* remove jitter due to measurement errors */ - if(abs(estimated_drift) <= TSCH_TIMESYNC_MEASUREMENT_ERROR) { + if(ABS(estimated_drift) <= TSCH_TIMESYNC_MEASUREMENT_ERROR) { estimated_drift = 0; } else if(estimated_drift > 0) { estimated_drift -= TSCH_TIMESYNC_MEASUREMENT_ERROR; @@ -761,12 +845,12 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t)) ack_len = tsch_packet_create_eack(ack_buf, sizeof(ack_buf), &source_address, frame.seq, (int16_t)RTIMERTICKS_TO_US(estimated_drift), do_nack); -#if TSCH_SECURITY_ENABLED +#if LLSEC802154_ENABLED if(tsch_is_pan_secured) { /* Secure ACK frame. There is only header and header IEs, therefore data len == 0. */ ack_len += tsch_security_secure_frame(ack_buf, ack_buf, ack_len, 0, ¤t_asn); } -#endif /* TSCH_SECURITY_ENABLED */ +#endif /* LLSEC802154_ENABLED */ /* Copy to radio buffer */ NETSTACK_RADIO.prepare((const void *)ack_buf, ack_len); @@ -776,6 +860,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t)) packet_duration + tsch_timing[tsch_ts_tx_ack_delay] - RADIO_DELAY_BEFORE_TX, "RxBeforeAck"); TSCH_DEBUG_RX_EVENT(); NETSTACK_RADIO.transmit(ack_len); + tsch_radio_off(TSCH_RADIO_CMD_OFF_WITHIN_TIMESLOT); } /* If the sender is a time source, proceed to clock drift compensation */ @@ -805,18 +890,14 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t)) log->rx.sec_level = frame.aux_hdr.security_control.security_level; log->rx.estimated_drift = estimated_drift; ); - } else { - TSCH_LOG_ADD(tsch_log_message, - snprintf(log->message, sizeof(log->message), - "!not for us %x:%x", - destination_address.u8[LINKADDR_SIZE - 2], destination_address.u8[LINKADDR_SIZE - 1]); - ); } /* Poll process for processing of pending input and logs */ process_poll(&tsch_pending_events_process); } } + + tsch_radio_off(TSCH_RADIO_CMD_OFF_END_OF_TIMESLOT); } if(input_queue_drop != 0) { @@ -857,8 +938,12 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr)) } else { uint8_t current_channel; + int is_active_slot; TSCH_DEBUG_SLOT_START(); tsch_in_slot_operation = 1; + /* Reset drift correction */ + drift_correction = 0; + is_drift_correction_used = 0; /* Get a packet ready to be sent */ current_packet = get_packet_and_neighbor_for_link(current_link, ¤t_neighbor); /* There is no packet to send, and this link does not have Rx flag. Instead of doing @@ -867,26 +952,28 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr)) current_link = backup_link; current_packet = get_packet_and_neighbor_for_link(current_link, ¤t_neighbor); } - /* Hop channel */ - current_channel = tsch_calculate_channel(¤t_asn, current_link->channel_offset); - NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, current_channel); - /* Reset drift correction */ - drift_correction = 0; - is_drift_correction_used = 0; - /* Decide whether it is a TX/RX/IDLE or OFF slot */ - /* Actual slot operation */ - if(current_packet != NULL) { - /* We have something to transmit, do the following: - * 1. send - * 2. update_backoff_state(current_neighbor) - * 3. post tx callback - **/ - static struct pt slot_tx_pt; - PT_SPAWN(&slot_operation_pt, &slot_tx_pt, tsch_tx_slot(&slot_tx_pt, t)); - } else if((current_link->link_options & LINK_OPTION_RX)) { - /* Listen */ - static struct pt slot_rx_pt; - PT_SPAWN(&slot_operation_pt, &slot_rx_pt, tsch_rx_slot(&slot_rx_pt, t)); + is_active_slot = current_packet != NULL || (current_link->link_options & LINK_OPTION_RX); + if(is_active_slot) { + /* Hop channel */ + current_channel = tsch_calculate_channel(¤t_asn, current_link->channel_offset); + NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, current_channel); + /* Turn the radio on already here if configured so; necessary for radios with slow startup */ + tsch_radio_on(TSCH_RADIO_CMD_ON_START_OF_TIMESLOT); + /* Decide whether it is a TX/RX/IDLE or OFF slot */ + /* Actual slot operation */ + if(current_packet != NULL) { + /* We have something to transmit, do the following: + * 1. send + * 2. update_backoff_state(current_neighbor) + * 3. post tx callback + **/ + static struct pt slot_tx_pt; + PT_SPAWN(&slot_operation_pt, &slot_tx_pt, tsch_tx_slot(&slot_tx_pt, t)); + } else { + /* Listen */ + static struct pt slot_rx_pt; + PT_SPAWN(&slot_operation_pt, &slot_rx_pt, tsch_rx_slot(&slot_rx_pt, t)); + } } TSCH_DEBUG_SLOT_END(); } diff --git a/core/net/mac/tsch/tsch.c b/core/net/mac/tsch/tsch.c index 1d9701e42..292744ecc 100644 --- a/core/net/mac/tsch/tsch.c +++ b/core/net/mac/tsch/tsch.c @@ -64,7 +64,7 @@ #else /* TSCH_LOG_LEVEL */ #define DEBUG DEBUG_NONE #endif /* TSCH_LOG_LEVEL */ -#include "net/ip/uip-debug.h" +#include "net/net-debug.h" /* Use to collect link statistics even on Keep-Alive, even though they were * not sent from an upper layer and don't have a valid packet_sent callback */ @@ -141,7 +141,7 @@ int tsch_is_coordinator = 0; /* Are we associated to a TSCH network? */ int tsch_is_associated = 0; /* Is the PAN running link-layer security? */ -int tsch_is_pan_secured = TSCH_SECURITY_ENABLED; +int tsch_is_pan_secured = LLSEC802154_ENABLED; /* The current Absolute Slot Number (ASN) */ struct asn_t current_asn; /* Device rank or join priority: @@ -177,7 +177,7 @@ tsch_set_coordinator(int enable) void tsch_set_pan_secured(int enable) { - tsch_is_pan_secured = TSCH_SECURITY_ENABLED && enable; + tsch_is_pan_secured = LLSEC802154_ENABLED && enable; } /*---------------------------------------------------------------------------*/ void @@ -199,8 +199,8 @@ tsch_reset(void) frame802154_set_pan_id(0xffff); /* First make sure pending packet callbacks are sent etc */ process_post_synch(&tsch_pending_events_process, PROCESS_EVENT_POLL, NULL); - /* Empty all neighbor queues */ - /* tsch_queue_flush_all(); */ + /* Reset neighbor queues */ + tsch_queue_reset(); /* Remove unused neighbors */ tsch_queue_free_unused_neighbors(); tsch_queue_update_time_source(NULL); @@ -455,21 +455,21 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp) } #endif /* TSCH_JOIN_SECURED_ONLY */ -#if TSCH_SECURITY_ENABLED +#if LLSEC802154_ENABLED if(!tsch_security_parse_frame(input_eb->payload, hdrlen, input_eb->len - hdrlen - tsch_security_mic_len(&frame), &frame, (linkaddr_t*)&frame.src_addr, ¤t_asn)) { PRINTF("TSCH:! parse_eb: failed to authenticate\n"); return 0; } -#endif /* TSCH_SECURITY_ENABLED */ +#endif /* LLSEC802154_ENABLED */ -#if !TSCH_SECURITY_ENABLED +#if !LLSEC802154_ENABLED if(frame.fcf.security_enabled == 1) { PRINTF("TSCH:! parse_eb: we do not support security, but EB is secured\n"); return 0; } -#endif /* !TSCH_SECURITY_ENABLED */ +#endif /* !LLSEC802154_ENABLED */ #if TSCH_JOIN_MY_PANID_ONLY /* Check if the EB comes from the PAN ID we expect */ @@ -609,24 +609,25 @@ PT_THREAD(tsch_scan(struct pt *pt)) static struct input_packet input_eb; static struct etimer scan_timer; + /* Time when we started scanning on current_channel */ + static clock_time_t current_channel_since; ASN_INIT(current_asn, 0, 0); etimer_set(&scan_timer, CLOCK_SECOND / TSCH_ASSOCIATION_POLL_FREQUENCY); + current_channel_since = clock_time(); while(!tsch_is_associated && !tsch_is_coordinator) { /* Hop to any channel offset */ - static int current_channel = 0; - /* Time when we started scanning on current_channel */ - static clock_time_t current_channel_since = 0; + static uint8_t current_channel = 0; /* We are not coordinator, try to associate */ rtimer_clock_t t0; int is_packet_pending = 0; - clock_time_t now_seconds = clock_seconds(); + clock_time_t now_time = clock_time(); /* Switch to a (new) channel for scanning */ - if(current_channel == 0 || now_seconds != current_channel_since) { + if(current_channel == 0 || now_time - current_channel_since > TSCH_CHANNEL_SCAN_DURATION) { /* 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)]; @@ -635,7 +636,7 @@ PT_THREAD(tsch_scan(struct pt *pt)) current_channel = scan_channel; PRINTF("TSCH: scanning on channel %u\n", scan_channel); } - current_channel_since = now_seconds; + current_channel_since = now_time; } /* Turn radio on and wait for EB */ @@ -649,12 +650,12 @@ PT_THREAD(tsch_scan(struct pt *pt)) } if(is_packet_pending) { - /* Save packet timestamp */ - NETSTACK_RADIO.get_object(RADIO_PARAM_LAST_PACKET_TIMESTAMP, &t0, sizeof(rtimer_clock_t)); - /* 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)); + /* Parse EB and attempt to associate */ PRINTF("TSCH: association: received packet (%u bytes) on channel %u\n", input_eb.len, current_channel); @@ -746,14 +747,14 @@ PROCESS_THREAD(tsch_send_eb_process, ev, data) } packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_BEACONFRAME); packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, tsch_packet_seqno); -#if TSCH_SECURITY_ENABLED +#if LLSEC802154_ENABLED if(tsch_is_pan_secured) { /* Set security level, key id and index */ packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, TSCH_SECURITY_KEY_SEC_LEVEL_EB); packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, FRAME802154_1_BYTE_KEY_ID_MODE); /* Use 1-byte key index */ packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, TSCH_SECURITY_KEY_INDEX_EB); } -#endif /* TSCH_SECURITY_ENABLED */ +#endif /* LLSEC802154_ENABLED */ eb_len = tsch_packet_create_eb(packetbuf_dataptr(), PACKETBUF_SIZE, tsch_packet_seqno, &hdr_len, &tsch_sync_ie_offset); if(eb_len != 0) { @@ -907,14 +908,14 @@ send_packet(mac_callback_t sent, void *ptr) packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME); packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, tsch_packet_seqno); -#if TSCH_SECURITY_ENABLED +#if LLSEC802154_ENABLED if(tsch_is_pan_secured) { /* Set security level, key id and index */ packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, TSCH_SECURITY_KEY_SEC_LEVEL_OTHER); packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, FRAME802154_1_BYTE_KEY_ID_MODE); /* Use 1-byte key index */ packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, TSCH_SECURITY_KEY_INDEX_OTHER); } -#endif /* TSCH_SECURITY_ENABLED */ +#endif /* LLSEC802154_ENABLED */ packet_count_before = tsch_queue_packet_count(addr); @@ -936,6 +937,7 @@ send_packet(mac_callback_t sent, void *ptr) tsch_queue_packet_count(addr), p->header_len, queuebuf_datalen(p->qb)); + (void)packet_count_before; /* Discard "variable set but unused" warning in case of TSCH_LOG_LEVEL of 0 */ } } if(ret != MAC_TX_DEFERRED) { diff --git a/core/net/mac/tsch/tsch.h b/core/net/mac/tsch/tsch.h index 31b5d41f9..d548df9d5 100644 --- a/core/net/mac/tsch/tsch.h +++ b/core/net/mac/tsch/tsch.h @@ -84,8 +84,8 @@ #ifdef TSCH_CONF_JOIN_SECURED_ONLY #define TSCH_JOIN_SECURED_ONLY TSCH_CONF_JOIN_SECURED_ONLY #else -/* By default, set if TSCH_SECURITY_ENABLED is also non-zero */ -#define TSCH_JOIN_SECURED_ONLY TSCH_SECURITY_ENABLED +/* By default, set if LLSEC802154_ENABLED is also non-zero */ +#define TSCH_JOIN_SECURED_ONLY LLSEC802154_ENABLED #endif /* By default, join any PAN ID. Otherwise, wait for an EB from IEEE802154_PANID */ diff --git a/core/net/nbr-table.c b/core/net/nbr-table.c index 6b990a020..4893a99ca 100644 --- a/core/net/nbr-table.c +++ b/core/net/nbr-table.c @@ -47,11 +47,20 @@ static void handle_periodic_timer(void *ptr); static struct ctimer periodic_timer; static uint8_t initialized = 0; +static void print_table(); #define PRINTF(...) printf(__VA_ARGS__) #else #define PRINTF(...) #endif +/* This is the callback function that will be called when there is a + * nbr-policy active + **/ +#ifdef NBR_TABLE_FIND_REMOVABLE +const linkaddr_t *NBR_TABLE_FIND_REMOVABLE(nbr_table_reason_t reason, void *data); +#endif /* NBR_TABLE_FIND_REMOVABLE */ + + /* List of link-layer addresses of the neighbors, used as key in the tables */ typedef struct nbr_table_key { struct nbr_table_key *next; @@ -169,8 +178,27 @@ nbr_set_bit(uint8_t *bitmap, nbr_table_t *table, nbr_table_item_t *item, int val return 0; } /*---------------------------------------------------------------------------*/ +static void +remove_key(nbr_table_key_t *least_used_key) +{ + int i; + for(i = 0; i < MAX_NUM_TABLES; i++) { + if(all_tables[i] != NULL && all_tables[i]->callback != NULL) { + /* Call table callback for each table that uses this item */ + nbr_table_item_t *removed_item = item_from_key(all_tables[i], least_used_key); + if(nbr_get_bit(used_map, all_tables[i], removed_item) == 1) { + all_tables[i]->callback(removed_item); + } + } + } + /* Empty used map */ + used_map[index_from_key(least_used_key)] = 0; + /* Remove neighbor from list */ + list_remove(nbr_table_keys, least_used_key); +} +/*---------------------------------------------------------------------------*/ static nbr_table_key_t * -nbr_table_allocate(void) +nbr_table_allocate(nbr_table_reason_t reason, void *data) { nbr_table_key_t *key; int least_used_count = 0; @@ -179,59 +207,72 @@ nbr_table_allocate(void) key = memb_alloc(&neighbor_addr_mem); if(key != NULL) { return key; - } else { /* No more space, try to free a neighbor. - * The replacement policy is the following: remove neighbor that is: - * (1) not locked - * (2) used by fewest tables - * (3) oldest (the list is ordered by insertion time) - * */ - /* Get item from first key */ - key = list_head(nbr_table_keys); - while(key != NULL) { - int item_index = index_from_key(key); - int locked = locked_map[item_index]; - /* Never delete a locked item */ - if(!locked) { - int used = used_map[item_index]; - int used_count = 0; - /* Count how many tables are using this item */ - while(used != 0) { - if((used & 1) == 1) { - used_count++; - } - used >>= 1; - } - /* Find least used item */ - if(least_used_key == NULL || used_count < least_used_count) { - least_used_key = key; - least_used_count = used_count; - if(used_count == 0) { /* We won't find any least used item */ - break; - } - } + } else { +#ifdef NBR_TABLE_FIND_REMOVABLE + const linkaddr_t *lladdr; + lladdr = NBR_TABLE_FIND_REMOVABLE(reason, data); + if(lladdr == NULL) { + /* Nothing found that can be deleted - return NULL to indicate failure */ + PRINTF("*** Not removing entry to allocate new\n"); + return NULL; + } else { + /* used least_used_key to indicate what is the least useful entry */ + int index; + int locked = 0; + if((index = index_from_lladdr(lladdr)) != -1) { + least_used_key = key_from_index(index); + locked = locked_map[index]; + } + /* Allow delete of locked item? */ + if(least_used_key != NULL && locked) { + PRINTF("Deleting locked item!\n"); + locked_map[index] = 0; } - key = list_item_next(key); } +#endif /* NBR_TABLE_FIND_REMOVABLE */ + + if(least_used_key == NULL) { + /* No more space, try to free a neighbor. + * The replacement policy is the following: remove neighbor that is: + * (1) not locked + * (2) used by fewest tables + * (3) oldest (the list is ordered by insertion time) + * */ + /* Get item from first key */ + key = list_head(nbr_table_keys); + while(key != NULL) { + int item_index = index_from_key(key); + int locked = locked_map[item_index]; + /* Never delete a locked item */ + if(!locked) { + int used = used_map[item_index]; + int used_count = 0; + /* Count how many tables are using this item */ + while(used != 0) { + if((used & 1) == 1) { + used_count++; + } + used >>= 1; + } + /* Find least used item */ + if(least_used_key == NULL || used_count < least_used_count) { + least_used_key = key; + least_used_count = used_count; + if(used_count == 0) { /* We won't find any least used item */ + break; + } + } + } + key = list_item_next(key); + } + } + if(least_used_key == NULL) { /* We haven't found any unlocked item, allocation fails */ return NULL; } else { /* Reuse least used item */ - int i; - for(i = 0; icallback != NULL) { - /* Call table callback for each table that uses this item */ - nbr_table_item_t *removed_item = item_from_key(all_tables[i], least_used_key); - if(nbr_get_bit(used_map, all_tables[i], removed_item) == 1) { - all_tables[i]->callback(removed_item); - } - } - } - /* Empty used map */ - used_map[index_from_key(least_used_key)] = 0; - /* Remove neighbor from list */ - list_remove(nbr_table_keys, least_used_key); - /* Return associated key */ + remove_key(least_used_key); return least_used_key; } } @@ -289,7 +330,7 @@ nbr_table_next(nbr_table_t *table, nbr_table_item_t *item) /*---------------------------------------------------------------------------*/ /* Add a neighbor indexed with its link-layer address */ nbr_table_item_t * -nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr) +nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr, nbr_table_reason_t reason, void *data) { int index; nbr_table_item_t *item; @@ -303,7 +344,7 @@ nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr) if((index = index_from_lladdr(lladdr)) == -1) { /* Neighbor not yet in table, let's try to allocate one */ - key = nbr_table_allocate(); + key = nbr_table_allocate(reason, data); /* No space available for new entry */ if(key == NULL) { @@ -327,6 +368,9 @@ nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr) memset(item, 0, table->item_size); nbr_set_bit(used_map, table, item, 1); +#if DEBUG + print_table(); +#endif return item; } /*---------------------------------------------------------------------------*/ @@ -377,9 +421,42 @@ nbr_table_get_lladdr(nbr_table_t *table, const void *item) return key != NULL ? &key->lladdr : NULL; } /*---------------------------------------------------------------------------*/ +/* Update link-layer address of an item */ +int +nbr_table_update_lladdr(const linkaddr_t *old_addr, const linkaddr_t *new_addr, + int remove_if_duplicate) +{ + int index; + int new_index; + nbr_table_key_t *key; + index = index_from_lladdr(old_addr); + if(index == -1) { + /* Failure to change since there is nothing to change. */ + return 0; + } + if((new_index = index_from_lladdr(new_addr)) != -1) { + /* check if it is a change or not - do not remove / fail if same */ + if(new_index == index) { + return 1; + } + /* This new entry already exists - failure! - remove if requested. */ + if(remove_if_duplicate) { + remove_key(key_from_index(index)); + } + return 0; + } + key = key_from_index(index); + /** + * Copy the new lladdr into the key - since we know that there is no + * conflicting entry. + */ + memcpy(&key->lladdr, new_addr, sizeof(linkaddr_t)); + return 1; +} +/*---------------------------------------------------------------------------*/ #if DEBUG static void -handle_periodic_timer(void *ptr) +print_table() { int i, j; /* Printout all neighbors and which tables they are used in */ @@ -394,6 +471,12 @@ handle_periodic_timer(void *ptr) PRINTF("\n"); } } +} +/*---------------------------------------------------------------------------*/ +static void +handle_periodic_timer(void *ptr) +{ + print_table(); ctimer_reset(&periodic_timer); } #endif diff --git a/core/net/nbr-table.h b/core/net/nbr-table.h index 516901fe3..320ef2e5f 100644 --- a/core/net/nbr-table.h +++ b/core/net/nbr-table.h @@ -75,6 +75,18 @@ typedef struct nbr_table { /** \brief Declaration of non-static neighbor tables */ #define NBR_TABLE_DECLARE(name) extern nbr_table_t *name +typedef enum { + NBR_TABLE_REASON_UNDEFINED, + NBR_TABLE_REASON_RPL_DIO, + NBR_TABLE_REASON_RPL_DAO, + NBR_TABLE_REASON_RPL_DIS, + NBR_TABLE_REASON_ROUTE, + NBR_TABLE_REASON_IPV6_ND, + NBR_TABLE_REASON_MAC, + NBR_TABLE_REASON_LLSEC, + NBR_TABLE_REASON_LINK_STATS, +} nbr_table_reason_t; + /** \name Neighbor tables: register and loop through table elements */ /** @{ */ int nbr_table_register(nbr_table_t *table, nbr_table_callback *callback); @@ -84,7 +96,7 @@ nbr_table_item_t *nbr_table_next(nbr_table_t *table, nbr_table_item_t *item); /** \name Neighbor tables: add and get data */ /** @{ */ -nbr_table_item_t *nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr); +nbr_table_item_t *nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr, nbr_table_reason_t reason, void *data); nbr_table_item_t *nbr_table_get_from_lladdr(nbr_table_t *table, const linkaddr_t *lladdr); /** @} */ @@ -98,6 +110,7 @@ int nbr_table_unlock(nbr_table_t *table, nbr_table_item_t *item); /** \name Neighbor tables: address manipulation */ /** @{ */ linkaddr_t *nbr_table_get_lladdr(nbr_table_t *table, const nbr_table_item_t *item); +int nbr_table_update_lladdr(const linkaddr_t *old_addr, const linkaddr_t *new_addr, int remove_if_duplicate); /** @} */ #endif /* NBR_TABLE_H_ */ diff --git a/core/net/net-debug.c b/core/net/net-debug.c new file mode 100644 index 000000000..8dd630666 --- /dev/null +++ b/core/net/net-debug.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \file + * A set of debugging tools for the IP stack + * \author + * Nicolas Tsiftes + * Niclas Finne + * Joakim Eriksson + * Simon Duquennoy + */ + +#include "net/net-debug.h" + +/*---------------------------------------------------------------------------*/ +void +net_debug_lladdr_print(const uip_lladdr_t *addr) +{ + if(addr == NULL) { + PRINTA("(NULL LL addr)"); + return; + } else { +#if NETSTACK_CONF_WITH_RIME + /* Rime uses traditionally a %u.%u format */ + PRINTA("%u.%u", addr->addr[0], addr->addr[1]); +#else /* NETSTACK_CONF_WITH_RIME */ + unsigned int i; + for(i = 0; i < LINKADDR_SIZE; i++) { + if(i > 0) { + PRINTA(":"); + } + PRINTA("%02x", addr->addr[i]); + } +#endif /* NETSTACK_CONF_WITH_RIME */ + } +} +/*---------------------------------------------------------------------------*/ diff --git a/core/net/net-debug.h b/core/net/net-debug.h new file mode 100644 index 000000000..a4c6a3313 --- /dev/null +++ b/core/net/net-debug.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/** + * \file + * A set of debugging macros for the netstack + * + * \author Nicolas Tsiftes + * Niclas Finne + * Joakim Eriksson + * Simon Duquennoy + */ + +#ifndef NET_DEBUG_H +#define NET_DEBUG_H + +#include "net/ip/uip.h" +#include "net/linkaddr.h" +#include + +void net_debug_lladdr_print(const uip_lladdr_t *addr); + +#define DEBUG_NONE 0 +#define DEBUG_PRINT 1 +#define DEBUG_ANNOTATE 2 +#define DEBUG_FULL DEBUG_ANNOTATE | DEBUG_PRINT + +/* PRINTA will always print if the debug routines are called directly */ +#ifdef __AVR__ +#include +#define PRINTA(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTA(...) printf(__VA_ARGS__) +#endif + +#if (DEBUG) & DEBUG_ANNOTATE +#ifdef __AVR__ +#define ANNOTATE(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#else +#define ANNOTATE(...) printf(__VA_ARGS__) +#endif +#else +#define ANNOTATE(...) +#endif /* (DEBUG) & DEBUG_ANNOTATE */ + +#if (DEBUG) & DEBUG_PRINT +#ifdef __AVR__ +#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTF(...) printf(__VA_ARGS__) +#endif +#define PRINTLLADDR(lladdr) net_debug_lladdr_print(lladdr) +#else +#define PRINTF(...) +#define PRINTLLADDR(lladdr) +#endif /* (DEBUG) & DEBUG_PRINT */ + +#endif /* NET_DEBUG_H */ diff --git a/core/net/packetbuf.c b/core/net/packetbuf.c index c7e2a9898..4869263cf 100644 --- a/core/net/packetbuf.c +++ b/core/net/packetbuf.c @@ -47,23 +47,22 @@ #include "contiki-net.h" #include "net/packetbuf.h" #include "net/rime/rime.h" +#include "sys/cc.h" struct packetbuf_attr packetbuf_attrs[PACKETBUF_NUM_ATTRS]; struct packetbuf_addr packetbuf_addrs[PACKETBUF_NUM_ADDRS]; static uint16_t buflen, bufptr; -static uint8_t hdrptr; +static uint8_t hdrlen; /* The declarations below ensure that the packet buffer is aligned on an even 32-bit boundary. On some platforms (most notably the msp430 or OpenRISC), having a potentially misaligned packet buffer may lead to problems when accessing words. */ -static uint32_t packetbuf_aligned[(PACKETBUF_SIZE + PACKETBUF_HDR_SIZE + 3) / 4]; +static uint32_t packetbuf_aligned[(PACKETBUF_SIZE + 3) / 4]; static uint8_t *packetbuf = (uint8_t *)packetbuf_aligned; -static uint8_t *packetbufptr; - #define DEBUG 0 #if DEBUG #include @@ -77,26 +76,19 @@ void packetbuf_clear(void) { buflen = bufptr = 0; - hdrptr = PACKETBUF_HDR_SIZE; + hdrlen = 0; - packetbufptr = &packetbuf[PACKETBUF_HDR_SIZE]; packetbuf_attr_clear(); } /*---------------------------------------------------------------------------*/ -void -packetbuf_clear_hdr(void) -{ - hdrptr = PACKETBUF_HDR_SIZE; -} -/*---------------------------------------------------------------------------*/ int packetbuf_copyfrom(const void *from, uint16_t len) { uint16_t l; packetbuf_clear(); - l = len > PACKETBUF_SIZE? PACKETBUF_SIZE: len; - memcpy(packetbufptr, from, l); + l = MIN(PACKETBUF_SIZE, len); + memcpy(packetbuf, from, l); buflen = l; return l; } @@ -104,82 +96,43 @@ packetbuf_copyfrom(const void *from, uint16_t len) void packetbuf_compact(void) { - int i, len; + int16_t i; - if(bufptr > 0) { - len = packetbuf_datalen() + PACKETBUF_HDR_SIZE; - for(i = PACKETBUF_HDR_SIZE; i < len; i++) { - packetbuf[i] = packetbuf[bufptr + i]; + if(bufptr) { + /* shift data to the left */ + for(i = 0; i < buflen; i++) { + packetbuf[hdrlen + i] = packetbuf[packetbuf_hdrlen() + i]; } - bufptr = 0; } } /*---------------------------------------------------------------------------*/ int -packetbuf_copyto_hdr(uint8_t *to) -{ -#if DEBUG_LEVEL > 0 - { - int i; - PRINTF("packetbuf_write_hdr: header:\n"); - for(i = hdrptr; i < PACKETBUF_HDR_SIZE; ++i) { - PRINTF("0x%02x, ", packetbuf[i]); - } - PRINTF("\n"); - } -#endif /* DEBUG_LEVEL */ - memcpy(to, packetbuf + hdrptr, PACKETBUF_HDR_SIZE - hdrptr); - return PACKETBUF_HDR_SIZE - hdrptr; -} -/*---------------------------------------------------------------------------*/ -int packetbuf_copyto(void *to) { -#if DEBUG_LEVEL > 0 - { - int i; - char buffer[1000]; - char *bufferptr = buffer; - int bufferlen = 0; - - bufferptr[0] = 0; - for(i = hdrptr; i < PACKETBUF_HDR_SIZE; ++i) { - bufferptr += sprintf(bufferptr, "0x%02x, ", packetbuf[i]); - } - PRINTF("packetbuf_write: header: %s\n", buffer); - bufferptr = buffer; - bufferptr[0] = 0; - for(i = bufptr; ((i < buflen + bufptr) && (bufferlen < (sizeof(buffer) - 10))); ++i) { - bufferlen += sprintf(bufferptr + bufferlen, "0x%02x, ", packetbufptr[i]); - } - PRINTF("packetbuf_write: data: %s\n", buffer); - } -#endif /* DEBUG_LEVEL */ - if(PACKETBUF_HDR_SIZE - hdrptr + buflen > PACKETBUF_SIZE) { - /* Too large packet */ + if(hdrlen + buflen > PACKETBUF_SIZE) { return 0; } - memcpy(to, packetbuf + hdrptr, PACKETBUF_HDR_SIZE - hdrptr); - memcpy((uint8_t *)to + PACKETBUF_HDR_SIZE - hdrptr, packetbufptr + bufptr, - buflen); - return PACKETBUF_HDR_SIZE - hdrptr + buflen; + memcpy(to, packetbuf_hdrptr(), hdrlen); + memcpy((uint8_t *)to + hdrlen, packetbuf_dataptr(), buflen); + return hdrlen + buflen; } /*---------------------------------------------------------------------------*/ int packetbuf_hdralloc(int size) { - if(hdrptr >= size && packetbuf_totlen() + size <= PACKETBUF_SIZE) { - hdrptr -= size; - return 1; + int16_t i; + + if(size + packetbuf_totlen() > PACKETBUF_SIZE) { + return 0; } - return 0; -} -/*---------------------------------------------------------------------------*/ -void -packetbuf_hdr_remove(int size) -{ - hdrptr += size; + + /* shift data to the right */ + for(i = packetbuf_totlen() - 1; i >= 0; i--) { + packetbuf[i + size] = packetbuf[i]; + } + hdrlen += size; + return 1; } /*---------------------------------------------------------------------------*/ int @@ -204,13 +157,13 @@ packetbuf_set_datalen(uint16_t len) void * packetbuf_dataptr(void) { - return (void *)(&packetbuf[bufptr + PACKETBUF_HDR_SIZE]); + return packetbuf + packetbuf_hdrlen(); } /*---------------------------------------------------------------------------*/ void * packetbuf_hdrptr(void) { - return (void *)(&packetbuf[hdrptr]); + return packetbuf; } /*---------------------------------------------------------------------------*/ uint16_t @@ -222,16 +175,7 @@ packetbuf_datalen(void) uint8_t packetbuf_hdrlen(void) { - uint8_t hdrlen; - - hdrlen = PACKETBUF_HDR_SIZE - hdrptr; - if(hdrlen) { - /* outbound packet */ - return hdrlen; - } else { - /* inbound packet */ - return bufptr; - } + return bufptr + hdrlen; } /*---------------------------------------------------------------------------*/ uint16_t @@ -244,9 +188,7 @@ void packetbuf_attr_clear(void) { int i; - for(i = 0; i < PACKETBUF_NUM_ATTRS; ++i) { - packetbuf_attrs[i].val = 0; - } + memset(packetbuf_attrs, 0, sizeof(packetbuf_attrs)); for(i = 0; i < PACKETBUF_NUM_ADDRS; ++i) { linkaddr_copy(&packetbuf_addrs[i].addr, &linkaddr_null); } @@ -272,7 +214,6 @@ packetbuf_attr_copyfrom(struct packetbuf_attr *attrs, int packetbuf_set_attr(uint8_t type, const packetbuf_attr_t val) { -/* packetbuf_attrs[type].type = type; */ packetbuf_attrs[type].val = val; return 1; } @@ -286,7 +227,6 @@ packetbuf_attr(uint8_t type) int packetbuf_set_addr(uint8_t type, const linkaddr_t *addr) { -/* packetbuf_addrs[type - PACKETBUF_ADDR_FIRST].type = type; */ linkaddr_copy(&packetbuf_addrs[type - PACKETBUF_ADDR_FIRST].addr, addr); return 1; } diff --git a/core/net/packetbuf.h b/core/net/packetbuf.h index 12b0d9dce..6f5d4b740 100644 --- a/core/net/packetbuf.h +++ b/core/net/packetbuf.h @@ -66,15 +66,6 @@ #define PACKETBUF_SIZE 128 #endif -/** - * \brief The size of the packetbuf header, in bytes - */ -#ifdef PACKETBUF_CONF_HDR_SIZE -#define PACKETBUF_HDR_SIZE PACKETBUF_CONF_HDR_SIZE -#else -#define PACKETBUF_HDR_SIZE 48 -#endif - #ifdef PACKETBUF_CONF_WITH_PACKET_TYPE #define PACKETBUF_WITH_PACKET_TYPE PACKETBUF_CONF_WITH_PACKET_TYPE #else @@ -92,21 +83,6 @@ */ void packetbuf_clear(void); -/** - * \brief Clear and reset the header of the packetbuf - * - * This function clears the header of the packetbuf and - * resets all the internal state pointers pertaining to - * the header (header size, header pointer, but not - * external data pointer). It is used before after sending - * a packet in the packetbuf, to be able to reuse the - * packet buffer for a later retransmission. - * - */ -void packetbuf_clear_hdr(void); - -void packetbuf_hdr_remove(int bytes); - /** * \brief Get a pointer to the data in the packetbuf * \return Pointer to the packetbuf data @@ -115,15 +91,6 @@ void packetbuf_hdr_remove(int bytes); * the packetbuf. The data is either stored in the packetbuf, * or referenced to an external location. * - * For outbound packets, the packetbuf consists of two - * parts: header and data. The header is accessed with the - * packetbuf_hdrptr() function. - * - * For incoming packets, both the packet header and the - * packet data is stored in the data portion of the - * packetbuf. Thus this function is used to get a pointer to - * the header for incoming packets. - * */ void *packetbuf_dataptr(void); @@ -131,11 +98,6 @@ void *packetbuf_dataptr(void); * \brief Get a pointer to the header in the packetbuf, for outbound packets * \return Pointer to the packetbuf header * - * For outbound packets, the packetbuf consists of two - * parts: header and data. This function is used to get a - * pointer to the header in the packetbuf. The header is - * stored in the packetbuf. - * */ void *packetbuf_hdrptr(void); @@ -143,12 +105,6 @@ void *packetbuf_hdrptr(void); * \brief Get the length of the header in the packetbuf * \return Length of the header in the packetbuf * - * For outbound packets, the packetbuf consists of two - * parts: header and data. This function is used to get - * the length of the header in the packetbuf. The header is - * stored in the packetbuf and accessed via the - * packetbuf_hdrptr() function. - * */ uint8_t packetbuf_hdrlen(void); @@ -157,17 +113,6 @@ uint8_t packetbuf_hdrlen(void); * \brief Get the length of the data in the packetbuf * \return Length of the data in the packetbuf * - * For outbound packets, the packetbuf consists of two - * parts: header and data. This function is used to get - * the length of the data in the packetbuf. The data is - * stored in the packetbuf and accessed via the - * packetbuf_dataptr() function. - * - * For incoming packets, both the packet header and the - * packet data is stored in the data portion of the - * packetbuf. This function is then used to get the total - * length of the packet - both header and data. - * */ uint16_t packetbuf_datalen(void); @@ -181,10 +126,6 @@ uint16_t packetbuf_totlen(void); /** * \brief Set the length of the data in the packetbuf * \param len The length of the data - * - * For outbound packets, the packetbuf consists of two - * parts: header and data. This function is used to set - * the length of the data in the packetbuf. */ void packetbuf_set_datalen(uint16_t len); @@ -228,29 +169,13 @@ int packetbuf_copyfrom(const void *from, uint16_t len); * * The external buffer to which the packetbuf is to be * copied must be able to accomodate at least - * (PACKETBUF_SIZE + PACKETBUF_HDR_SIZE) bytes. The number of + * PACKETBUF_SIZE bytes. The number of * bytes that was copied to the external buffer is * returned. * */ int packetbuf_copyto(void *to); -/** - * \brief Copy the header portion of the packetbuf to an external buffer - * \param to A pointer to the buffer to which the data is to be copied - * \retval The number of bytes that was copied to the external buffer - * - * This function copies the header portion of the packetbuf - * to an external buffer. - * - * The external buffer to which the packetbuf is to be - * copied must be able to accomodate at least - * PACKETBUF_HDR_SIZE bytes. The number of bytes that was - * copied to the external buffer is returned. - * - */ -int packetbuf_copyto_hdr(uint8_t *to); - /** * \brief Extend the header of the packetbuf, for outbound packets * \param size The number of bytes the header should be extended @@ -284,11 +209,9 @@ int packetbuf_hdrreduce(int size); typedef uint16_t packetbuf_attr_t; struct packetbuf_attr { -/* uint8_t type; */ packetbuf_attr_t val; }; struct packetbuf_addr { -/* uint8_t type; */ linkaddr_t addr; }; @@ -332,9 +255,9 @@ enum { #endif /* NETSTACK_CONF_WITH_RIME */ PACKETBUF_ATTR_PENDING, PACKETBUF_ATTR_FRAME_TYPE, -#if LLSEC802154_SECURITY_LEVEL +#if LLSEC802154_USES_AUX_HEADER PACKETBUF_ATTR_SECURITY_LEVEL, -#endif /* LLSEC802154_SECURITY_LEVEL */ +#endif /* LLSEC802154_USES_AUX_HEADER */ #if LLSEC802154_USES_FRAME_COUNTER PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, @@ -365,29 +288,6 @@ enum { PACKETBUF_ATTR_MAX }; -/* Define surrogates when 802.15.4 security is off */ -#if !LLSEC802154_SECURITY_LEVEL -enum { - PACKETBUF_ATTR_SECURITY_LEVEL, -}; -#endif /* LLSEC802154_SECURITY_LEVEL */ - -#if !LLSEC802154_USES_FRAME_COUNTER -enum { - PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, - PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3 -}; -#endif /* LLSEC802154_USES_FRAME_COUNTER */ - -/* Define surrogates when not using explicit keys */ -#if !LLSEC802154_USES_EXPLICIT_KEYS -enum { - PACKETBUF_ATTR_KEY_ID_MODE, - PACKETBUF_ATTR_KEY_INDEX, - PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1 -}; -#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ - #if NETSTACK_CONF_WITH_RIME #define PACKETBUF_NUM_ADDRS 4 #else /* NETSTACK_CONF_WITH_RIME */ @@ -403,15 +303,9 @@ enum { extern struct packetbuf_attr packetbuf_attrs[]; extern struct packetbuf_addr packetbuf_addrs[]; -static int packetbuf_set_attr(uint8_t type, const packetbuf_attr_t val); -static packetbuf_attr_t packetbuf_attr(uint8_t type); -static int packetbuf_set_addr(uint8_t type, const linkaddr_t *addr); -static const linkaddr_t *packetbuf_addr(uint8_t type); - static inline int packetbuf_set_attr(uint8_t type, const packetbuf_attr_t val) { -/* packetbuf_attrs[type].type = type; */ packetbuf_attrs[type].val = val; return 1; } @@ -424,7 +318,6 @@ packetbuf_attr(uint8_t type) static inline int packetbuf_set_addr(uint8_t type, const linkaddr_t *addr) { -/* packetbuf_addrs[type - PACKETBUF_ADDR_FIRST].type = type; */ linkaddr_copy(&packetbuf_addrs[type - PACKETBUF_ADDR_FIRST].addr, addr); return 1; } diff --git a/core/net/rime/chameleon-raw.c b/core/net/rime/chameleon-raw.c old mode 100644 new mode 100755 index 8efcf8a1f..16b17fb5d --- a/core/net/rime/chameleon-raw.c +++ b/core/net/rime/chameleon-raw.c @@ -205,10 +205,7 @@ hdrsize(const struct packetbuf_attrlist *a) continue; } #endif /* CHAMELEON_WITH_MAC_LINK_ADDRESSES */ - len = a->len; - if(len < 8) { - len = 8; - } + len = (a->len & 0xf8) + ((a->len & 7) ? 8: 0); size += len; } return size / 8; diff --git a/core/net/rpl/rpl-conf.h b/core/net/rpl/rpl-conf.h index 5511b8289..97ab8f49d 100644 --- a/core/net/rpl/rpl-conf.h +++ b/core/net/rpl/rpl-conf.h @@ -45,31 +45,52 @@ #define RPL_CONF_STATS 0 #endif /* RPL_CONF_STATS */ -/* - * Select routing metric supported at runtime. This must be a valid - * DAG Metric Container Object Type (see below). Currently, we only - * support RPL_DAG_MC_ETX and RPL_DAG_MC_ENERGY. - * When MRHOF (RFC6719) is used with ETX, no metric container must - * be used; instead the rank carries ETX directly. +/* + * The objective function (OF) used by a RPL root is configurable through + * the RPL_CONF_OF_OCP parameter. This is defined as the objective code + * point (OCP) of the OF, RPL_OCP_OF0 or RPL_OCP_MRHOF. This flag is of + * no relevance to non-root nodes, which run the OF advertised in the + * instance they join. + * Make sure the selected of is inRPL_SUPPORTED_OFS. */ +#ifdef RPL_CONF_OF_OCP +#define RPL_OF_OCP RPL_CONF_OF_OCP +#else /* RPL_CONF_OF_OCP */ +#define RPL_OF_OCP RPL_OCP_MRHOF +#endif /* RPL_CONF_OF_OCP */ + +/* + * The set of objective functions supported at runtime. Nodes are only + * able to join instances that advertise an OF in this set. To include + * both OF0 and MRHOF, use {&rpl_of0, &rpl_mrhof}. + */ +#ifdef RPL_CONF_SUPPORTED_OFS +#define RPL_SUPPORTED_OFS RPL_CONF_SUPPORTED_OFS +#else /* RPL_CONF_SUPPORTED_OFS */ +#define RPL_SUPPORTED_OFS {&rpl_mrhof} +#endif /* RPL_CONF_SUPPORTED_OFS */ + +/* + * Enable/disable RPL Metric Containers (MC). The actual MC in use + * for a given DODAG is decided at runtime, when joining. Note that + * OF0 (RFC6552) operates without MC, and so does MRHOF (RFC6719) when + * used with ETX as a metric (the rank is the metric). We disable MC + * by default, but note it must be enabled to support joining a DODAG + * that requires MC (e.g., MRHOF with a metric other than ETX). + */ +#ifdef RPL_CONF_WITH_MC +#define RPL_WITH_MC RPL_CONF_WITH_MC +#else /* RPL_CONF_WITH_MC */ +#define RPL_WITH_MC 0 +#endif /* RPL_CONF_WITH_MC */ + +/* The MC advertised in DIOs and propagating from the root */ #ifdef RPL_CONF_DAG_MC #define RPL_DAG_MC RPL_CONF_DAG_MC #else #define RPL_DAG_MC RPL_DAG_MC_NONE #endif /* RPL_CONF_DAG_MC */ -/* - * The objective function used by RPL is configurable through the - * RPL_CONF_OF parameter. This should be defined to be the name of an - * rpl_of object linked into the system image, e.g., rpl_of0. - */ -#ifdef RPL_CONF_OF -#define RPL_OF RPL_CONF_OF -#else -/* ETX is the default objective function. */ -#define RPL_OF rpl_mrhof -#endif /* RPL_CONF_OF */ - /* This value decides which DAG instance we should participate in by default. */ #ifdef RPL_CONF_DEFAULT_INSTANCE #define RPL_DEFAULT_INSTANCE RPL_CONF_DEFAULT_INSTANCE @@ -118,7 +139,7 @@ #ifdef RPL_CONF_DEFAULT_ROUTE_INFINITE_LIFETIME #define RPL_DEFAULT_ROUTE_INFINITE_LIFETIME RPL_CONF_DEFAULT_ROUTE_INFINITE_LIFETIME #else -#define RPL_DEFAULT_ROUTE_INFINITE_LIFETIME 0 +#define RPL_DEFAULT_ROUTE_INFINITE_LIFETIME 1 #endif /* RPL_CONF_DEFAULT_ROUTE_INFINITE_LIFETIME */ /* @@ -186,21 +207,12 @@ #define RPL_DIO_REDUNDANCY 10 #endif -/* - * Initial metric attributed to a link when the ETX is unknown - */ -#ifndef RPL_CONF_INIT_LINK_METRIC -#define RPL_INIT_LINK_METRIC 2 -#else -#define RPL_INIT_LINK_METRIC RPL_CONF_INIT_LINK_METRIC -#endif - /* * Default route lifetime unit. This is the granularity of time * used in RPL lifetime values, in seconds. */ #ifndef RPL_CONF_DEFAULT_LIFETIME_UNIT -#define RPL_DEFAULT_LIFETIME_UNIT 0xffff +#define RPL_DEFAULT_LIFETIME_UNIT 60 #else #define RPL_DEFAULT_LIFETIME_UNIT RPL_CONF_DEFAULT_LIFETIME_UNIT #endif @@ -209,7 +221,7 @@ * Default route lifetime as a multiple of the lifetime unit. */ #ifndef RPL_CONF_DEFAULT_LIFETIME -#define RPL_DEFAULT_LIFETIME 0xff +#define RPL_DEFAULT_LIFETIME 30 #else #define RPL_DEFAULT_LIFETIME RPL_CONF_DEFAULT_LIFETIME #endif @@ -224,16 +236,38 @@ #endif /* - * Hop-by-hop option - * This option control the insertion of the RPL Hop-by-Hop extension header - * into packets originating from this node. Incoming Hop-by-hop extension - * header are still processed and forwarded. - */ -#ifdef RPL_CONF_INSERT_HBH_OPTION -#define RPL_INSERT_HBH_OPTION RPL_CONF_INSERT_HBH_OPTION + * RPL DAO ACK support. When enabled, DAO ACK will be sent and requested. + * This will also enable retransmission of DAO when no ack is received. + * */ +#ifdef RPL_CONF_WITH_DAO_ACK +#define RPL_WITH_DAO_ACK RPL_CONF_WITH_DAO_ACK #else -#define RPL_INSERT_HBH_OPTION 1 -#endif +#define RPL_WITH_DAO_ACK 0 +#endif /* RPL_CONF_WITH_DAO_ACK */ + +/* + * RPL REPAIR ON DAO NACK. When enabled, DAO NACK will trigger a local + * repair in order to quickly find a new parent to send DAO's to. + * NOTE: this is too agressive in some cases so use with care. + * */ +#ifdef RPL_CONF_RPL_REPAIR_ON_DAO_NACK +#define RPL_REPAIR_ON_DAO_NACK RPL_CONF_RPL_REPAIR_ON_DAO_NACK +#else +#define RPL_REPAIR_ON_DAO_NACK 0 +#endif /* RPL_CONF_RPL_REPAIR_ON_DAO_NACK */ + +/* + * Setting the DIO_REFRESH_DAO_ROUTES will make the RPL root always + * increase the DTSN (Destination Advertisement Trigger Sequence Number) + * when sending multicast DIO. This is to get all children to re-register + * their DAO route. This is needed when DAO-ACK is not enabled to add + * reliability to route maintenance. + * */ +#ifdef RPL_CONF_DIO_REFRESH_DAO_ROUTES +#define RPL_DIO_REFRESH_DAO_ROUTES RPL_CONF_DIO_REFRESH_DAO_ROUTES +#else +#define RPL_DIO_REFRESH_DAO_ROUTES 1 +#endif /* RPL_CONF_DIO_REFRESH_DAO_ROUTES */ /* * RPL probing. When enabled, probes will be sent periodically to keep @@ -254,22 +288,13 @@ #define RPL_PROBING_INTERVAL (120 * CLOCK_SECOND) #endif -/* - * RPL probing expiration time. - */ -#ifdef RPL_CONF_PROBING_EXPIRATION_TIME -#define RPL_PROBING_EXPIRATION_TIME RPL_CONF_PROBING_EXPIRATION_TIME -#else -#define RPL_PROBING_EXPIRATION_TIME (10 * 60 * CLOCK_SECOND) -#endif - /* * Function used to select the next parent to be probed. */ #ifdef RPL_CONF_PROBING_SELECT_FUNC #define RPL_PROBING_SELECT_FUNC RPL_CONF_PROBING_SELECT_FUNC #else -#define RPL_PROBING_SELECT_FUNC(dag) get_probing_target((dag)) +#define RPL_PROBING_SELECT_FUNC get_probing_target #endif /* @@ -292,8 +317,7 @@ #ifdef RPL_CONF_PROBING_DELAY_FUNC #define RPL_PROBING_DELAY_FUNC RPL_CONF_PROBING_DELAY_FUNC #else -#define RPL_PROBING_DELAY_FUNC() ((RPL_PROBING_INTERVAL / 2) \ - + random_rand() % (RPL_PROBING_INTERVAL)) +#define RPL_PROBING_DELAY_FUNC get_probing_delay #endif /* diff --git a/core/net/rpl/rpl-dag-root.c b/core/net/rpl/rpl-dag-root.c index efbdb4035..57a10ef80 100644 --- a/core/net/rpl/rpl-dag-root.c +++ b/core/net/rpl/rpl-dag-root.c @@ -43,7 +43,9 @@ #define RPL_DAG_GRACE_PERIOD (CLOCK_SECOND * 20 * 1) +#if (UIP_CONF_MAX_ROUTES != 0) static struct uip_ds6_notification n; +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ static uint8_t to_become_root; static struct ctimer c; /*---------------------------------------------------------------------------*/ @@ -121,6 +123,7 @@ create_dag_callback(void *ptr) ctimer_set(&c, RPL_DAG_GRACE_PERIOD, create_dag_callback, NULL); } } +#if (UIP_CONF_MAX_ROUTES != 0) /*---------------------------------------------------------------------------*/ static void route_callback(int event, uip_ipaddr_t *route, uip_ipaddr_t *ipaddr, @@ -136,6 +139,7 @@ route_callback(int event, uip_ipaddr_t *route, uip_ipaddr_t *ipaddr, } } } +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ /*---------------------------------------------------------------------------*/ static uip_ipaddr_t * set_global_address(void) @@ -146,7 +150,7 @@ set_global_address(void) /* Assign a unique local address (RFC4193, http://tools.ietf.org/html/rfc4193). */ - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); @@ -171,7 +175,9 @@ rpl_dag_root_init(void) if(!initialized) { to_become_root = 0; set_global_address(); +#if (UIP_CONF_MAX_ROUTES != 0) uip_ds6_notification_add(&n, route_callback); +#endif /* (UIP_CONF_MAX_ROUTES != 0) */ initialized = 1; } } @@ -206,14 +212,16 @@ rpl_dag_root_init_dag_immediately(void) /* If there are routes in this dag, we remove them all as we are from now on the new dag root and the old routes are wrong */ - rpl_remove_routes(dag); + if(RPL_IS_STORING(dag->instance)) { + rpl_remove_routes(dag); + } if(dag->instance != NULL && dag->instance->def_route != NULL) { uip_ds6_defrt_rm(dag->instance->def_route); dag->instance->def_route = NULL; } - uip_ip6addr(&prefix, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &prefix, 64); PRINTF("rpl_dag_root_init_dag: created a new RPL dag\n"); return 0; diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 46f2936ef..4e9af23f7 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -44,6 +44,7 @@ */ #include "contiki.h" +#include "net/link-stats.h" #include "net/rpl/rpl-private.h" #include "net/ip/uip.h" #include "net/ipv6/uip-nd6.h" @@ -66,8 +67,8 @@ void RPL_CALLBACK_PARENT_SWITCH(rpl_parent_t *old, rpl_parent_t *new); #endif /* RPL_CALLBACK_PARENT_SWITCH */ /*---------------------------------------------------------------------------*/ -extern rpl_of_t RPL_OF; -static rpl_of_t * const objective_functions[] = {&RPL_OF}; +extern rpl_of_t rpl_of0, rpl_mrhof; +static rpl_of_t * const objective_functions[] = RPL_SUPPORTED_OFS; /*---------------------------------------------------------------------------*/ /* RPL definitions. */ @@ -88,25 +89,29 @@ rpl_instance_t *default_instance; /*---------------------------------------------------------------------------*/ void -rpl_print_neighbor_list() +rpl_print_neighbor_list(void) { if(default_instance != NULL && default_instance->current_dag != NULL && - default_instance->of != NULL && default_instance->of->calculate_rank != NULL) { + default_instance->of != NULL) { int curr_dio_interval = default_instance->dio_intcurrent; int curr_rank = default_instance->current_dag->rank; rpl_parent_t *p = nbr_table_head(rpl_parents); - clock_time_t now = clock_time(); + clock_time_t clock_now = clock_time(); - printf("RPL: rank %u dioint %u, %u nbr(s)\n", curr_rank, curr_dio_interval, uip_ds6_nbr_num()); + printf("RPL: MOP %u OCP %u rank %u dioint %u, nbr count %u\n", + default_instance->mop, default_instance->of->ocp, curr_rank, curr_dio_interval, uip_ds6_nbr_num()); while(p != NULL) { - uip_ds6_nbr_t *nbr = rpl_get_nbr(p); - printf("RPL: nbr %3u %5u, %5u => %5u %c%c (last tx %u min ago)\n", - nbr_table_get_lladdr(rpl_parents, p)->u8[7], - p->rank, nbr ? nbr->link_metric : 0, - default_instance->of->calculate_rank(p, 0), - default_instance->current_dag == p->dag ? 'd' : ' ', - p == default_instance->current_dag->preferred_parent ? '*' : ' ', - (unsigned)((now - p->last_tx_time) / (60 * CLOCK_SECOND))); + const struct link_stats *stats = rpl_get_parent_link_stats(p); + printf("RPL: nbr %3u %5u, %5u => %5u -- %2u %c%c (last tx %u min ago)\n", + rpl_get_parent_ipaddr(p)->u8[15], + p->rank, + rpl_get_parent_link_metric(p), + rpl_rank_via_parent(p), + stats != NULL ? stats->freshness : 0, + link_stats_is_fresh(stats) ? 'f' : ' ', + p == default_instance->current_dag->preferred_parent ? 'p' : ' ', + (unsigned)((clock_now - stats->last_tx_time) / (60 * CLOCK_SECOND)) + ); p = nbr_table_next(rpl_parents, p); } printf("RPL: end of list\n"); @@ -116,8 +121,7 @@ rpl_print_neighbor_list() uip_ds6_nbr_t * rpl_get_nbr(rpl_parent_t *parent) { - linkaddr_t *lladdr = NULL; - lladdr = nbr_table_get_lladdr(rpl_parents, parent); + const linkaddr_t *lladdr = rpl_get_parent_lladdr(parent); if(lladdr != NULL) { return nbr_table_get_from_lladdr(ds6_neighbors, lladdr); } else { @@ -151,30 +155,78 @@ rpl_get_parent_rank(uip_lladdr_t *addr) if(p != NULL) { return p->rank; } else { - return 0; + return INFINITE_RANK; } } /*---------------------------------------------------------------------------*/ uint16_t -rpl_get_parent_link_metric(const uip_lladdr_t *addr) +rpl_get_parent_link_metric(rpl_parent_t *p) { - uip_ds6_nbr_t *nbr; - nbr = nbr_table_get_from_lladdr(ds6_neighbors, (const linkaddr_t *)addr); - - if(nbr != NULL) { - return nbr->link_metric; - } else { - return 0; + if(p != NULL && p->dag != NULL) { + rpl_instance_t *instance = p->dag->instance; + if(instance != NULL && instance->of != NULL && instance->of->parent_link_metric != NULL) { + return instance->of->parent_link_metric(p); + } } + return 0xffff; +} +/*---------------------------------------------------------------------------*/ +rpl_rank_t +rpl_rank_via_parent(rpl_parent_t *p) +{ + if(p != NULL && p->dag != NULL) { + rpl_instance_t *instance = p->dag->instance; + if(instance != NULL && instance->of != NULL && instance->of->rank_via_parent != NULL) { + return instance->of->rank_via_parent(p); + } + } + return INFINITE_RANK; +} +/*---------------------------------------------------------------------------*/ +const linkaddr_t * +rpl_get_parent_lladdr(rpl_parent_t *p) +{ + return nbr_table_get_lladdr(rpl_parents, p); } /*---------------------------------------------------------------------------*/ uip_ipaddr_t * rpl_get_parent_ipaddr(rpl_parent_t *p) { - linkaddr_t *lladdr = nbr_table_get_lladdr(rpl_parents, p); + const linkaddr_t *lladdr = rpl_get_parent_lladdr(p); return uip_ds6_nbr_ipaddr_from_lladdr((uip_lladdr_t *)lladdr); } /*---------------------------------------------------------------------------*/ +const struct link_stats * +rpl_get_parent_link_stats(rpl_parent_t *p) +{ + const linkaddr_t *lladdr = rpl_get_parent_lladdr(p); + return link_stats_from_lladdr(lladdr); +} +/*---------------------------------------------------------------------------*/ +int +rpl_parent_is_fresh(rpl_parent_t *p) +{ + const struct link_stats *stats = rpl_get_parent_link_stats(p); + return link_stats_is_fresh(stats); +} +/*---------------------------------------------------------------------------*/ +int +rpl_parent_is_reachable(rpl_parent_t *p) { + if(p == NULL || p->dag == NULL || p->dag->instance == NULL || p->dag->instance->of == NULL) { + return 0; + } else { +#ifndef UIP_CONF_ND6_SEND_NA + uip_ds6_nbr_t *nbr = rpl_get_nbr(p); + /* Exclude links to a neighbor that is not reachable at a NUD level */ + if(nbr == NULL || nbr->state != NBR_REACHABLE) { + return 0; + } +#endif /* UIP_CONF_ND6_SEND_NA */ + /* If we don't have fresh link information, assume the parent is reachable. */ + return !rpl_parent_is_fresh(p) || p->dag->instance->of->parent_has_usable_link(p); + } +} +/*---------------------------------------------------------------------------*/ static void rpl_set_preferred_parent(rpl_dag_t *dag, rpl_parent_t *p) { @@ -340,7 +392,12 @@ rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id) dag->grounded = RPL_GROUNDED; dag->preference = RPL_PREFERENCE; instance->mop = RPL_MOP_DEFAULT; - instance->of = &RPL_OF; + instance->of = rpl_find_of(RPL_OF_OCP); + if(instance->of == NULL) { + PRINTF("RPL: OF with OCP %u not supported\n", RPL_OF_OCP); + return NULL; + } + rpl_set_preferred_parent(dag, NULL); memcpy(&dag->dag_id, dag_id, sizeof(dag->dag_id)); @@ -361,7 +418,9 @@ rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id) if(instance->current_dag != dag && instance->current_dag != NULL) { /* Remove routes installed by DAOs. */ - rpl_remove_routes(instance->current_dag); + if(RPL_IS_STORING(instance)) { + rpl_remove_routes(instance->current_dag); + } instance->current_dag->joined = 0; } @@ -610,7 +669,9 @@ rpl_free_dag(rpl_dag_t *dag) dag->joined = 0; /* Remove routes installed by DAOs. */ - rpl_remove_routes(dag); + if(RPL_IS_STORING(dag->instance)) { + rpl_remove_routes(dag); + } /* Remove autoconfigured address */ if((dag->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS)) { @@ -634,25 +695,18 @@ rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr) PRINT6ADDR(addr); PRINTF("\n"); if(lladdr != NULL) { - /* Add parent in rpl_parents */ - p = nbr_table_add_lladdr(rpl_parents, (linkaddr_t *)lladdr); + /* Add parent in rpl_parents - again this is due to DIO */ + p = nbr_table_add_lladdr(rpl_parents, (linkaddr_t *)lladdr, + NBR_TABLE_REASON_RPL_DIO, dio); if(p == NULL) { PRINTF("RPL: rpl_add_parent p NULL\n"); } else { - uip_ds6_nbr_t *nbr; - nbr = rpl_get_nbr(p); - p->dag = dag; p->rank = dio->rank; p->dtsn = dio->dtsn; - - /* Check whether we have a neighbor that has not gotten a link metric yet */ - if(nbr != NULL && nbr->link_metric == 0) { - nbr->link_metric = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR; - } -#if RPL_DAG_MC != RPL_DAG_MC_NONE +#if RPL_WITH_MC memcpy(&p->mc, &dio->mc, sizeof(p->mc)); -#endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */ +#endif /* RPL_WITH_MC */ } } @@ -737,7 +791,9 @@ rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p) if(instance->current_dag != best_dag) { /* Remove routes installed by DAOs. */ - rpl_remove_routes(instance->current_dag); + if(RPL_IS_STORING(instance)) { + rpl_remove_routes(instance->current_dag); + } PRINTF("RPL: New preferred DAG: "); PRINT6ADDR(&best_dag->dag_id); @@ -756,13 +812,17 @@ rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p) instance->of->update_metric_container(instance); /* Update the DAG rank. */ - best_dag->rank = instance->of->calculate_rank(best_dag->preferred_parent, 0); + best_dag->rank = rpl_rank_via_parent(best_dag->preferred_parent); if(last_parent == NULL || best_dag->rank < best_dag->min_rank) { + /* This is a slight departure from RFC6550: if we had no preferred parent before, + * reset min_rank. This helps recovering from temporary bad link conditions. */ best_dag->min_rank = best_dag->rank; - } else if(!acceptable_rank(best_dag, best_dag->rank)) { + } + + if(!acceptable_rank(best_dag, best_dag->rank)) { PRINTF("RPL: New rank unacceptable!\n"); rpl_set_preferred_parent(instance->current_dag, NULL); - if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES && last_parent != NULL) { + if(RPL_IS_STORING(instance) && last_parent != NULL) { /* Send a No-Path DAO to the removed preferred parent. */ dao_output(last_parent, RPL_ZERO_LIFETIME); } @@ -774,15 +834,13 @@ rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p) PRINTF("RPL: Changed preferred parent, rank changed from %u to %u\n", (unsigned)old_rank, best_dag->rank); RPL_STAT(rpl_stats.parent_switch++); - if(instance->mop != RPL_MOP_NO_DOWNWARD_ROUTES) { - if(last_parent != NULL) { - /* Send a No-Path DAO to the removed preferred parent. */ - dao_output(last_parent, RPL_ZERO_LIFETIME); - } - /* The DAO parent set changed - schedule a DAO transmission. */ - RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); - rpl_schedule_dao(instance); + if(RPL_IS_STORING(instance) && last_parent != NULL) { + /* Send a No-Path DAO to the removed preferred parent. */ + dao_output(last_parent, RPL_ZERO_LIFETIME); } + /* The DAO parent set changed - schedule a DAO transmission. */ + RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); + rpl_schedule_dao(instance); rpl_reset_dio_timer(instance); #if DEBUG rpl_print_neighbor_list(); @@ -795,22 +853,42 @@ rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p) } /*---------------------------------------------------------------------------*/ static rpl_parent_t * -best_parent(rpl_dag_t *dag) +best_parent(rpl_dag_t *dag, int fresh_only) { - rpl_parent_t *p, *best; + rpl_parent_t *p; + rpl_of_t *of; + rpl_parent_t *best = NULL; - best = NULL; + if(dag == NULL || dag->instance == NULL || dag->instance->of == NULL) { + return NULL; + } - p = nbr_table_head(rpl_parents); - while(p != NULL) { + of = dag->instance->of; + /* Search for the best parent according to the OF */ + for(p = nbr_table_head(rpl_parents); p != NULL; p = nbr_table_next(rpl_parents, p)) { + + /* Exclude parents from other DAGs or announcing an infinite rank */ if(p->dag != dag || p->rank == INFINITE_RANK) { - /* ignore this neighbor */ - } else if(best == NULL) { - best = p; - } else { - best = dag->instance->of->best_parent(best, p); + continue; } - p = nbr_table_next(rpl_parents, p); + + if(fresh_only && !rpl_parent_is_fresh(p)) { + /* Filter out non-fresh parents if fresh_only is set */ + continue; + } + +#ifndef UIP_CONF_ND6_SEND_NA + { + uip_ds6_nbr_t *nbr = rpl_get_nbr(p); + /* Exclude links to a neighbor that is not reachable at a NUD level */ + if(nbr == NULL || nbr->state != NBR_REACHABLE) { + continue; + } + } +#endif /* UIP_CONF_ND6_SEND_NA */ + + /* Now we have an acceptable parent, check if it is the new best */ + best = of->best_parent(best, p); } return best; @@ -819,16 +897,37 @@ best_parent(rpl_dag_t *dag) rpl_parent_t * rpl_select_parent(rpl_dag_t *dag) { - rpl_parent_t *best = best_parent(dag); + /* Look for best parent (regardless of freshness) */ + rpl_parent_t *best = best_parent(dag, 0); if(best != NULL) { - rpl_set_preferred_parent(dag, best); - dag->rank = dag->instance->of->calculate_rank(dag->preferred_parent, 0); +#if RPL_WITH_PROBING + if(rpl_parent_is_fresh(best)) { + rpl_set_preferred_parent(dag, best); + } else { + /* The best is not fresh. Look for the best fresh now. */ + rpl_parent_t *best_fresh = best_parent(dag, 1); + if(best_fresh == NULL) { + /* No fresh parent around, use best (non-fresh) */ + rpl_set_preferred_parent(dag, best); + } else { + /* Use best fresh */ + rpl_set_preferred_parent(dag, best_fresh); + } + /* Probe the best parent shortly in order to get a fresh estimate */ + dag->instance->urgent_probing_target = best; + rpl_schedule_probing(dag->instance); +#else /* RPL_WITH_PROBING */ + rpl_set_preferred_parent(dag, best); + dag->rank = rpl_rank_via_parent(dag->preferred_parent); +#endif /* RPL_WITH_PROBING */ + } } else { - dag->rank = INFINITE_RANK; + rpl_set_preferred_parent(dag, NULL); } - return best; + dag->rank = rpl_rank_via_parent(dag->preferred_parent); + return dag->preferred_parent; } /*---------------------------------------------------------------------------*/ void @@ -859,9 +958,11 @@ rpl_nullify_parent(rpl_parent_t *parent) uip_ds6_defrt_rm(dag->instance->def_route); dag->instance->def_route = NULL; } - /* Send No-Path DAO only to preferred parent, if any */ + /* Send No-Path DAO only when nullifying preferred parent */ if(parent == dag->preferred_parent) { - dao_output(parent, RPL_ZERO_LIFETIME); + if(RPL_IS_STORING(dag->instance)) { + dao_output(parent, RPL_ZERO_LIFETIME); + } rpl_set_preferred_parent(dag, NULL); } } @@ -887,8 +988,10 @@ rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent) dag_src->instance->def_route = NULL; } } else if(dag_src->joined) { - /* Remove uIPv6 routes that have this parent as the next hop. */ - rpl_remove_routes_by_nexthop(rpl_get_parent_ipaddr(parent), dag_src); + if(RPL_IS_STORING(dag_src->instance)) { + /* Remove uIPv6 routes that have this parent as the next hop. */ + rpl_remove_routes_by_nexthop(rpl_get_parent_ipaddr(parent), dag_src); + } } PRINTF("RPL: Moving parent "); @@ -898,6 +1001,37 @@ rpl_move_parent(rpl_dag_t *dag_src, rpl_dag_t *dag_dst, rpl_parent_t *parent) parent->dag = dag_dst; } /*---------------------------------------------------------------------------*/ +int +rpl_has_downward_route(void) +{ + int i; + for(i = 0; i < RPL_MAX_INSTANCES; ++i) { + if(instance_table[i].used && instance_table[i].has_downward_route) { + return 1; + } + } + return 0; +} +/*---------------------------------------------------------------------------*/ +rpl_dag_t * +rpl_get_dag(const uip_ipaddr_t *addr) +{ + int i, j; + + for(i = 0; i < RPL_MAX_INSTANCES; ++i) { + if(instance_table[i].used) { + for(j = 0; j < RPL_MAX_DAG_PER_INSTANCE; ++j) { + if(instance_table[i].dag_table[j].joined + && uip_ipaddr_prefixcmp(&instance_table[i].dag_table[j].dag_id, addr, + instance_table[i].dag_table[j].prefix_info.length)) { + return &instance_table[i].dag_table[j]; + } + } + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ rpl_dag_t * rpl_get_any_dag(void) { @@ -948,6 +1082,12 @@ rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio) rpl_parent_t *p; rpl_of_t *of; + if((!RPL_WITH_NON_STORING && dio->mop == RPL_MOP_NON_STORING) + || (!RPL_WITH_STORING && (dio->mop == RPL_MOP_STORING_NO_MULTICAST + || dio->mop == RPL_MOP_STORING_MULTICAST))) { + PRINTF("RPL: DIO advertising a non-supported MOP %u\n", dio->mop); + } + /* Determine the objective function by using the objective code point of the DIO. */ of = rpl_find_of(dio->ocp); @@ -990,6 +1130,10 @@ rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio) instance->of = of; instance->mop = dio->mop; + instance->mc.type = dio->mc.type; + instance->mc.flags = dio->mc.flags; + instance->mc.aggr = dio->mc.aggr; + instance->mc.prec = dio->mc.prec; instance->current_dag = dag; instance->dtsn_out = RPL_LOLLIPOP_INIT; @@ -1009,7 +1153,7 @@ rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio) rpl_set_preferred_parent(dag, p); instance->of->update_metric_container(instance); - dag->rank = instance->of->calculate_rank(p, 0); + dag->rank = rpl_rank_via_parent(p); /* So far this is the lowest rank we are aware of. */ dag->min_rank = dag->rank; @@ -1032,6 +1176,8 @@ rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio) } else { PRINTF("RPL: The DIO does not meet the prerequisites for sending a DAO\n"); } + + instance->of->reset(dag); } #if RPL_MAX_DAG_PER_INSTANCE > 1 @@ -1102,7 +1248,7 @@ rpl_add_dag(uip_ipaddr_t *from, rpl_dio_t *dio) memcpy(&dag->prefix_info, &dio->prefix_info, sizeof(rpl_prefix_t)); rpl_set_preferred_parent(dag, p); - dag->rank = instance->of->calculate_rank(p, 0); + dag->rank = rpl_rank_via_parent(p); dag->min_rank = dag->rank; /* So far this is the lowest rank we know of. */ PRINTF("RPL: Joined DAG with instance ID %u, rank %hu, DAG ID ", @@ -1144,7 +1290,7 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) PRINTF("RPL: Failed to add a parent during the global repair\n"); dag->rank = INFINITE_RANK; } else { - dag->rank = dag->instance->of->calculate_rank(p, 0); + dag->rank = rpl_rank_via_parent(p); dag->min_rank = dag->rank; PRINTF("RPL: rpl_process_parent_event global repair\n"); rpl_process_parent_event(dag->instance, p); @@ -1155,6 +1301,7 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) RPL_STAT(rpl_stats.global_repairs++); } + /*---------------------------------------------------------------------------*/ void rpl_local_repair(rpl_instance_t *instance) @@ -1173,7 +1320,12 @@ rpl_local_repair(rpl_instance_t *instance) } } + /* no downward route anymore */ + instance->has_downward_route = 0; + rpl_reset_dio_timer(instance); + /* Request refresh of DAO registrations next DIO */ + RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); RPL_STAT(rpl_stats.local_repairs++); } @@ -1205,6 +1357,7 @@ int rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p) { int return_value; + rpl_parent_t *last_parent = instance->current_dag->preferred_parent; #if DEBUG rpl_rank_t old_rank; @@ -1213,10 +1366,20 @@ rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p) return_value = 1; + if(RPL_IS_STORING(instance) + && uip_ds6_route_is_nexthop(rpl_get_parent_ipaddr(p)) + && !rpl_parent_is_reachable(p) && instance->mop > RPL_MOP_NON_STORING) { + PRINTF("RPL: Unacceptable link %u, removing routes via: ", rpl_get_parent_link_metric(p)); + PRINT6ADDR(rpl_get_parent_ipaddr(p)); + PRINTF("\n"); + rpl_remove_routes_by_nexthop(rpl_get_parent_ipaddr(p), p->dag); + } + if(!acceptable_rank(p->dag, p->rank)) { /* The candidate parent is no longer valid: the rank increase resulting from the choice of it as a parent would be too high. */ - PRINTF("RPL: Unacceptable rank %u\n", (unsigned)p->rank); + PRINTF("RPL: Unacceptable rank %u (Current min %u, MaxRankInc %u)\n", (unsigned)p->rank, + p->dag->min_rank, p->dag->instance->max_rankinc); rpl_nullify_parent(p); if(p != instance->current_dag->preferred_parent) { return 0; @@ -1226,10 +1389,12 @@ rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p) } if(rpl_select_dag(instance, p) == NULL) { - /* No suitable parent; trigger a local repair. */ - PRINTF("RPL: No parents found in any DAG\n"); - rpl_local_repair(instance); - return 0; + if(last_parent != NULL) { + /* No suitable parent anymore; trigger a local repair. */ + PRINTF("RPL: No parents found in any DAG\n"); + rpl_local_repair(instance); + return 0; + } } #if DEBUG @@ -1250,6 +1415,19 @@ rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p) return return_value; } /*---------------------------------------------------------------------------*/ +static int +add_nbr_from_dio(uip_ipaddr_t *from, rpl_dio_t *dio) +{ + /* add this to the neighbor cache if not already there */ + if(rpl_icmp6_update_nbr_table(from, NBR_TABLE_REASON_RPL_DIO, dio) == NULL) { + PRINTF("RPL: Out of memory, dropping DIO from "); + PRINT6ADDR(from); + PRINTF("\n"); + return 0; + } + return 1; +} +/*---------------------------------------------------------------------------*/ void rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) { @@ -1257,7 +1435,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) rpl_dag_t *dag, *previous_dag; rpl_parent_t *p; -#if RPL_CONF_MULTICAST +#if RPL_WITH_MULTICAST /* If the root is advertising MOP 2 but we support MOP 3 we can still join * In that scenario, we suppress DAOs for multicast targets */ if(dio->mop < RPL_MOP_STORING_NO_MULTICAST) { @@ -1282,7 +1460,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) PRINTF("RPL: Global repair\n"); if(dio->prefix_info.length != 0) { if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) { - PRINTF("RPL : Prefix announced in DIO\n"); + PRINTF("RPL: Prefix announced in DIO\n"); rpl_set_prefix(dag, &dio->prefix_info.prefix, dio->prefix_info.length); } } @@ -1303,7 +1481,11 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) if(instance == NULL) { PRINTF("RPL: New instance detected (ID=%u): Joining...\n", dio->instance_id); - rpl_join_instance(from, dio); + if(add_nbr_from_dio(from, dio)) { + rpl_join_instance(from, dio); + } else { + PRINTF("RPL: Not joining since could not add parent\n"); + } return; } @@ -1315,6 +1497,10 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) if(dag == NULL) { #if RPL_MAX_DAG_PER_INSTANCE > 1 PRINTF("RPL: Adding new DAG to known instance.\n"); + if(!add_nbr_from_dio(from, dio)) { + PRINTF("RPL: Could not add new DAG, could not add parent\n"); + return; + } dag = rpl_add_dag(from, dio); if(dag == NULL) { PRINTF("RPL: Failed to add DAG.\n"); @@ -1331,18 +1517,21 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) PRINTF("RPL: Ignoring DIO with too low rank: %u\n", (unsigned)dio->rank); return; - } else if(dio->rank == INFINITE_RANK && dag->joined) { - rpl_reset_dio_timer(instance); } /* Prefix Information Option treated to add new prefix */ if(dio->prefix_info.length != 0) { if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) { - PRINTF("RPL : Prefix announced in DIO\n"); + PRINTF("RPL: Prefix announced in DIO\n"); rpl_set_prefix(dag, &dio->prefix_info.prefix, dio->prefix_info.length); } } + if(!add_nbr_from_dio(from, dio)) { + PRINTF("RPL: Could not add parent based on DIO\n"); + return; + } + if(dag->rank == ROOT_RANK(instance)) { if(dio->rank != INFINITE_RANK) { instance->dio_counter++; @@ -1394,6 +1583,11 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) } p->rank = dio->rank; + if(dio->rank == INFINITE_RANK && p == dag->preferred_parent) { + /* Our preferred parent advertised an infinite rank, reset DIO timer */ + rpl_reset_dio_timer(instance); + } + /* Parent info has been updated, trigger rank recalculation */ p->flags |= RPL_PARENT_FLAG_UPDATED; @@ -1401,14 +1595,14 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) PRINT6ADDR(&instance->current_dag->dag_id); PRINTF(", rank %u, min_rank %u, ", instance->current_dag->rank, instance->current_dag->min_rank); - PRINTF("parent rank %u, parent etx %u, link metric %u, instance etx %u\n", - p->rank, -1/*p->mc.obj.etx*/, rpl_get_nbr(p)->link_metric, instance->mc.obj.etx); + PRINTF("parent rank %u, link metric %u\n", + p->rank, rpl_get_parent_link_metric(p)); /* We have allocated a candidate parent; process the DIO further. */ -#if RPL_DAG_MC != RPL_DAG_MC_NONE +#if RPL_WITH_MC memcpy(&p->mc, &dio->mc, sizeof(p->mc)); -#endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */ +#endif /* RPL_WITH_MC */ if(rpl_process_parent_event(instance, p) == 0) { PRINTF("RPL: The candidate parent is rejected\n"); return; diff --git a/core/net/rpl/rpl-ext-header.c b/core/net/rpl/rpl-ext-header.c index a2392c124..b6d17d4a9 100644 --- a/core/net/rpl/rpl-ext-header.c +++ b/core/net/rpl/rpl-ext-header.c @@ -48,6 +48,7 @@ #include "net/ip/tcpip.h" #include "net/ipv6/uip-ds6.h" #include "net/rpl/rpl-private.h" +#include "net/rpl/rpl-ns.h" #include "net/packetbuf.h" #define DEBUG DEBUG_NONE @@ -61,12 +62,14 @@ #define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len]) #define UIP_HBHO_BUF ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len]) #define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_HOP_BY_HOP_LEN]) +#define UIP_RH_BUF ((struct uip_routing_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#define UIP_RPL_SRH_BUF ((struct uip_rpl_srh_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_RH_LEN]) #define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) #define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) #define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) /*---------------------------------------------------------------------------*/ int -rpl_verify_header(int uip_ext_opt_offset) +rpl_verify_hbh_header(int uip_ext_opt_offset) { rpl_instance_t *instance; int down; @@ -75,7 +78,7 @@ rpl_verify_header(int uip_ext_opt_offset) uip_ds6_route_t *route; rpl_parent_t *sender = NULL; - if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_LEN - 8) { + if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)) { PRINTF("RPL: Hop-by-hop extension header has wrong size\n"); return 1; } @@ -100,12 +103,14 @@ rpl_verify_header(int uip_ext_opt_offset) if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_FWD_ERR) { PRINTF("RPL: Forward error!\n"); /* We should try to repair it by removing the neighbor that caused - the packet to be forwareded in the first place. We drop any - routes that go through the neighbor that sent the packet to - us. */ - route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); - if(route != NULL) { - uip_ds6_route_rm(route); + the packet to be forwareded in the first place. We drop any + routes that go through the neighbor that sent the packet to + us. */ + if(RPL_IS_STORING(instance)) { + route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr); + if(route != NULL) { + uip_ds6_route_rm(route); + } } RPL_STAT(rpl_stats.forward_errors++); /* Trigger DAO retransmission */ @@ -125,23 +130,28 @@ rpl_verify_header(int uip_ext_opt_offset) } sender_rank = UIP_HTONS(UIP_EXT_HDR_OPT_RPL_BUF->senderrank); - sender_closer = sender_rank < instance->current_dag->rank; - - PRINTF("RPL: Packet going %s, sender closer %d (%d < %d)\n", down == 1 ? "down" : "up", - sender_closer, - sender_rank, - instance->current_dag->rank - ); - sender = nbr_table_get_from_lladdr(rpl_parents, packetbuf_addr(PACKETBUF_ADDR_SENDER)); if(sender != NULL && (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR)) { /* A rank error was signalled, attempt to repair it by updating * the sender's rank from ext header */ sender->rank = sender_rank; - rpl_select_dag(instance, sender); + if(RPL_IS_NON_STORING(instance)) { + /* Select DAG and preferred parent only in non-storing mode. In storing mode, + * a parent switch would result in an immediate No-path DAO transmission, dropping + * current incoming packet. */ + rpl_select_dag(instance, sender); + } } + sender_closer = sender_rank < instance->current_dag->rank; + + PRINTF("RPL: Packet going %s, sender closer %d (%d < %d)\n", down == 1 ? "down" : "up", + sender_closer, + sender_rank, + instance->current_dag->rank + ); + if((down && !sender_closer) || (!down && sender_closer)) { PRINTF("RPL: Loop detected - senderrank: %d my-rank: %d sender_closer: %d\n", sender_rank, instance->current_dag->rank, @@ -166,35 +176,308 @@ rpl_verify_header(int uip_ext_opt_offset) } PRINTF("RPL: Rank OK\n"); - return 0; } /*---------------------------------------------------------------------------*/ -static void -set_rpl_opt(unsigned uip_ext_opt_offset) +#if RPL_WITH_NON_STORING +int +rpl_srh_get_next_hop(uip_ipaddr_t *ipaddr) { - uint8_t temp_len; + uint8_t *uip_next_hdr; + int last_uip_ext_len = uip_ext_len; + rpl_dag_t *dag; + rpl_ns_node_t *dest_node; + rpl_ns_node_t *root_node; - memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF, uip_len - UIP_IPH_LEN); - memset(UIP_HBHO_BUF, 0, RPL_HOP_BY_HOP_LEN); - UIP_HBHO_BUF->next = UIP_IP_BUF->proto; - UIP_IP_BUF->proto = UIP_PROTO_HBHO; - UIP_HBHO_BUF->len = RPL_HOP_BY_HOP_LEN - 8; - UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL; - UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN; - UIP_EXT_HDR_OPT_RPL_BUF->flags = 0; - UIP_EXT_HDR_OPT_RPL_BUF->instance = 0; - UIP_EXT_HDR_OPT_RPL_BUF->senderrank = 0; - uip_len += RPL_HOP_BY_HOP_LEN; - temp_len = UIP_IP_BUF->len[1]; - UIP_IP_BUF->len[1] += UIP_HBHO_BUF->len + 8; - if(UIP_IP_BUF->len[1] < temp_len) { - UIP_IP_BUF->len[0]++; + uip_ext_len = 0; + uip_next_hdr = &UIP_IP_BUF->proto; + + /* Look for routing header */ + while(uip_next_hdr != NULL && *uip_next_hdr != UIP_PROTO_ROUTING) { + switch(*uip_next_hdr) { + case UIP_PROTO_TCP: + case UIP_PROTO_UDP: + case UIP_PROTO_ICMP6: + case UIP_PROTO_NONE: + uip_next_hdr = NULL; + break; + case UIP_PROTO_HBHO: + case UIP_PROTO_DESTO: + case UIP_PROTO_FRAG: + /* Move to next header */ + if(uip_next_hdr != &UIP_IP_BUF->proto) { + uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; + } + uip_next_hdr = &UIP_EXT_BUF->next; + break; + default: + break; + } } + + dag = rpl_get_dag(&UIP_IP_BUF->destipaddr); + root_node = rpl_ns_get_node(dag, &dag->dag_id); + dest_node = rpl_ns_get_node(dag, &UIP_IP_BUF->destipaddr); + + if((uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING + && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) || + (dest_node != NULL && root_node != NULL && + dest_node->parent == root_node)) { + /* Routing header found or the packet destined for a direct child of the root. + * The next hop should be already copied as the IPv6 destination + * address, via rpl_process_srh_header. We turn this address into a link-local to enable + * forwarding to next hop */ + uip_ipaddr_copy(ipaddr, &UIP_IP_BUF->destipaddr); + uip_create_linklocal_prefix(ipaddr); + uip_ext_len = last_uip_ext_len; + return 1; + } + + uip_ext_len = last_uip_ext_len; + return 0; } /*---------------------------------------------------------------------------*/ int -rpl_update_header_empty(void) +rpl_process_srh_header(void) +{ + uint8_t *uip_next_hdr; + int last_uip_ext_len = uip_ext_len; + + uip_ext_len = 0; + uip_next_hdr = &UIP_IP_BUF->proto; + + /* Look for routing header */ + while(uip_next_hdr != NULL && *uip_next_hdr != UIP_PROTO_ROUTING) { + switch(*uip_next_hdr) { + case UIP_PROTO_TCP: + case UIP_PROTO_UDP: + case UIP_PROTO_ICMP6: + case UIP_PROTO_NONE: + uip_next_hdr = NULL; + break; + case UIP_PROTO_HBHO: + case UIP_PROTO_DESTO: + case UIP_PROTO_FRAG: + /* Move to next header */ + if(uip_next_hdr != &UIP_IP_BUF->proto) { + uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; + } + uip_next_hdr = &UIP_EXT_BUF->next; + break; + default: + break; + } + } + + if(uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING + && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) { + /* SRH found, now look for next hop */ + uint8_t cmpri, cmpre; + uint8_t ext_len; + uint8_t padding; + uint8_t path_len; + uint8_t segments_left; + uip_ipaddr_t current_dest_addr; + + segments_left = UIP_RH_BUF->seg_left; + ext_len = (UIP_RH_BUF->len * 8) + 8; + cmpri = UIP_RPL_SRH_BUF->cmpr >> 4; + cmpre = UIP_RPL_SRH_BUF->cmpr & 0x0f; + padding = UIP_RPL_SRH_BUF->pad >> 4; + path_len = ((ext_len - padding - RPL_RH_LEN - RPL_SRH_LEN - (16 - cmpre)) / (16 - cmpri)) + 1; + (void)path_len; + + PRINTF("RPL: read SRH, path len %u, segments left %u, Cmpri %u, Cmpre %u, ext len %u (padding %u)\n", + path_len, segments_left, cmpri, cmpre, ext_len, padding); + + if(segments_left == 0) { + /* We are the final destination, do nothing */ + } else { + uint8_t i = path_len - segments_left; /* The index of the next address to be visited */ + uint8_t *addr_ptr = ((uint8_t *)UIP_RH_BUF) + RPL_RH_LEN + RPL_SRH_LEN + (i * (16 - cmpri)); + uint8_t cmpr = segments_left == 1 ? cmpre : cmpri; + + /* As per RFC6554: swap the IPv6 destination address and address[i] */ + + /* First, copy the current IPv6 destination address */ + uip_ipaddr_copy(¤t_dest_addr, &UIP_IP_BUF->destipaddr); + /* Second, update the IPv6 destination address with addresses[i] */ + memcpy(((uint8_t *)&UIP_IP_BUF->destipaddr) + cmpr, addr_ptr, 16 - cmpr); + /* Third, write current_dest_addr to addresses[i] */ + memcpy(addr_ptr, ((uint8_t *)¤t_dest_addr) + cmpr, 16 - cmpr); + + /* Update segments left field */ + UIP_RH_BUF->seg_left--; + + PRINTF("RPL: SRH next hop "); + PRINT6ADDR(&UIP_IP_BUF->destipaddr); + PRINTF("\n"); + } + uip_ext_len = last_uip_ext_len; + return 1; + } + + uip_ext_len = last_uip_ext_len; + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +count_matching_bytes(const void *p1, const void *p2, size_t n) +{ + int i = 0; + for(i = 0; i < n; i++) { + if(((uint8_t *)p1)[i] != ((uint8_t *)p2)[i]) { + return i; + } + } + return n; +} +/*---------------------------------------------------------------------------*/ +static int +insert_srh_header(void) +{ + /* Implementation of RFC6554 */ + uint8_t temp_len; + uint8_t path_len; + uint8_t ext_len; + uint8_t cmpri, cmpre; /* ComprI and ComprE fields of the RPL Source Routing Header */ + uint8_t *hop_ptr; + uint8_t padding; + rpl_ns_node_t *dest_node; + rpl_ns_node_t *root_node; + rpl_ns_node_t *node; + rpl_dag_t *dag; + uip_ipaddr_t node_addr; + + PRINTF("RPL: SRH creating source routing header with destination "); + PRINT6ADDR(&UIP_IP_BUF->destipaddr); + PRINTF(" \n"); + + /* Construct source route. We do not do this recursively to keep the runtime stack usage constant. */ + + /* Get link of the destination and root */ + dag = rpl_get_dag(&UIP_IP_BUF->destipaddr); + + if(dag == NULL) { + PRINTF("RPL: SRH DAG not found\n"); + return 0; + } + + dest_node = rpl_ns_get_node(dag, &UIP_IP_BUF->destipaddr); + if(dest_node == NULL) { + /* The destination is not found, skip SRH insertion */ + return 1; + } + + root_node = rpl_ns_get_node(dag, &dag->dag_id); + if(root_node == NULL) { + PRINTF("RPL: SRH root node not found\n"); + return 0; + } + + if(!rpl_ns_is_node_reachable(dag, &UIP_IP_BUF->destipaddr)) { + PRINTF("RPL: SRH no path found to destination\n"); + return 0; + } + + /* Compute path length and compression factors (we use cmpri == cmpre) */ + path_len = 0; + node = dest_node->parent; + /* For simplicity, we use cmpri = cmpre */ + cmpri = 15; + cmpre = 15; + + if(node == root_node) { + PRINTF("RPL: SRH no need to insert SRH\n"); + return 0; + } + + while(node != NULL && node != root_node) { + + rpl_ns_get_node_global_addr(&node_addr, node); + + /* How many bytes in common between all nodes in the path? */ + cmpri = MIN(cmpri, count_matching_bytes(&node_addr, &UIP_IP_BUF->destipaddr, 16)); + cmpre = cmpri; + + PRINTF("RPL: SRH Hop "); + PRINT6ADDR(&node_addr); + PRINTF("\n"); + node = node->parent; + path_len++; + } + + /* Extension header length: fixed headers + (n-1) * (16-ComprI) + (16-ComprE)*/ + ext_len = RPL_RH_LEN + RPL_SRH_LEN + + (path_len - 1) * (16 - cmpre) + + (16 - cmpri); + + padding = ext_len % 8 == 0 ? 0 : (8 - (ext_len % 8)); + ext_len += padding; + + PRINTF("RPL: SRH Path len: %u, ComprI %u, ComprE %u, ext len %u (padding %u)\n", + path_len, cmpri, cmpre, ext_len, padding); + + /* Check if there is enough space to store the extension header */ + if(uip_len + ext_len > UIP_BUFSIZE) { + PRINTF("RPL: Packet too long: impossible to add source routing header (%u bytes)\n", ext_len); + return 1; + } + + /* Move existing ext headers and payload uip_ext_len further */ + memmove(uip_buf + uip_l2_l3_hdr_len + ext_len, + uip_buf + uip_l2_l3_hdr_len, uip_len - UIP_IPH_LEN); + memset(uip_buf + uip_l2_l3_hdr_len, 0, ext_len); + + /* Insert source routing header */ + UIP_RH_BUF->next = UIP_IP_BUF->proto; + UIP_IP_BUF->proto = UIP_PROTO_ROUTING; + + /* Initialize IPv6 Routing Header */ + UIP_RH_BUF->len = (ext_len - 8) / 8; + UIP_RH_BUF->routing_type = RPL_RH_TYPE_SRH; + UIP_RH_BUF->seg_left = path_len; + + /* Initialize RPL Source Routing Header */ + UIP_RPL_SRH_BUF->cmpr = (cmpri << 4) + cmpre; + UIP_RPL_SRH_BUF->pad = padding << 4; + + /* Initialize addresses field (the actual source route). + * From last to first. */ + node = dest_node; + hop_ptr = ((uint8_t *)UIP_RH_BUF) + ext_len - padding; /* Pointer where to write the next hop compressed address */ + + while(node != NULL && node->parent != root_node) { + rpl_ns_get_node_global_addr(&node_addr, node); + + hop_ptr -= (16 - cmpri); + memcpy(hop_ptr, ((uint8_t*)&node_addr) + cmpri, 16 - cmpri); + + node = node->parent; + } + + /* The next hop (i.e. node whose parent is the root) is placed as the current IPv6 destination */ + rpl_ns_get_node_global_addr(&node_addr, node); + uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &node_addr); + + /* In-place update of IPv6 length field */ + temp_len = UIP_IP_BUF->len[1]; + UIP_IP_BUF->len[1] += ext_len; + if(UIP_IP_BUF->len[1] < temp_len) { + UIP_IP_BUF->len[0]++; + } + + uip_ext_len += ext_len; + uip_len += ext_len; + + return 1; +} +#else /* RPL_WITH_NON_STORING */ +int insert_srh_header(void); +#endif /* RPL_WITH_NON_STORING */ +/*---------------------------------------------------------------------------*/ +static int +update_hbh_header(void) { rpl_instance_t *instance; int uip_ext_opt_offset; @@ -209,39 +492,30 @@ rpl_update_header_empty(void) switch(UIP_IP_BUF->proto) { case UIP_PROTO_HBHO: - if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_LEN - 8) { + if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)) { PRINTF("RPL: Hop-by-hop extension header has wrong size\n"); uip_ext_len = last_uip_ext_len; - return 0; + return 1; } if(UIP_EXT_HDR_OPT_RPL_BUF->opt_type != UIP_EXT_HDR_OPT_RPL) { PRINTF("RPL: Non RPL Hop-by-hop option support not implemented\n"); uip_ext_len = last_uip_ext_len; - return 0; + return 1; } if(UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) { PRINTF("RPL: RPL Hop-by-hop option has wrong length\n"); uip_ext_len = last_uip_ext_len; - return 0; + return 1; } instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance); if(instance == NULL || !instance->used || !instance->current_dag->joined) { PRINTF("RPL: Unable to add hop-by-hop extension header: incorrect instance\n"); - return 0; + return 1; } break; default: -#if RPL_INSERT_HBH_OPTION - PRINTF("RPL: No hop-by-hop option found, creating it\n"); - if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_BUFSIZE) { - PRINTF("RPL: Packet too long: impossible to add hop-by-hop option\n"); - uip_ext_len = last_uip_ext_len; - return 0; - } - set_rpl_opt(uip_ext_opt_offset); - uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN; -#endif - return 0; + PRINTF("RPL: No hop-by-hop option found\n"); + return 1; } switch(UIP_EXT_HDR_OPT_BUF->type) { @@ -249,51 +523,98 @@ rpl_update_header_empty(void) PRINTF("RPL: Updating RPL option\n"); UIP_EXT_HDR_OPT_RPL_BUF->senderrank = UIP_HTONS(instance->current_dag->rank); - /* Check the direction of the down flag, as per Section 11.2.2.3, - which states that if a packet is going down it should in - general not go back up again. If this happens, a - RPL_HDR_OPT_FWD_ERR should be flagged. */ - if((UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN)) { - if(uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr) == NULL) { - UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_FWD_ERR; - PRINTF("RPL forwarding error\n"); - /* We should send back the packet to the originating parent, - but it is not feasible yet, so we send a No-Path DAO instead */ - PRINTF("RPL generate No-Path DAO\n"); - parent = rpl_get_parent((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); - if(parent != NULL) { - dao_output_target(parent, &UIP_IP_BUF->destipaddr, RPL_ZERO_LIFETIME); + if(RPL_IS_STORING(instance)) { /* In non-storing mode, downwards traffic does not have the HBH option */ + /* Check the direction of the down flag, as per Section 11.2.2.3, + which states that if a packet is going down it should in + general not go back up again. If this happens, a + RPL_HDR_OPT_FWD_ERR should be flagged. */ + if((UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN)) { + if(uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr) == NULL) { + UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_FWD_ERR; + PRINTF("RPL forwarding error\n"); + /* We should send back the packet to the originating parent, + but it is not feasible yet, so we send a No-Path DAO instead */ + PRINTF("RPL generate No-Path DAO\n"); + parent = rpl_get_parent((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); + if(parent != NULL) { + dao_output_target(parent, &UIP_IP_BUF->destipaddr, RPL_ZERO_LIFETIME); + } + /* Drop packet */ + return 0; } - /* Drop packet */ - return 1; - } - } else { - /* Set the down extension flag correctly as described in Section - 11.2 of RFC6550. If the packet progresses along a DAO route, - the down flag should be set. */ - if(uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr) == NULL) { - /* No route was found, so this packet will go towards the RPL - root. If so, we should not set the down flag. */ - UIP_EXT_HDR_OPT_RPL_BUF->flags &= ~RPL_HDR_OPT_DOWN; - PRINTF("RPL option going up\n"); } else { - /* A DAO route was found so we set the down flag. */ - UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_DOWN; - PRINTF("RPL option going down\n"); + /* Set the down extension flag correctly as described in Section + 11.2 of RFC6550. If the packet progresses along a DAO route, + the down flag should be set. */ + if(uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr) == NULL) { + /* No route was found, so this packet will go towards the RPL + root. If so, we should not set the down flag. */ + UIP_EXT_HDR_OPT_RPL_BUF->flags &= ~RPL_HDR_OPT_DOWN; + PRINTF("RPL option going up\n"); + } else { + /* A DAO route was found so we set the down flag. */ + UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_DOWN; + PRINTF("RPL option going down\n"); + } } } uip_ext_len = last_uip_ext_len; - return 0; + return 1; default: PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); uip_ext_len = last_uip_ext_len; - return 0; + return 1; } } /*---------------------------------------------------------------------------*/ +static int +insert_hbh_header(void) +{ + int uip_ext_opt_offset; + int last_uip_ext_len; + uint8_t temp_len; + + last_uip_ext_len = uip_ext_len; + uip_ext_len = 0; + uip_ext_opt_offset = 2; + + /* Insert hop-by-hop header */ + PRINTF("RPL: Creating hop-by-hop option\n"); + if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_BUFSIZE) { + PRINTF("RPL: Packet too long: impossible to add hop-by-hop option\n"); + uip_ext_len = last_uip_ext_len; + return 0; + } + + /* Move existing ext headers and payload UIP_EXT_BUF further */ + memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF, uip_len - UIP_IPH_LEN); + memset(UIP_HBHO_BUF, 0, RPL_HOP_BY_HOP_LEN); + + /* Update IP and HBH protocol and fields */ + UIP_HBHO_BUF->next = UIP_IP_BUF->proto; + UIP_IP_BUF->proto = UIP_PROTO_HBHO; + + /* Initialize HBH option */ + UIP_HBHO_BUF->len = (RPL_HOP_BY_HOP_LEN - 8) / 8; + UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL; + UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN; + UIP_EXT_HDR_OPT_RPL_BUF->flags = 0; + UIP_EXT_HDR_OPT_RPL_BUF->instance = 0; + UIP_EXT_HDR_OPT_RPL_BUF->senderrank = 0; + uip_len += RPL_HOP_BY_HOP_LEN; + temp_len = UIP_IP_BUF->len[1]; + UIP_IP_BUF->len[1] += RPL_HOP_BY_HOP_LEN; + if(UIP_IP_BUF->len[1] < temp_len) { + UIP_IP_BUF->len[0]++; + } + + uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN; + return 1; +} +/*---------------------------------------------------------------------------*/ int -rpl_update_header_final(uip_ipaddr_t *addr) +rpl_finalize_header(uip_ipaddr_t *addr) { rpl_parent_t *parent; int uip_ext_opt_offset; @@ -304,10 +625,10 @@ rpl_update_header_final(uip_ipaddr_t *addr) uip_ext_opt_offset = 2; if(UIP_IP_BUF->proto == UIP_PROTO_HBHO) { - if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_LEN - 8) { + if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)) { PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); uip_ext_len = last_uip_ext_len; - return 0; + return 1; } if(UIP_EXT_HDR_OPT_BUF->type == UIP_EXT_HDR_OPT_RPL) { @@ -315,7 +636,7 @@ rpl_update_header_final(uip_ipaddr_t *addr) PRINTF("RPL: Updating RPL option\n"); if(default_instance == NULL || !default_instance->used || !default_instance->current_dag->joined) { PRINTF("RPL: Unable to add hop-by-hop extension header: incorrect default instance\n"); - return 1; + return 0; } parent = rpl_find_parent(default_instance->current_dag, addr); if(parent == NULL || parent != parent->dag->preferred_parent) { @@ -326,78 +647,100 @@ rpl_update_header_final(uip_ipaddr_t *addr) } } } - return 0; + return 1; } /*---------------------------------------------------------------------------*/ void rpl_remove_header(void) { uint8_t temp_len; + uint8_t rpl_ext_hdr_len; + uint8_t *uip_next_hdr; uip_ext_len = 0; + uip_next_hdr = &UIP_IP_BUF->proto; - PRINTF("RPL: Verifying the presence of the RPL header option\n"); - switch(UIP_IP_BUF->proto){ - case UIP_PROTO_HBHO: - PRINTF("RPL: Removing the RPL header option\n"); - UIP_IP_BUF->proto = UIP_HBHO_BUF->next; - temp_len = UIP_IP_BUF->len[1]; - uip_len -= UIP_HBHO_BUF->len + 8; - UIP_IP_BUF->len[1] -= UIP_HBHO_BUF->len + 8; - if(UIP_IP_BUF->len[1] > temp_len) { - UIP_IP_BUF->len[0]--; + PRINTF("RPL: Verifying the presence of RPL extension headers\n"); + + /* Look for hop-by-hop and routing headers */ + while(uip_next_hdr != NULL) { + switch(*uip_next_hdr) { + case UIP_PROTO_TCP: + case UIP_PROTO_UDP: + case UIP_PROTO_ICMP6: + case UIP_PROTO_NONE: + return; + case UIP_PROTO_HBHO: + case UIP_PROTO_ROUTING: + /* Remove hop-by-hop and routing headers */ + *uip_next_hdr = UIP_EXT_BUF->next; + rpl_ext_hdr_len = (UIP_EXT_BUF->len * 8) + 8; + temp_len = UIP_IP_BUF->len[1]; + uip_len -= rpl_ext_hdr_len; + UIP_IP_BUF->len[1] -= rpl_ext_hdr_len; + if(UIP_IP_BUF->len[1] > temp_len) { + UIP_IP_BUF->len[0]--; + } + PRINTF("RPL: Removing RPL extension header (type %u, len %u)\n", *uip_next_hdr, rpl_ext_hdr_len); + memmove(UIP_EXT_BUF, ((uint8_t *)UIP_EXT_BUF) + rpl_ext_hdr_len, uip_len - UIP_IPH_LEN); + break; + default: + /* Move to next header */ + if(uip_next_hdr != &UIP_IP_BUF->proto) { + uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; + } + uip_next_hdr = &UIP_EXT_BUF->next; + break; } - memmove(UIP_EXT_BUF, UIP_HBHO_NEXT_BUF, uip_len - UIP_IPH_LEN); - break; - default: - PRINTF("RPL: No hop-by-hop Option found\n"); - } -} -/*---------------------------------------------------------------------------*/ -uint8_t -rpl_invert_header(void) -{ - uint8_t uip_ext_opt_offset; - uint8_t last_uip_ext_len; - - last_uip_ext_len = uip_ext_len; - uip_ext_len = 0; - uip_ext_opt_offset = 2; - - PRINTF("RPL: Verifying the presence of the RPL header option\n"); - switch(UIP_IP_BUF->proto) { - case UIP_PROTO_HBHO: - break; - default: - PRINTF("RPL: No hop-by-hop Option found\n"); - uip_ext_len = last_uip_ext_len; - return 0; - } - - switch (UIP_EXT_HDR_OPT_BUF->type) { - case UIP_EXT_HDR_OPT_RPL: - PRINTF("RPL: Updating RPL option (switching direction)\n"); - UIP_EXT_HDR_OPT_RPL_BUF->flags &= RPL_HDR_OPT_DOWN; - UIP_EXT_HDR_OPT_RPL_BUF->flags ^= RPL_HDR_OPT_DOWN; - UIP_EXT_HDR_OPT_RPL_BUF->senderrank = UIP_HTONS(rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance)->current_dag->rank); - uip_ext_len = last_uip_ext_len; - return RPL_HOP_BY_HOP_LEN; - default: - PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); - uip_ext_len = last_uip_ext_len; - return 0; } } /*---------------------------------------------------------------------------*/ void rpl_insert_header(void) { -#if RPL_INSERT_HBH_OPTION - if(default_instance != NULL && !uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { - rpl_update_header_empty(); + if(default_instance == NULL || default_instance->current_dag == NULL + || uip_is_addr_linklocal(&UIP_IP_BUF->destipaddr) || uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { + return; + } + + if(RPL_IS_STORING(default_instance)) { + insert_hbh_header(); + } + + if(RPL_IS_NON_STORING(default_instance)) { + if(default_instance->current_dag != NULL) { + if(default_instance->current_dag->rank == ROOT_RANK(default_instance)) { + insert_srh_header(); + } else { + insert_hbh_header(); + } + } } -#endif } /*---------------------------------------------------------------------------*/ +int +rpl_update_header(void) +{ + if(default_instance == NULL) { + return 0; + } + + if(default_instance->current_dag != NULL) { + if(default_instance->current_dag->rank == ROOT_RANK(default_instance)) { + /* At the root, remove headers if any, and insert SRH or HBH + * (SRH is inserted only if the destination is in the DODAG) */ + rpl_remove_header(); + if(RPL_IS_NON_STORING(default_instance)) { + return insert_srh_header(); + } else { + return insert_hbh_header(); + } + } else { + return update_hbh_header(); + } + } else { + return 0; + } +} /** @}*/ diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index f0ba41308..5fac66d7c 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -51,8 +51,10 @@ #include "net/ipv6/uip-nd6.h" #include "net/ipv6/uip-icmp6.h" #include "net/rpl/rpl-private.h" +#include "net/rpl/rpl-ns.h" #include "net/packetbuf.h" #include "net/ipv6/multicast/uip-mcast6.h" +#include "random.h" #include #include @@ -76,6 +78,9 @@ static void dio_input(void); static void dao_input(void); static void dao_ack_input(void); +static void dao_output_target_seq(rpl_parent_t *parent, uip_ipaddr_t *prefix, + uint8_t lifetime, uint8_t seq_no); + /* some debug callbacks useful when debugging RPL networks */ #ifdef RPL_DEBUG_DIO_INPUT void RPL_DEBUG_DIO_INPUT(uip_ipaddr_t *, rpl_dio_t *); @@ -87,9 +92,7 @@ void RPL_DEBUG_DAO_OUTPUT(rpl_parent_t *); static uint8_t dao_sequence = RPL_LOLLIPOP_INIT; -extern rpl_of_t RPL_OF; - -#if RPL_CONF_MULTICAST +#if RPL_WITH_MULTICAST static uip_mcast6_route_t *mcast_group; #endif /*---------------------------------------------------------------------------*/ @@ -99,6 +102,40 @@ UIP_ICMP6_HANDLER(dio_handler, ICMP6_RPL, RPL_CODE_DIO, dio_input); UIP_ICMP6_HANDLER(dao_handler, ICMP6_RPL, RPL_CODE_DAO, dao_input); UIP_ICMP6_HANDLER(dao_ack_handler, ICMP6_RPL, RPL_CODE_DAO_ACK, dao_ack_input); /*---------------------------------------------------------------------------*/ + +#if RPL_WITH_DAO_ACK +static uip_ds6_route_t * +find_route_entry_by_dao_ack(uint8_t seq) +{ + uip_ds6_route_t *re; + re = uip_ds6_route_head(); + while(re != NULL) { + if(re->state.dao_seqno_out == seq && RPL_ROUTE_IS_DAO_PENDING(re)) { + /* found it! */ + return re; + } + re = uip_ds6_route_next(re); + } + return NULL; +} +#endif /* RPL_WITH_DAO_ACK */ + +#if RPL_WITH_STORING +/* prepare for forwarding of DAO */ +static uint8_t +prepare_for_dao_fwd(uint8_t sequence, uip_ds6_route_t *rep) +{ + /* not pending - or pending but not a retransmission */ + RPL_LOLLIPOP_INCREMENT(dao_sequence); + + /* set DAO pending and sequence numbers */ + rep->state.dao_seqno_in = sequence; + rep->state.dao_seqno_out = dao_sequence; + RPL_ROUTE_SET_DAO_PENDING(rep); + return dao_sequence; +} +#endif /* RPL_WITH_STORING */ +/*---------------------------------------------------------------------------*/ static int get_global_addr(uip_ipaddr_t *addr) { @@ -147,6 +184,34 @@ set16(uint8_t *buffer, int pos, uint16_t value) buffer[pos++] = value & 0xff; } /*---------------------------------------------------------------------------*/ +uip_ds6_nbr_t * +rpl_icmp6_update_nbr_table(uip_ipaddr_t *from, nbr_table_reason_t reason, void *data) +{ + uip_ds6_nbr_t *nbr; + + if((nbr = uip_ds6_nbr_lookup(from)) == NULL) { + if((nbr = uip_ds6_nbr_add(from, (uip_lladdr_t *) + packetbuf_addr(PACKETBUF_ADDR_SENDER), + 0, NBR_REACHABLE, reason, data)) != NULL) { + PRINTF("RPL: Neighbor added to neighbor cache "); + PRINT6ADDR(from); + PRINTF(", "); + PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); + PRINTF("\n"); + } + } + + if(nbr != NULL) { +#if UIP_ND6_SEND_NA + /* set reachable timer if we added or found the nbr entry - and update + neighbor entry to reachable to avoid sending NS/NA, etc. */ + stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000); + nbr->state = NBR_REACHABLE; +#endif /* UIP_ND6_SEND_NA */ + } + return nbr; + } +/*---------------------------------------------------------------------------*/ static void dis_input(void) { @@ -170,8 +235,19 @@ dis_input(void) rpl_reset_dio_timer(instance); } else { #endif /* !RPL_LEAF_ONLY */ - PRINTF("RPL: Unicast DIS, reply to sender\n"); - dio_output(instance, &UIP_IP_BUF->srcipaddr); + /* Check if this neighbor should be added according to the policy. */ + if(rpl_icmp6_update_nbr_table(&UIP_IP_BUF->srcipaddr, + NBR_TABLE_REASON_RPL_DIS, NULL) == NULL) { + PRINTF("RPL: Out of Memory, not sending unicast DIO, DIS from "); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF(", "); + PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); + PRINTF("\n"); + } else { + PRINTF("RPL: Unicast DIS, reply to sender\n"); + dio_output(instance, &UIP_IP_BUF->srcipaddr); + } + /* } */ } } } @@ -218,7 +294,6 @@ dio_input(void) int i; int len; uip_ipaddr_t from; - uip_ds6_nbr_t *nbr; memset(&dio, 0, sizeof(dio)); @@ -228,7 +303,7 @@ dio_input(void) dio.dag_redund = RPL_DIO_REDUNDANCY; dio.dag_min_hoprankinc = RPL_MIN_HOPRANKINC; dio.dag_max_rankinc = RPL_MAX_RANKINC; - dio.ocp = RPL_OF.ocp; + dio.ocp = RPL_OF_OCP; dio.default_lifetime = RPL_DEFAULT_LIFETIME; dio.lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT; @@ -239,30 +314,6 @@ dio_input(void) PRINT6ADDR(&from); PRINTF("\n"); - if((nbr = uip_ds6_nbr_lookup(&from)) == NULL) { - if((nbr = uip_ds6_nbr_add(&from, (uip_lladdr_t *) - packetbuf_addr(PACKETBUF_ADDR_SENDER), - 0, NBR_REACHABLE)) != NULL) { - /* set reachable timer */ - stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000); - PRINTF("RPL: Neighbor added to neighbor cache "); - PRINT6ADDR(&from); - PRINTF(", "); - PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); - PRINTF("\n"); - } else { - PRINTF("RPL: Out of memory, dropping DIO from "); - PRINT6ADDR(&from); - PRINTF(", "); - PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); - PRINTF("\n"); - - goto discard; - } - } else { - PRINTF("RPL: Neighbor already in neighbor cache\n"); - } - buffer_length = uip_len - uip_l3_icmp_hdr_len; /* Process the DIO base option. */ @@ -428,6 +479,7 @@ dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr) { unsigned char *buffer; int pos; + int is_root; rpl_dag_t *dag = instance->current_dag; #if !RPL_LEAF_ONLY uip_ipaddr_t addr; @@ -448,6 +500,7 @@ dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr) buffer = UIP_ICMP_PAYLOAD; buffer[pos++] = instance->instance_id; buffer[pos++] = dag->version; + is_root = (dag->rank == ROOT_RANK(instance)); #if RPL_LEAF_ONLY PRINTF("RPL: LEAF ONLY DIO rank set to INFINITE_RANK\n"); @@ -468,7 +521,7 @@ dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr) buffer[pos++] = instance->dtsn_out; - if(uc_addr == NULL) { + if(RPL_DIO_REFRESH_DAO_ROUTES && is_root && uc_addr == NULL) { /* Request new DAO to refresh route. We do not do this for unicast DIO * in order to avoid DAO messages after a DIS-DIO update, * or upon unicast DIO probing. */ @@ -578,8 +631,9 @@ dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr) } /*---------------------------------------------------------------------------*/ static void -dao_input(void) +dao_input_storing(void) { +#if RPL_WITH_STORING uip_ipaddr_t dao_sender_addr; rpl_dag_t *dag; rpl_instance_t *instance; @@ -603,17 +657,13 @@ dao_input(void) int learned_from; rpl_parent_t *parent; uip_ds6_nbr_t *nbr; + int is_root; prefixlen = 0; parent = NULL; uip_ipaddr_copy(&dao_sender_addr, &UIP_IP_BUF->srcipaddr); - /* Destination Advertisement Object */ - PRINTF("RPL: Received a DAO from "); - PRINT6ADDR(&dao_sender_addr); - PRINTF("\n"); - buffer = UIP_ICMP_PAYLOAD; buffer_length = uip_len - uip_l3_icmp_hdr_len; @@ -621,11 +671,6 @@ dao_input(void) instance_id = buffer[pos++]; instance = rpl_get_instance(instance_id); - if(instance == NULL) { - PRINTF("RPL: Ignoring a DAO for an unknown RPL instance(%u)\n", - instance_id); - goto discard; - } lifetime = instance->default_lifetime; @@ -635,11 +680,13 @@ dao_input(void) sequence = buffer[pos++]; dag = instance->current_dag; + is_root = (dag->rank == ROOT_RANK(instance)); + /* Is the DAG ID present? */ if(flags & RPL_DAO_D_FLAG) { if(memcmp(&dag->dag_id, &buffer[pos], sizeof(dag->dag_id))) { PRINTF("RPL: Ignoring a DAO for a DAG different from ours\n"); - goto discard; + return; } pos += 16; } @@ -647,8 +694,12 @@ dao_input(void) learned_from = uip_is_addr_mcast(&dao_sender_addr) ? RPL_ROUTE_FROM_MULTICAST_DAO : RPL_ROUTE_FROM_UNICAST_DAO; - PRINTF("RPL: DAO from %s\n", - learned_from == RPL_ROUTE_FROM_UNICAST_DAO? "unicast": "multicast"); + /* Destination Advertisement Object */ + PRINTF("RPL: Received a (%s) DAO with sequence number %u from ", + learned_from == RPL_ROUTE_FROM_UNICAST_DAO? "unicast": "multicast", sequence); + PRINT6ADDR(&dao_sender_addr); + PRINTF("\n"); + if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) { /* Check whether this is a DAO forwarding loop. */ parent = rpl_find_parent(dag, &dao_sender_addr); @@ -660,7 +711,7 @@ dao_input(void) DAG_RANK(parent->rank, instance), DAG_RANK(dag->rank, instance)); parent->rank = INFINITE_RANK; parent->flags |= RPL_PARENT_FLAG_UPDATED; - goto discard; + return; } /* If we get the DAO from our parent, we also have a loop. */ @@ -668,7 +719,7 @@ dao_input(void) PRINTF("RPL: Loop detected when receiving a unicast DAO from our parent\n"); parent->rank = INFINITE_RANK; parent->flags |= RPL_PARENT_FLAG_UPDATED; - goto discard; + return; } } @@ -704,7 +755,7 @@ dao_input(void) PRINT6ADDR(&prefix); PRINTF("\n"); -#if RPL_CONF_MULTICAST +#if RPL_WITH_MULTICAST if(uip_is_addr_mcast_global(&prefix)) { mcast_group = uip_mcast6_route_add(&prefix); if(mcast_group) { @@ -721,91 +772,319 @@ dao_input(void) PRINTF("RPL: No-Path DAO received\n"); /* No-Path DAO received; invoke the route purging routine. */ if(rep != NULL && - rep->state.nopath_received == 0 && + !RPL_ROUTE_IS_NOPATH_RECEIVED(rep) && rep->length == prefixlen && uip_ds6_route_nexthop(rep) != NULL && uip_ipaddr_cmp(uip_ds6_route_nexthop(rep), &dao_sender_addr)) { PRINTF("RPL: Setting expiration timer for prefix "); PRINT6ADDR(&prefix); PRINTF("\n"); - rep->state.nopath_received = 1; + RPL_ROUTE_SET_NOPATH_RECEIVED(rep); rep->state.lifetime = RPL_NOPATH_REMOVAL_DELAY; /* We forward the incoming No-Path DAO to our parent, if we have one. */ if(dag->preferred_parent != NULL && rpl_get_parent_ipaddr(dag->preferred_parent) != NULL) { - PRINTF("RPL: Forwarding No-Path DAO to parent "); + uint8_t out_seq; + out_seq = prepare_for_dao_fwd(sequence, rep); + + PRINTF("RPL: Forwarding No-path DAO to parent - out_seq:%d", + out_seq); PRINT6ADDR(rpl_get_parent_ipaddr(dag->preferred_parent)); PRINTF("\n"); + + buffer = UIP_ICMP_PAYLOAD; + buffer[3] = out_seq; /* add an outgoing seq no before fwd */ uip_icmp6_send(rpl_get_parent_ipaddr(dag->preferred_parent), ICMP6_RPL, RPL_CODE_DAO, buffer_length); } - if(flags & RPL_DAO_K_FLAG) { - dao_ack_output(instance, &dao_sender_addr, sequence); - } } - goto discard; + /* independent if we remove or not - ACK the request */ + if(flags & RPL_DAO_K_FLAG) { + /* indicate that we accepted the no-path DAO */ + uip_clear_buf(); + dao_ack_output(instance, &dao_sender_addr, sequence, + RPL_DAO_ACK_UNCONDITIONAL_ACCEPT); + } + return; } - PRINTF("RPL: adding DAO route\n"); + PRINTF("RPL: Adding DAO route\n"); - if((nbr = uip_ds6_nbr_lookup(&dao_sender_addr)) == NULL) { - if((nbr = uip_ds6_nbr_add(&dao_sender_addr, - (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER), - 0, NBR_REACHABLE)) != NULL) { - /* set reachable timer */ - stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000); - PRINTF("RPL: Neighbor added to neighbor cache "); - PRINT6ADDR(&dao_sender_addr); - PRINTF(", "); - PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); - PRINTF("\n"); - } else { - PRINTF("RPL: Out of Memory, dropping DAO from "); - PRINT6ADDR(&dao_sender_addr); - PRINTF(", "); - PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); - PRINTF("\n"); - goto discard; + /* Update and add neighbor - if no room - fail. */ + if((nbr = rpl_icmp6_update_nbr_table(&dao_sender_addr, NBR_TABLE_REASON_RPL_DAO, instance)) == NULL) { + PRINTF("RPL: Out of Memory, dropping DAO from "); + PRINT6ADDR(&dao_sender_addr); + PRINTF(", "); + PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); + PRINTF("\n"); + if(flags & RPL_DAO_K_FLAG) { + /* signal the failure to add the node */ + dao_ack_output(instance, &dao_sender_addr, sequence, + is_root ? RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT : + RPL_DAO_ACK_UNABLE_TO_ACCEPT); } - } else { - PRINTF("RPL: Neighbor already in neighbor cache\n"); + return; } rep = rpl_add_route(dag, &prefix, prefixlen, &dao_sender_addr); if(rep == NULL) { RPL_STAT(rpl_stats.mem_overflows++); PRINTF("RPL: Could not add a route after receiving a DAO\n"); - goto discard; + if(flags & RPL_DAO_K_FLAG) { + /* signal the failure to add the node */ + dao_ack_output(instance, &dao_sender_addr, sequence, + is_root ? RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT : + RPL_DAO_ACK_UNABLE_TO_ACCEPT); + } + return; } + /* set lifetime and clear NOPATH bit */ rep->state.lifetime = RPL_LIFETIME(instance, lifetime); - rep->state.learned_from = learned_from; - rep->state.nopath_received = 0; + RPL_ROUTE_CLEAR_NOPATH_RECEIVED(rep); -#if RPL_CONF_MULTICAST +#if RPL_WITH_MULTICAST fwd_dao: #endif if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) { + int should_ack = 0; + + if(flags & RPL_DAO_K_FLAG) { + /* + * check if this route is already installed and we can ack now! + * not pending - and same seq-no means that we can ack. + * (e.g. the route is installed already so it will not take any + * more room that it already takes - so should be ok!) + */ + if((!RPL_ROUTE_IS_DAO_PENDING(rep) && + rep->state.dao_seqno_in == sequence) || + dag->rank == ROOT_RANK(instance)) { + should_ack = 1; + } + } + if(dag->preferred_parent != NULL && rpl_get_parent_ipaddr(dag->preferred_parent) != NULL) { + uint8_t out_seq = 0; + /* if this is pending and we get the same seq no it is a retrans */ + if(RPL_ROUTE_IS_DAO_PENDING(rep) && + rep->state.dao_seqno_in == sequence) { + /* keep the same seq-no as before for parent also */ + out_seq = rep->state.dao_seqno_out; + } else { + out_seq = prepare_for_dao_fwd(sequence, rep); + } + PRINTF("RPL: Forwarding DAO to parent "); PRINT6ADDR(rpl_get_parent_ipaddr(dag->preferred_parent)); - PRINTF("\n"); + PRINTF(" in seq: %d out seq: %d\n", sequence, out_seq); + + buffer = UIP_ICMP_PAYLOAD; + buffer[3] = out_seq; /* add an outgoing seq no before fwd */ uip_icmp6_send(rpl_get_parent_ipaddr(dag->preferred_parent), ICMP6_RPL, RPL_CODE_DAO, buffer_length); } - if(flags & RPL_DAO_K_FLAG) { - dao_ack_output(instance, &dao_sender_addr, sequence); + if(should_ack) { + PRINTF("RPL: Sending DAO ACK\n"); + uip_clear_buf(); + dao_ack_output(instance, &dao_sender_addr, sequence, + RPL_DAO_ACK_UNCONDITIONAL_ACCEPT); } } +#endif /* RPL_WITH_STORING */ +} +/*---------------------------------------------------------------------------*/ +static void +dao_input_nonstoring(void) +{ +#if RPL_WITH_NON_STORING + uip_ipaddr_t dao_sender_addr; + uip_ipaddr_t dao_parent_addr; + rpl_dag_t *dag; + rpl_instance_t *instance; + unsigned char *buffer; + uint16_t sequence; + uint8_t instance_id; + uint8_t lifetime; + uint8_t prefixlen; + uint8_t flags; + uint8_t subopt_type; + uip_ipaddr_t prefix; + uint8_t buffer_length; + int pos; + int len; + int i; + + prefixlen = 0; + + uip_ipaddr_copy(&dao_sender_addr, &UIP_IP_BUF->srcipaddr); + memset(&dao_parent_addr, 0, 16); + + buffer = UIP_ICMP_PAYLOAD; + buffer_length = uip_len - uip_l3_icmp_hdr_len; + + pos = 0; + instance_id = buffer[pos++]; + instance = rpl_get_instance(instance_id); + lifetime = instance->default_lifetime; + + flags = buffer[pos++]; + /* reserved */ + pos++; + sequence = buffer[pos++]; + + dag = instance->current_dag; + /* Is the DAG ID present? */ + if(flags & RPL_DAO_D_FLAG) { + if(memcmp(&dag->dag_id, &buffer[pos], sizeof(dag->dag_id))) { + PRINTF("RPL: Ignoring a DAO for a DAG different from ours\n"); + return; + } + pos += 16; + } + + /* Check if there are any RPL options present. */ + for(i = pos; i < buffer_length; i += len) { + subopt_type = buffer[i]; + if(subopt_type == RPL_OPTION_PAD1) { + len = 1; + } else { + /* The option consists of a two-byte header and a payload. */ + len = 2 + buffer[i + 1]; + } + + switch(subopt_type) { + case RPL_OPTION_TARGET: + /* Handle the target option. */ + prefixlen = buffer[i + 3]; + memset(&prefix, 0, sizeof(prefix)); + memcpy(&prefix, buffer + i + 4, (prefixlen + 7) / CHAR_BIT); + break; + case RPL_OPTION_TRANSIT: + /* The path sequence and control are ignored. */ + /* pathcontrol = buffer[i + 3]; + pathsequence = buffer[i + 4];*/ + lifetime = buffer[i + 5]; + if(len >= 20) { + memcpy(&dao_parent_addr, buffer + i + 6, 16); + } + break; + } + } + + PRINTF("RPL: DAO lifetime: %u, prefix length: %u prefix: ", + (unsigned)lifetime, (unsigned)prefixlen); + PRINT6ADDR(&prefix); + PRINTF(", parent: "); + PRINT6ADDR(&dao_parent_addr); + PRINTF(" \n"); + + if(lifetime == RPL_ZERO_LIFETIME) { + PRINTF("RPL: No-Path DAO received\n"); + rpl_ns_expire_parent(dag, &prefix, &dao_parent_addr); + } else { + if(rpl_ns_update_node(dag, &prefix, &dao_parent_addr, RPL_LIFETIME(instance, lifetime)) == NULL) { + PRINTF("RPL: failed to add link\n"); + return; + } + } + + if(flags & RPL_DAO_K_FLAG) { + PRINTF("RPL: Sending DAO ACK\n"); + uip_clear_buf(); + dao_ack_output(instance, &dao_sender_addr, sequence, + RPL_DAO_ACK_UNCONDITIONAL_ACCEPT); + } +#endif /* RPL_WITH_NON_STORING */ +} +/*---------------------------------------------------------------------------*/ +static void +dao_input(void) +{ + rpl_instance_t *instance; + uint8_t instance_id; + + /* Destination Advertisement Object */ + PRINTF("RPL: Received a DAO from "); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF("\n"); + + instance_id = UIP_ICMP_PAYLOAD[0]; + instance = rpl_get_instance(instance_id); + if(instance == NULL) { + PRINTF("RPL: Ignoring a DAO for an unknown RPL instance(%u)\n", + instance_id); + goto discard; + } + + if(RPL_IS_STORING(instance)) { + dao_input_storing(); + } else if(RPL_IS_NON_STORING(instance)) { + dao_input_nonstoring(); + } discard: uip_clear_buf(); } /*---------------------------------------------------------------------------*/ +#if RPL_WITH_DAO_ACK +static void +handle_dao_retransmission(void *ptr) +{ + rpl_parent_t *parent; + uip_ipaddr_t prefix; + rpl_instance_t *instance; + + parent = ptr; + if(parent == NULL || parent->dag == NULL || parent->dag->instance == NULL) { + return; + } + instance = parent->dag->instance; + + if(instance->my_dao_transmissions >= RPL_DAO_MAX_RETRANSMISSIONS) { + /* No more retransmissions - give up. */ + if(instance->lifetime_unit == 0xffff && instance->default_lifetime == 0xff) { + /* + * ContikiRPL was previously using infinite lifetime for routes + * and no DAO_ACK configured. This probably means that the root + * and possibly other nodes might be running an old version that + * does not support DAO ack. Assume that everything is ok for + * now and let the normal repair mechanisms detect any problems. + */ + return; + } + + if(RPL_IS_STORING(instance) && instance->of->dao_ack_callback) { + /* Inform the objective function about the timeout. */ + instance->of->dao_ack_callback(parent, RPL_DAO_ACK_TIMEOUT); + } + + /* Perform local repair and hope to find another parent. */ + rpl_local_repair(instance); + return; + } + + PRINTF("RPL: will retransmit DAO - seq:%d trans:%d\n", instance->my_dao_seqno, + instance->my_dao_transmissions); + + if(get_global_addr(&prefix) == 0) { + return; + } + + ctimer_set(&instance->dao_retransmit_timer, + RPL_DAO_RETRANSMISSION_TIMEOUT / 2 + + (random_rand() % (RPL_DAO_RETRANSMISSION_TIMEOUT / 2)), + handle_dao_retransmission, parent); + + instance->my_dao_transmissions++; + dao_output_target_seq(parent, &prefix, + instance->default_lifetime, instance->my_dao_seqno); +} +#endif /* RPL_WITH_DAO_ACK */ +/*---------------------------------------------------------------------------*/ void dao_output(rpl_parent_t *parent, uint8_t lifetime) { @@ -817,18 +1096,51 @@ dao_output(rpl_parent_t *parent, uint8_t lifetime) return; } + if(parent == NULL || parent->dag == NULL || parent->dag->instance == NULL) { + return; + } + + RPL_LOLLIPOP_INCREMENT(dao_sequence); +#if RPL_WITH_DAO_ACK + /* set up the state since this will be the first transmission of DAO */ + /* retransmissions will call directly to dao_output_target_seq */ + /* keep track of my own sending of DAO for handling ack and loss of ack */ + if(lifetime != RPL_ZERO_LIFETIME) { + rpl_instance_t *instance; + instance = parent->dag->instance; + + instance->my_dao_seqno = dao_sequence; + instance->my_dao_transmissions = 1; + ctimer_set(&instance->dao_retransmit_timer, RPL_DAO_RETRANSMISSION_TIMEOUT, + handle_dao_retransmission, parent); + } +#else + /* We know that we have tried to register so now we are assuming + that we have a down-link - unless this is a zero lifetime one */ + parent->dag->instance->has_downward_route = lifetime != RPL_ZERO_LIFETIME; +#endif /* RPL_WITH_DAO_ACK */ + /* Sending a DAO with own prefix as target */ dao_output_target(parent, &prefix, lifetime); } /*---------------------------------------------------------------------------*/ void dao_output_target(rpl_parent_t *parent, uip_ipaddr_t *prefix, uint8_t lifetime) +{ + dao_output_target_seq(parent, prefix, lifetime, dao_sequence); +} +/*---------------------------------------------------------------------------*/ +static void +dao_output_target_seq(rpl_parent_t *parent, uip_ipaddr_t *prefix, + uint8_t lifetime, uint8_t seq_no) { rpl_dag_t *dag; rpl_instance_t *instance; unsigned char *buffer; uint8_t prefixlen; int pos; + uip_ipaddr_t *parent_ipaddr = NULL; + uip_ipaddr_t *dest_ipaddr = NULL; /* Destination Advertisement Object */ @@ -842,6 +1154,12 @@ dao_output_target(rpl_parent_t *parent, uip_ipaddr_t *prefix, uint8_t lifetime) return; } + parent_ipaddr = rpl_get_parent_ipaddr(parent); + if(parent_ipaddr == NULL) { + PRINTF("RPL dao_output_target error parent IP address NULL\n"); + return; + } + dag = parent->dag; if(dag == NULL) { PRINTF("RPL dao_output_target error dag NULL\n"); @@ -863,8 +1181,6 @@ dao_output_target(rpl_parent_t *parent, uip_ipaddr_t *prefix, uint8_t lifetime) #endif buffer = UIP_ICMP_PAYLOAD; - - RPL_LOLLIPOP_INCREMENT(dao_sequence); pos = 0; buffer[pos++] = instance->instance_id; @@ -872,12 +1188,14 @@ dao_output_target(rpl_parent_t *parent, uip_ipaddr_t *prefix, uint8_t lifetime) #if RPL_DAO_SPECIFY_DAG buffer[pos] |= RPL_DAO_D_FLAG; #endif /* RPL_DAO_SPECIFY_DAG */ -#if RPL_CONF_DAO_ACK - buffer[pos] |= RPL_DAO_K_FLAG; -#endif /* RPL_CONF_DAO_ACK */ +#if RPL_WITH_DAO_ACK + if(lifetime != RPL_ZERO_LIFETIME) { + buffer[pos] |= RPL_DAO_K_FLAG; + } +#endif /* RPL_WITH_DAO_ACK */ ++pos; buffer[pos++] = 0; /* reserved */ - buffer[pos++] = dao_sequence; + buffer[pos++] = seq_no; #if RPL_DAO_SPECIFY_DAG memcpy(buffer + pos, &dag->dag_id, sizeof(dag->dag_id)); pos+=sizeof(dag->dag_id); @@ -894,61 +1212,154 @@ dao_output_target(rpl_parent_t *parent, uip_ipaddr_t *prefix, uint8_t lifetime) /* Create a transit information sub-option. */ buffer[pos++] = RPL_OPTION_TRANSIT; - buffer[pos++] = 4; + buffer[pos++] = (instance->mop != RPL_MOP_NON_STORING) ? 4 : 20; buffer[pos++] = 0; /* flags - ignored */ buffer[pos++] = 0; /* path control - ignored */ buffer[pos++] = 0; /* path seq - ignored */ buffer[pos++] = lifetime; - PRINTF("RPL: Sending %sDAO with prefix ", lifetime == RPL_ZERO_LIFETIME ? "No-Path " : ""); + if(instance->mop != RPL_MOP_NON_STORING) { + /* Send DAO to parent */ + dest_ipaddr = parent_ipaddr; + } else { + /* Include parent global IP address */ + memcpy(buffer + pos, &parent->dag->dag_id, 8); /* Prefix */ + pos += 8; + memcpy(buffer + pos, ((const unsigned char *)parent_ipaddr) + 8, 8); /* Interface identifier */ + pos += 8; + /* Send DAO to root */ + dest_ipaddr = &parent->dag->dag_id; + } + + PRINTF("RPL: Sending a %sDAO with sequence number %u, lifetime %u, prefix ", + lifetime == RPL_ZERO_LIFETIME ? "No-Path " : "", seq_no, lifetime); + PRINT6ADDR(prefix); PRINTF(" to "); - PRINT6ADDR(rpl_get_parent_ipaddr(parent)); + PRINT6ADDR(dest_ipaddr); + PRINTF(" , parent "); + PRINT6ADDR(parent_ipaddr); PRINTF("\n"); - if(rpl_get_parent_ipaddr(parent) != NULL) { - uip_icmp6_send(rpl_get_parent_ipaddr(parent), ICMP6_RPL, RPL_CODE_DAO, pos); + if(dest_ipaddr != NULL) { + uip_icmp6_send(dest_ipaddr, ICMP6_RPL, RPL_CODE_DAO, pos); } } /*---------------------------------------------------------------------------*/ static void dao_ack_input(void) { -#if DEBUG - unsigned char *buffer; +#if RPL_WITH_DAO_ACK + + uint8_t *buffer; + uint8_t instance_id; uint8_t sequence; uint8_t status; + rpl_instance_t *instance; + rpl_parent_t *parent; buffer = UIP_ICMP_PAYLOAD; + instance_id = buffer[0]; sequence = buffer[2]; status = buffer[3]; - PRINTF("RPL: Received a DAO ACK with sequence number %d and status %d from ", - sequence, status); + instance = rpl_get_instance(instance_id); + if(instance == NULL) { + uip_clear_buf(); + return; + } + + if(RPL_IS_STORING(instance)) { + parent = rpl_find_parent(instance->current_dag, &UIP_IP_BUF->srcipaddr); + if(parent == NULL) { + /* not a known instance - drop the packet and ignore */ + uip_clear_buf(); + return; + } + } else { + parent = NULL; + } + + PRINTF("RPL: Received a DAO %s with sequence number %d (%d) and status %d from ", + status < 128 ? "ACK" : "NACK", + sequence, instance->my_dao_seqno, status); PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINTF("\n"); -#endif /* DEBUG */ + + if(sequence == instance->my_dao_seqno) { + instance->has_downward_route = status < 128; + + /* always stop the retransmit timer when the ACK arrived */ + ctimer_stop(&instance->dao_retransmit_timer); + + /* Inform objective function on status of the DAO ACK */ + if(RPL_IS_STORING(instance) && instance->of->dao_ack_callback) { + instance->of->dao_ack_callback(parent, status); + } + +#if RPL_REPAIR_ON_DAO_NACK + if(status >= RPL_DAO_ACK_UNABLE_TO_ACCEPT) { + /* + * Failed the DAO transmission - need to remove the default route. + * Trigger a local repair since we can not get our DAO in. + */ + rpl_local_repair(instance); + } +#endif + + } else if(RPL_IS_STORING(instance)) { + /* this DAO ACK should be forwarded to another recently registered route */ + uip_ds6_route_t *re; + uip_ipaddr_t *nexthop; + if((re = find_route_entry_by_dao_ack(sequence)) != NULL) { + /* pick the recorded seq no from that node and forward DAO ACK - and + clear the pending flag*/ + RPL_ROUTE_CLEAR_DAO_PENDING(re); + + nexthop = uip_ds6_route_nexthop(re); + if(nexthop == NULL) { + PRINTF("RPL: No next hop to fwd DAO ACK to\n"); + } else { + PRINTF("RPL: Fwd DAO ACK to:"); + PRINT6ADDR(nexthop); + PRINTF("\n"); + buffer[2] = re->state.dao_seqno_in; + uip_icmp6_send(nexthop, ICMP6_RPL, RPL_CODE_DAO_ACK, 4); + } + + if(status >= RPL_DAO_ACK_UNABLE_TO_ACCEPT) { + /* this node did not get in to the routing tables above... - remove */ + uip_ds6_route_rm(re); + } + } else { + PRINTF("RPL: No route entry found to forward DAO ACK (seqno %u)\n", sequence); + } + } +#endif /* RPL_WITH_DAO_ACK */ uip_clear_buf(); } /*---------------------------------------------------------------------------*/ void -dao_ack_output(rpl_instance_t *instance, uip_ipaddr_t *dest, uint8_t sequence) +dao_ack_output(rpl_instance_t *instance, uip_ipaddr_t *dest, uint8_t sequence, + uint8_t status) { +#if RPL_WITH_DAO_ACK unsigned char *buffer; - PRINTF("RPL: Sending a DAO ACK with sequence number %d to ", sequence); + PRINTF("RPL: Sending a DAO %s with sequence number %d to ", status < 128 ? "ACK" : "NACK", sequence); PRINT6ADDR(dest); - PRINTF("\n"); + PRINTF(" with status %d\n", status); buffer = UIP_ICMP_PAYLOAD; buffer[0] = instance->instance_id; buffer[1] = 0; buffer[2] = sequence; - buffer[3] = 0; + buffer[3] = status; uip_icmp6_send(dest, ICMP6_RPL, RPL_CODE_DAO_ACK, 4); +#endif /* RPL_WITH_DAO_ACK */ } /*---------------------------------------------------------------------------*/ void diff --git a/core/net/rpl/rpl-mrhof.c b/core/net/rpl/rpl-mrhof.c index 47314917f..c51ac8694 100644 --- a/core/net/rpl/rpl-mrhof.c +++ b/core/net/rpl/rpl-mrhof.c @@ -32,7 +32,7 @@ /** * \file - * The Minimum Rank with Hysteresis Objective Function (MRHOF) + * The Minimum Rank with Hysteresis Objective Function (MRHOF), RFC6719 * * This implementation uses the estimated number of * transmissions (ETX) as the additive routing metric, @@ -46,150 +46,187 @@ * @{ */ +#include "net/rpl/rpl.h" #include "net/rpl/rpl-private.h" #include "net/nbr-table.h" +#include "net/link-stats.h" #define DEBUG DEBUG_NONE #include "net/ip/uip-debug.h" -static void reset(rpl_dag_t *); -static void neighbor_link_callback(rpl_parent_t *, int, int); -static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *); -static rpl_dag_t *best_dag(rpl_dag_t *, rpl_dag_t *); -static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t); -static void update_metric_container(rpl_instance_t *); +/* RFC6551 and RFC6719 do not mandate the use of a specific formula to + * compute the ETX value. This MRHOF implementation relies on the value + * computed by the link-stats module. It has an optional feature, + * RPL_MRHOF_CONF_SQUARED_ETX, that consists in squaring this value. + * This basically penalizes bad links while preserving the semantics of ETX + * (1 = perfect link, more = worse link). As a result, MRHOF will favor + * good links over short paths. Recommended when reliability is a priority. + * Without this feature, a hop with 50% PRR (ETX=2) is equivalent to two + * perfect hops with 100% PRR (ETX=1+1=2). With this feature, the former + * path obtains ETX=2*2=4 and the former ETX=1*1+1*1=2. */ +#ifdef RPL_MRHOF_CONF_SQUARED_ETX +#define RPL_MRHOF_SQUARED_ETX RPL_MRHOF_CONF_SQUARED_ETX +#else /* RPL_MRHOF_CONF_SQUARED_ETX */ +#define RPL_MRHOF_SQUARED_ETX 0 +#endif /* RPL_MRHOF_CONF_SQUARED_ETX */ -rpl_of_t rpl_mrhof = { - reset, - neighbor_link_callback, - best_parent, - best_dag, - calculate_rank, - update_metric_container, - 1 -}; - -/* Constants for the ETX moving average */ -#define ETX_SCALE 100 -#define ETX_ALPHA 90 - -/* Reject parents that have a higher link metric than the following. */ -#define MAX_LINK_METRIC 10 +#if !RPL_MRHOF_SQUARED_ETX +/* Configuration parameters of RFC6719. Reject parents that have a higher + * link metric than the following. The default value is 512 but we use 1024. */ +#define MAX_LINK_METRIC 1024 /* Eq ETX of 8 */ +/* Hysteresis of MRHOF: the rank must differ more than PARENT_SWITCH_THRESHOLD_DIV + * in order to switch preferred parent. Default in RFC6719: 192, eq ETX of 1.5. + * We use a more aggressive setting: 96, eq ETX of 0.75. + */ +#define PARENT_SWITCH_THRESHOLD 96 /* Eq ETX of 0.75 */ +#else /* !RPL_MRHOF_SQUARED_ETX */ +#define MAX_LINK_METRIC 2048 /* Eq ETX of 4 */ +#define PARENT_SWITCH_THRESHOLD 160 /* Eq ETX of 1.25 (results in a churn comparable +to the threshold of 96 in the non-squared case) */ +#endif /* !RPL_MRHOF_SQUARED_ETX */ /* Reject parents that have a higher path cost than the following. */ -#define MAX_PATH_COST 100 - -/* - * The rank must differ more than 1/PARENT_SWITCH_THRESHOLD_DIV in order - * to switch preferred parent. - */ -#define PARENT_SWITCH_THRESHOLD_DIV 2 - -typedef uint16_t rpl_path_metric_t; - -static rpl_path_metric_t -calculate_path_metric(rpl_parent_t *p) -{ - uip_ds6_nbr_t *nbr; - if(p == NULL) { - return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR; - } - nbr = rpl_get_nbr(p); - if(nbr == NULL) { - return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR; - } -#if RPL_DAG_MC == RPL_DAG_MC_NONE - { - return p->rank + (uint16_t)nbr->link_metric; - } -#elif RPL_DAG_MC == RPL_DAG_MC_ETX - return p->mc.obj.etx + (uint16_t)nbr->link_metric; -#elif RPL_DAG_MC == RPL_DAG_MC_ENERGY - return p->mc.obj.energy.energy_est + (uint16_t)nbr->link_metric; -#else -#error "Unsupported RPL_DAG_MC configured. See rpl.h." -#endif /* RPL_DAG_MC */ -} +#define MAX_PATH_COST 32768 /* Eq path ETX of 256 */ +/*---------------------------------------------------------------------------*/ static void reset(rpl_dag_t *dag) { PRINTF("RPL: Reset MRHOF\n"); } - +/*---------------------------------------------------------------------------*/ +#if RPL_WITH_DAO_ACK static void -neighbor_link_callback(rpl_parent_t *p, int status, int numtx) +dao_ack_callback(rpl_parent_t *p, int status) { - uint16_t recorded_etx = 0; - uint16_t packet_etx = numtx * RPL_DAG_MC_ETX_DIVISOR; - uint16_t new_etx; - uip_ds6_nbr_t *nbr = NULL; - - nbr = rpl_get_nbr(p); - if(nbr == NULL) { - /* No neighbor for this parent - something bad has occurred */ + if(status == RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT) { return; } - - recorded_etx = nbr->link_metric; - - /* Do not penalize the ETX when collisions or transmission errors occur. */ - if(status == MAC_TX_OK || status == MAC_TX_NOACK) { - if(status == MAC_TX_NOACK) { - packet_etx = MAX_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR; - } - - if(p->flags & RPL_PARENT_FLAG_LINK_METRIC_VALID) { - /* We already have a valid link metric, use weighted moving average to update it */ - new_etx = ((uint32_t)recorded_etx * ETX_ALPHA + - (uint32_t)packet_etx * (ETX_SCALE - ETX_ALPHA)) / ETX_SCALE; - } else { - /* We don't have a valid link metric, set it to the current packet's ETX */ - new_etx = packet_etx; - /* Set link metric as valid */ - p->flags |= RPL_PARENT_FLAG_LINK_METRIC_VALID; - } - - PRINTF("RPL: ETX changed from %u to %u (packet ETX = %u)\n", - (unsigned)(recorded_etx / RPL_DAG_MC_ETX_DIVISOR), - (unsigned)(new_etx / RPL_DAG_MC_ETX_DIVISOR), - (unsigned)(packet_etx / RPL_DAG_MC_ETX_DIVISOR)); - /* update the link metric for this nbr */ - nbr->link_metric = new_etx; + /* here we need to handle failed DAO's and other stuff */ + PRINTF("RPL: MRHOF - DAO ACK received with status: %d\n", status); + if(status >= RPL_DAO_ACK_UNABLE_TO_ACCEPT) { + /* punish the ETX as if this was 10 packets lost */ + link_stats_packet_sent(rpl_get_parent_lladdr(p), MAC_TX_OK, 10); + } else if(status == RPL_DAO_ACK_TIMEOUT) { /* timeout = no ack */ + /* punish the total lack of ACK with a similar punishment */ + link_stats_packet_sent(rpl_get_parent_lladdr(p), MAC_TX_OK, 10); } } - -static rpl_rank_t -calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank) +#endif /* RPL_WITH_DAO_ACK */ +/*---------------------------------------------------------------------------*/ +static uint16_t +parent_link_metric(rpl_parent_t *p) { - rpl_rank_t new_rank; - rpl_rank_t rank_increase; - uip_ds6_nbr_t *nbr; - - if(p == NULL || (nbr = rpl_get_nbr(p)) == NULL) { - if(base_rank == 0) { - return INFINITE_RANK; - } - rank_increase = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR; - } else { - rank_increase = nbr->link_metric; - if(base_rank == 0) { - base_rank = p->rank; - } + const struct link_stats *stats = rpl_get_parent_link_stats(p); + if(stats != NULL) { +#if RPL_MRHOF_SQUARED_ETX + uint32_t squared_etx = ((uint32_t)stats->etx * stats->etx) / LINK_STATS_ETX_DIVISOR; + return (uint16_t)MIN(squared_etx, 0xffff); +#else /* RPL_MRHOF_SQUARED_ETX */ + return stats->etx; +#endif /* RPL_MRHOF_SQUARED_ETX */ } - - if(INFINITE_RANK - base_rank < rank_increase) { - /* Reached the maximum rank. */ - new_rank = INFINITE_RANK; - } else { - /* Calculate the rank based on the new rank information from DIO or - stored otherwise. */ - new_rank = base_rank + rank_increase; - } - - return new_rank; + return 0xffff; } +/*---------------------------------------------------------------------------*/ +static uint16_t +parent_path_cost(rpl_parent_t *p) +{ + uint16_t base; + if(p == NULL || p->dag == NULL || p->dag->instance == NULL) { + return 0xffff; + } + +#if RPL_WITH_MC + /* Handle the different MC types */ + switch(p->dag->instance->mc.type) { + case RPL_DAG_MC_ETX: + base = p->mc.obj.etx; + break; + case RPL_DAG_MC_ENERGY: + base = p->mc.obj.energy.energy_est << 8; + break; + default: + base = p->rank; + break; + } +#else /* RPL_WITH_MC */ + base = p->rank; +#endif /* RPL_WITH_MC */ + + /* path cost upper bound: 0xffff */ + return MIN((uint32_t)base + parent_link_metric(p), 0xffff); +} +/*---------------------------------------------------------------------------*/ +static rpl_rank_t +rank_via_parent(rpl_parent_t *p) +{ + uint16_t min_hoprankinc; + uint16_t path_cost; + + if(p == NULL || p->dag == NULL || p->dag->instance == NULL) { + return INFINITE_RANK; + } + + min_hoprankinc = p->dag->instance->min_hoprankinc; + path_cost = parent_path_cost(p); + + /* Rank lower-bound: parent rank + min_hoprankinc */ + return MAX(MIN((uint32_t)p->rank + min_hoprankinc, 0xffff), path_cost); +} +/*---------------------------------------------------------------------------*/ +static int +parent_is_acceptable(rpl_parent_t *p) +{ + uint16_t link_metric = parent_link_metric(p); + uint16_t path_cost = parent_path_cost(p); + /* Exclude links with too high link metrics or path cost (RFC6719, 3.2.2) */ + return link_metric <= MAX_LINK_METRIC && path_cost <= MAX_PATH_COST; +} +/*---------------------------------------------------------------------------*/ +static int +parent_has_usable_link(rpl_parent_t *p) +{ + uint16_t link_metric = parent_link_metric(p); + /* Exclude links with too high link metrics */ + return link_metric <= MAX_LINK_METRIC; +} +/*---------------------------------------------------------------------------*/ +static rpl_parent_t * +best_parent(rpl_parent_t *p1, rpl_parent_t *p2) +{ + rpl_dag_t *dag; + uint16_t p1_cost; + uint16_t p2_cost; + int p1_is_acceptable; + int p2_is_acceptable; + + p1_is_acceptable = p1 != NULL && parent_is_acceptable(p1); + p2_is_acceptable = p2 != NULL && parent_is_acceptable(p2); + + if(!p1_is_acceptable) { + return p2_is_acceptable ? p2 : NULL; + } + if(!p2_is_acceptable) { + return p1_is_acceptable ? p1 : NULL; + } + + dag = p1->dag; /* Both parents are in the same DAG. */ + p1_cost = parent_path_cost(p1); + p2_cost = parent_path_cost(p2); + + /* Maintain stability of the preferred parent in case of similar ranks. */ + if(p1 == dag->preferred_parent || p2 == dag->preferred_parent) { + if(p1_cost < p2_cost + PARENT_SWITCH_THRESHOLD && + p1_cost > p2_cost - PARENT_SWITCH_THRESHOLD) { + return dag->preferred_parent; + } + } + + return p1_cost < p2_cost ? p1 : p2; +} +/*---------------------------------------------------------------------------*/ static rpl_dag_t * best_dag(rpl_dag_t *d1, rpl_dag_t *d2) { @@ -203,93 +240,77 @@ best_dag(rpl_dag_t *d1, rpl_dag_t *d2) return d1->rank < d2->rank ? d1 : d2; } - -static rpl_parent_t * -best_parent(rpl_parent_t *p1, rpl_parent_t *p2) -{ - rpl_dag_t *dag; - rpl_path_metric_t min_diff; - rpl_path_metric_t p1_metric; - rpl_path_metric_t p2_metric; - - dag = p1->dag; /* Both parents are in the same DAG. */ - - min_diff = RPL_DAG_MC_ETX_DIVISOR / - PARENT_SWITCH_THRESHOLD_DIV; - - p1_metric = calculate_path_metric(p1); - p2_metric = calculate_path_metric(p2); - - /* Maintain stability of the preferred parent in case of similar ranks. */ - if(p1 == dag->preferred_parent || p2 == dag->preferred_parent) { - if(p1_metric < p2_metric + min_diff && - p1_metric > p2_metric - min_diff) { - PRINTF("RPL: MRHOF hysteresis: %u <= %u <= %u\n", - p2_metric - min_diff, - p1_metric, - p2_metric + min_diff); - return dag->preferred_parent; - } - } - - return p1_metric < p2_metric ? p1 : p2; -} - -#if RPL_DAG_MC == RPL_DAG_MC_NONE +/*---------------------------------------------------------------------------*/ +#if !RPL_WITH_MC static void update_metric_container(rpl_instance_t *instance) { - instance->mc.type = RPL_DAG_MC; + instance->mc.type = RPL_DAG_MC_NONE; } -#else +#else /* RPL_WITH_MC */ static void update_metric_container(rpl_instance_t *instance) { - rpl_path_metric_t path_metric; rpl_dag_t *dag; -#if RPL_DAG_MC == RPL_DAG_MC_ENERGY + uint16_t path_cost; uint8_t type; -#endif - - instance->mc.type = RPL_DAG_MC; - instance->mc.flags = RPL_DAG_MC_FLAG_P; - instance->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE; - instance->mc.prec = 0; dag = instance->current_dag; - - if (!dag->joined) { + if(dag == NULL || !dag->joined) { PRINTF("RPL: Cannot update the metric container when not joined\n"); return; } if(dag->rank == ROOT_RANK(instance)) { - path_metric = 0; + /* Configure MC at root only, other nodes are auto-configured when joining */ + instance->mc.type = RPL_DAG_MC; + instance->mc.flags = 0; + instance->mc.aggr = RPL_DAG_MC_AGGR_ADDITIVE; + instance->mc.prec = 0; + path_cost = dag->rank; } else { - path_metric = calculate_path_metric(dag->preferred_parent); + path_cost = parent_path_cost(dag->preferred_parent); } -#if RPL_DAG_MC == RPL_DAG_MC_ETX - instance->mc.length = sizeof(instance->mc.obj.etx); - instance->mc.obj.etx = path_metric; - - PRINTF("RPL: My path ETX to the root is %u.%u\n", - instance->mc.obj.etx / RPL_DAG_MC_ETX_DIVISOR, - (instance->mc.obj.etx % RPL_DAG_MC_ETX_DIVISOR * 100) / - RPL_DAG_MC_ETX_DIVISOR); -#elif RPL_DAG_MC == RPL_DAG_MC_ENERGY - instance->mc.length = sizeof(instance->mc.obj.energy); - - if(dag->rank == ROOT_RANK(instance)) { - type = RPL_DAG_MC_ENERGY_TYPE_MAINS; - } else { - type = RPL_DAG_MC_ENERGY_TYPE_BATTERY; + /* Handle the different MC types */ + switch(instance->mc.type) { + case RPL_DAG_MC_NONE: + break; + case RPL_DAG_MC_ETX: + instance->mc.length = sizeof(instance->mc.obj.etx); + instance->mc.obj.etx = path_cost; + break; + case RPL_DAG_MC_ENERGY: + instance->mc.length = sizeof(instance->mc.obj.energy); + if(dag->rank == ROOT_RANK(instance)) { + type = RPL_DAG_MC_ENERGY_TYPE_MAINS; + } else { + type = RPL_DAG_MC_ENERGY_TYPE_BATTERY; + } + instance->mc.obj.energy.flags = type << RPL_DAG_MC_ENERGY_TYPE; + /* Energy_est is only one byte, use the least significant byte of the path metric. */ + instance->mc.obj.energy.energy_est = path_cost >> 8; + break; + default: + PRINTF("RPL: MRHOF, non-supported MC %u\n", instance->mc.type); + break; } - - instance->mc.obj.energy.flags = type << RPL_DAG_MC_ENERGY_TYPE; - instance->mc.obj.energy.energy_est = path_metric; -#endif /* RPL_DAG_MC == RPL_DAG_MC_ETX */ } -#endif /* RPL_DAG_MC == RPL_DAG_MC_NONE */ +#endif /* RPL_WITH_MC */ +/*---------------------------------------------------------------------------*/ +rpl_of_t rpl_mrhof = { + reset, +#if RPL_WITH_DAO_ACK + dao_ack_callback, +#endif + parent_link_metric, + parent_has_usable_link, + parent_path_cost, + rank_via_parent, + best_parent, + best_dag, + update_metric_container, + RPL_OCP_MRHOF +}; /** @}*/ diff --git a/core/net/rpl/rpl-nbr-policy.c b/core/net/rpl/rpl-nbr-policy.c new file mode 100644 index 000000000..0af5a9041 --- /dev/null +++ b/core/net/rpl/rpl-nbr-policy.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2014-2015, Yanzi Networks AB. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders 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 HOLDERS 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 uip6 + * @{ + */ + + +/** + * \file + * + * Default RPL NBR policy + * decides when to add a new discovered node to the nbr table from RPL. + * + * \author Joakim Eriksson + * Contributors: Niclas Finne , Oriol Piñol , + * + */ + +#include "net/rpl/rpl-private.h" +#include "net/nbr-table.h" +#include "net/ipv6/uip-ds6-nbr.h" +#include "net/ipv6/uip-ds6-route.h" + +#define DEBUG DEBUG_NONE +#include "net/ip/uip-debug.h" + +/* + * Policy for neighbor adds + * - one node is locked (default route) + * - max X children (nexthops) + * - max Y "best parents" + * => at least MAX_NBRS - (Y + X + 1) free slots for other. + * + * NOTE: this policy assumes that all neighbors end up being IPv6 + * neighbors and are not only MAC neighbors. + */ +#define MAX_CHILDREN (NBR_TABLE_MAX_NEIGHBORS - 2) +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) + +static int num_parents; /* any node that are possible parents */ +static int num_children; /* all children that we have as nexthop */ +static int num_free; +static linkaddr_t *worst_rank_nbr; /* the parent that has the worst rank */ +static rpl_rank_t worst_rank; +/*---------------------------------------------------------------------------*/ +#if DEBUG == DEBUG_FULL +/* + * This create a periodic call of the update_nbr function that will print + * useful debugging information when in DEBUG_FULL mode + */ +static void update_nbr(void); +static struct ctimer periodic_timer; +static int timer_init = 0; +static void +handle_periodic_timer(void *ptr) +{ + update_nbr(); + ctimer_restart(&periodic_timer); +} +#endif /* DEBUG == DEBUG_FULL */ +/*---------------------------------------------------------------------------*/ +static void +update_nbr(void) +{ + uip_ds6_nbr_t *nbr; + rpl_parent_t *parent; + int num_used; + int is_used; + rpl_rank_t rank; + +#if DEBUG == DEBUG_FULL + if(!timer_init) { + timer_init = 1; + ctimer_set(&periodic_timer, 60 * CLOCK_SECOND, + &handle_periodic_timer, NULL); + } +#endif /* DEBUG == DEBUG_FULL */ + + worst_rank = 0; + worst_rank_nbr = NULL; + num_used = 0; + num_parents = 0; + num_children = 0; + + nbr = nbr_table_head(ds6_neighbors); + while(nbr != NULL) { + linkaddr_t *lladdr = nbr_table_get_lladdr(ds6_neighbors, nbr); + is_used = 0; + + /* + * Check if this neighbor is used as nexthop and therefor being a + * RPL child. + */ + + if(uip_ds6_route_is_nexthop(&nbr->ipaddr) != 0) { + is_used++; + num_children++; + } + + parent = rpl_get_parent((uip_lladdr_t *)lladdr); + if(parent != NULL) { + num_parents++; + + if(parent->dag != NULL && parent->dag->preferred_parent == parent) { + /* + * This is the preferred parent for the DAG and must not be removed + * Note: this assumes that only RPL adds default routes. + */ + } else if(is_used == 0 && worst_rank < INFINITE_RANK && + parent->rank > 0 && + parent->dag != NULL && + parent->dag->instance != NULL && + (rank = parent->dag->instance->of->rank_via_parent(parent)) > worst_rank) { + /* This is the worst-rank neighbor - this is a good candidate for removal */ + worst_rank = rank; + worst_rank_nbr = lladdr; + } + /* add to is_used after evaluation of is_used above */ + is_used++; + } + + if(is_used == 0) { + /* This neighbor is neither parent or child and can be safely removed */ + worst_rank_nbr = lladdr; + worst_rank = INFINITE_RANK; + } else if(is_used > 1) { + PRINTF("NBR-POLICY: *** Neighbor is both child and candidate parent: "); + PRINTLLADDR((uip_lladdr_t *)lladdr); + PRINTF("\n"); + } + + nbr = nbr_table_next(ds6_neighbors, nbr); + num_used++; + } + /* how many more IP neighbors can be have? */ + num_free = NBR_TABLE_MAX_NEIGHBORS - num_used; + + PRINTF("NBR-POLICY: Free: %d, Children: %d, Parents: %d Routes: %d\n", + num_free, num_children, num_parents, uip_ds6_route_num_routes()); +} +/*---------------------------------------------------------------------------*/ +/* Called whenever we get a unicast DIS - e.g. someone that already + have this node in its table - since it is a unicast */ +const linkaddr_t * +find_removable_dis(uip_ipaddr_t *from) +{ + + update_nbr(); + if(num_free > 0) { + /* there are free entries (e.g. unsused by RPL and ND6) but since it is + used by other modules we can not pick these entries for removal. */ + PRINTF("Num-free > 0 = %d - Other for RPL/ND6 unused NBR entry exists .", + num_free); + } + if(num_children < MAX_CHILDREN) { + return worst_rank_nbr; + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +const linkaddr_t * +find_removable_dio(uip_ipaddr_t *from, rpl_dio_t *dio) +{ + rpl_instance_t *instance; + + update_nbr(); + + instance = rpl_get_instance(dio->instance_id); + if(instance == NULL || instance->current_dag == NULL) { + PRINTF("Did not find instance id: %d\n", dio->instance_id); + return NULL; + } + + /* Add the new neighbor only if it is better than the worst parent. */ + if(dio->rank + instance->min_hoprankinc < worst_rank - instance->min_hoprankinc / 2) { + /* Found *great* neighbor - add! */ + PRINTF("Found better neighbor %d < %d - add to cache...\n", + rank, worst_rank); + + return worst_rank_nbr; + } + + PRINTF("Found worse neighbor with new %d and old %d - NOT add to cache.\n", + rank, worst_rank); + return NULL; +} +/*---------------------------------------------------------------------------*/ +const linkaddr_t * +find_removable_dao(uip_ipaddr_t *from, rpl_instance_t *instance) +{ + int max = MAX_CHILDREN; + update_nbr(); + + if(instance != NULL) { + /* No need to reserve space for parents for RPL ROOT */ + if(instance->current_dag->rank == ROOT_RANK(instance)) { + max = NBR_TABLE_MAX_NEIGHBORS; + } + } + + /* Check if this DAO sender is not yet neighbor and there is already too + many children. */ + if(num_children >= max) { + PRINTF("Can not add another child - already at max.\n"); + return NULL; + } + /* remove the worst ranked nbr */ + return worst_rank_nbr; +} +/*---------------------------------------------------------------------------*/ +const linkaddr_t * +rpl_nbr_policy_find_removable(nbr_table_reason_t reason,void * data) +{ + /* When we get the DIO/DAO/DIS we know that UIP contains the + incoming packet */ + switch(reason) { + case NBR_TABLE_REASON_RPL_DIO: + return find_removable_dio(&UIP_IP_BUF->srcipaddr, data); + case NBR_TABLE_REASON_RPL_DAO: + return find_removable_dao(&UIP_IP_BUF->srcipaddr, data); + case NBR_TABLE_REASON_RPL_DIS: + return find_removable_dis(&UIP_IP_BUF->srcipaddr); + default: + return NULL; + } +} +/*---------------------------------------------------------------------------*/ +/** @}*/ diff --git a/core/net/rpl/rpl-ns.c b/core/net/rpl/rpl-ns.c new file mode 100644 index 000000000..68969cef4 --- /dev/null +++ b/core/net/rpl/rpl-ns.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2016, Inria. + * 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 + * RPL non-storing mode specific functions. Includes support for + * source routing. + * + * \author Simon Duquennoy + */ + +#include "net/rpl/rpl-conf.h" + +#include "net/ip/uip.h" +#include "net/ip/tcpip.h" +#include "net/ipv6/uip-ds6.h" +#include "net/ipv6/uip-icmp6.h" +#include "net/rpl/rpl-private.h" +#include "net/rpl/rpl-ns.h" +#include "lib/list.h" +#include "lib/memb.h" + +#if RPL_WITH_NON_STORING + +#define DEBUG DEBUG_NONE +#include "net/ip/uip-debug.h" + +#include +#include + +/* Total number of nodes */ +static int num_nodes; + +/* Every known node in the network */ +LIST(nodelist); +MEMB(nodememb, rpl_ns_node_t, RPL_NS_LINK_NUM); + +/*---------------------------------------------------------------------------*/ +int +rpl_ns_num_nodes(void) +{ + return num_nodes; +} +/*---------------------------------------------------------------------------*/ +static int +node_matches_address(const rpl_dag_t *dag, const rpl_ns_node_t *node, const uip_ipaddr_t *addr) +{ + return addr != NULL + && node != NULL + && dag != NULL + && dag == node->dag + && !memcmp(addr, &node->dag->dag_id, 8) + && !memcmp(((const unsigned char *)addr) + 8, node->link_identifier, 8); +} +/*---------------------------------------------------------------------------*/ +rpl_ns_node_t * +rpl_ns_get_node(const rpl_dag_t *dag, const uip_ipaddr_t *addr) +{ + rpl_ns_node_t *l; + for(l = list_head(nodelist); l != NULL; l = list_item_next(l)) { + /* Compare prefix and node identifier */ + if(node_matches_address(dag, l, addr)) { + return l; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +int +rpl_ns_is_node_reachable(const rpl_dag_t *dag, const uip_ipaddr_t *addr) +{ + int max_depth = RPL_NS_LINK_NUM; + rpl_ns_node_t *node = rpl_ns_get_node(dag, addr); + rpl_ns_node_t *root_node = rpl_ns_get_node(dag, dag != NULL ? &dag->dag_id : NULL); + while(node != NULL && node != root_node && max_depth > 0) { + node = node->parent; + max_depth--; + } + return node != NULL && node == root_node; +} +/*---------------------------------------------------------------------------*/ +void +rpl_ns_expire_parent(rpl_dag_t *dag, const uip_ipaddr_t *child, const uip_ipaddr_t *parent) +{ + rpl_ns_node_t *l = rpl_ns_get_node(dag, child); + /* Check if parent matches */ + if(l != NULL && node_matches_address(dag, l->parent, parent)) { + l->lifetime = RPL_NOPATH_REMOVAL_DELAY; + } +} +/*---------------------------------------------------------------------------*/ +rpl_ns_node_t * +rpl_ns_update_node(rpl_dag_t *dag, const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime) +{ + rpl_ns_node_t *child_node = rpl_ns_get_node(dag, child); + rpl_ns_node_t *parent_node = rpl_ns_get_node(dag, parent); + rpl_ns_node_t *old_parent_node; + + if(parent != NULL) { + /* No node for the parent, add one with infinite lifetime */ + if(parent_node == NULL) { + parent_node = rpl_ns_update_node(dag, parent, NULL, 0xffffffff); + if(parent_node == NULL) { + return NULL; + } + } + } + + /* No node for this child, add one */ + if(child_node == NULL) { + child_node = memb_alloc(&nodememb); + /* No space left, abort */ + if(child_node == NULL) { + return NULL; + } + child_node->parent = NULL; + list_add(nodelist, child_node); + num_nodes++; + } + + /* Initialize node */ + child_node->dag = dag; + child_node->lifetime = lifetime; + memcpy(child_node->link_identifier, ((const unsigned char *)child) + 8, 8); + + /* Is the node reachable before the update? */ + if(rpl_ns_is_node_reachable(dag, child)) { + old_parent_node = child_node->parent; + /* Update node */ + child_node->parent = parent_node; + /* Has the node become unreachable? May happen if we create a loop. */ + if(!rpl_ns_is_node_reachable(dag, child)) { + /* The new parent makes the node unreachable, restore old parent. + * We will take the update next time, with chances we know more of + * the topology and the loop is gone. */ + child_node->parent = old_parent_node; + } + } else { + child_node->parent = parent_node; + } + + return child_node; +} +/*---------------------------------------------------------------------------*/ +void +rpl_ns_init(void) +{ + num_nodes = 0; + memb_init(&nodememb); + list_init(nodelist); +} +/*---------------------------------------------------------------------------*/ +rpl_ns_node_t * +rpl_ns_node_head(void) +{ + return list_head(nodelist); +} +/*---------------------------------------------------------------------------*/ +rpl_ns_node_t * +rpl_ns_node_next(rpl_ns_node_t *item) +{ + return list_item_next(item); +} +/*---------------------------------------------------------------------------*/ +void +rpl_ns_get_node_global_addr(uip_ipaddr_t *addr, rpl_ns_node_t *node) +{ + if(addr != NULL && node != NULL && node->dag != NULL) { + memcpy(addr, &node->dag->dag_id, 8); + memcpy(((unsigned char *)addr) + 8, &node->link_identifier, 8); + } +} +/*---------------------------------------------------------------------------*/ +void +rpl_ns_periodic(void) +{ + rpl_ns_node_t *l; + /* First pass, decrement lifetime for all nodes with non-infinite lifetime */ + for(l = list_head(nodelist); l != NULL; l = list_item_next(l)) { + /* Don't touch infinite lifetime nodes */ + if(l->lifetime != 0xffffffff && l->lifetime > 0) { + l->lifetime--; + } + } + /* Second pass, for all expire nodes, deallocate them iff no child points to them */ + for(l = list_head(nodelist); l != NULL; l = list_item_next(l)) { + if(l->lifetime == 0) { + rpl_ns_node_t *l2; + for(l2 = list_head(nodelist); l2 != NULL; l2 = list_item_next(l2)) { + if(l2->parent == l) { + break; + } + } + /* No child found, deallocate node */ + list_remove(nodelist, l); + memb_free(&nodememb, l); + num_nodes--; + } + } +} + +#endif /* RPL_WITH_NON_STORING */ diff --git a/core/net/rpl/rpl-ns.h b/core/net/rpl/rpl-ns.h new file mode 100644 index 000000000..66f911f77 --- /dev/null +++ b/core/net/rpl/rpl-ns.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, Inria. + * 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 + * RPL non-storing mode specific functions. Includes support for + * source routing. + * + * \author Simon Duquennoy + */ + + +#ifndef RPL_NS_H +#define RPL_NS_H + +#include "rpl-conf.h" + +#ifdef RPL_NS_CONF_LINK_NUM +#define RPL_NS_LINK_NUM RPL_NS_CONF_LINK_NUM +#else /* RPL_NS_CONF_LINK_NUM */ +#define RPL_NS_LINK_NUM 32 +#endif /* RPL_NS_CONF_LINK_NUM */ + +typedef struct rpl_ns_node { + struct rpl_ns_node *next; + uint32_t lifetime; + rpl_dag_t *dag; + /* Store only IPv6 link identifiers as all nodes in the DAG share the same prefix */ + unsigned char link_identifier[8]; + struct rpl_ns_node *parent; +} rpl_ns_node_t; + +int rpl_ns_num_nodes(void); +void rpl_ns_expire_parent(rpl_dag_t *dag, const uip_ipaddr_t *child, const uip_ipaddr_t *parent); +rpl_ns_node_t *rpl_ns_update_node(rpl_dag_t *dag, const uip_ipaddr_t *child, const uip_ipaddr_t *parent, uint32_t lifetime); +void rpl_ns_init(void); +rpl_ns_node_t *rpl_ns_node_head(void); +rpl_ns_node_t *rpl_ns_node_next(rpl_ns_node_t *item); +rpl_ns_node_t *rpl_ns_get_node(const rpl_dag_t *dag, const uip_ipaddr_t *addr); +int rpl_ns_is_node_reachable(const rpl_dag_t *dag, const uip_ipaddr_t *addr); +void rpl_ns_get_node_global_addr(uip_ipaddr_t *addr, rpl_ns_node_t *node); +void rpl_ns_periodic(); + +#endif /* RPL_NS_H */ diff --git a/core/net/rpl/rpl-of0.c b/core/net/rpl/rpl-of0.c index ca73169fc..d0bfd1296 100644 --- a/core/net/rpl/rpl-of0.c +++ b/core/net/rpl/rpl-of0.c @@ -27,11 +27,12 @@ * SUCH DAMAGE. * * This file is part of the Contiki operating system. + * */ /** * \file - * An implementation of RPL's objective function 0. + * An implementation of RPL's objective function 0, RFC6552 * * \author Joakim Eriksson , Nicolas Tsiftes */ @@ -41,133 +42,197 @@ * @{ */ +#include "net/rpl/rpl.h" #include "net/rpl/rpl-private.h" +#include "net/nbr-table.h" +#include "net/link-stats.h" #define DEBUG DEBUG_NONE #include "net/ip/uip-debug.h" -static void reset(rpl_dag_t *); -static rpl_parent_t *best_parent(rpl_parent_t *, rpl_parent_t *); -static rpl_dag_t *best_dag(rpl_dag_t *, rpl_dag_t *); -static rpl_rank_t calculate_rank(rpl_parent_t *, rpl_rank_t); -static void update_metric_container(rpl_instance_t *); +/* Constants from RFC6552. We use the default values. */ +#define RANK_STRETCH 0 /* Must be in the range [0;5] */ +#define RANK_FACTOR 1 /* Must be in the range [1;4] */ -rpl_of_t rpl_of0 = { - reset, - NULL, - best_parent, - best_dag, - calculate_rank, - update_metric_container, - 0 -}; +#define MIN_STEP_OF_RANK 1 +#define MAX_STEP_OF_RANK 9 -#define DEFAULT_RANK_INCREMENT RPL_MIN_HOPRANKINC +/* OF0 computes rank increase as follows: + * rank_increase = (RANK_FACTOR * STEP_OF_RANK + RANK_STRETCH) * min_hop_rank_increase + * STEP_OF_RANK is an implementation-specific scalar value in the range [1;9]. + * RFC6552 provides a default value of 3 but recommends to use a dynamic link metric + * such as ETX. + * */ -#define MIN_DIFFERENCE (RPL_MIN_HOPRANKINC + RPL_MIN_HOPRANKINC / 2) +#define RPL_OF0_FIXED_SR 0 +#define RPL_OF0_ETX_BASED_SR 1 +/* Select RPL_OF0_FIXED_SR or RPL_OF0_ETX_BASED_SR */ +#ifdef RPL_OF0_CONF_SR +#define RPL_OF0_SR RPL_OF0_CONF_SR +#else /* RPL_OF0_CONF_SR */ +#define RPL_OF0_SR RPL_OF0_ETX_BASED_SR +#endif /* RPL_OF0_CONF_SR */ +#if RPL_OF0_FIXED_SR +#define STEP_OF_RANK(p) (3) +#endif /* RPL_OF0_FIXED_SR */ + +#if RPL_OF0_ETX_BASED_SR +/* Numbers suggested by P. Thubert for in the 6TiSCH WG. Anything that maps ETX to + * a step between 1 and 9 works. */ +#define STEP_OF_RANK(p) (((3 * parent_link_metric(p)) / LINK_STATS_ETX_DIVISOR) - 2) +#endif /* RPL_OF0_ETX_BASED_SR */ + +/*---------------------------------------------------------------------------*/ static void reset(rpl_dag_t *dag) { - PRINTF("RPL: Resetting OF0\n"); + PRINTF("RPL: Reset OF0\n"); } - -static rpl_rank_t -calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank) +/*---------------------------------------------------------------------------*/ +#if RPL_WITH_DAO_ACK +static void +dao_ack_callback(rpl_parent_t *p, int status) { - rpl_rank_t increment; - if(base_rank == 0) { - if(p == NULL) { - return INFINITE_RANK; - } - base_rank = p->rank; + if(status == RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT) { + return; } - - increment = p != NULL ? - p->dag->instance->min_hoprankinc : - DEFAULT_RANK_INCREMENT; - - if((rpl_rank_t)(base_rank + increment) < base_rank) { - PRINTF("RPL: OF0 rank %d incremented to infinite rank due to wrapping\n", - base_rank); + /* here we need to handle failed DAO's and other stuff */ + PRINTF("RPL: OF0 - DAO ACK received with status: %d\n", status); + if(status >= RPL_DAO_ACK_UNABLE_TO_ACCEPT) { + /* punish the ETX as if this was 10 packets lost */ + link_stats_packet_sent(rpl_get_parent_lladdr(p), MAC_TX_OK, 10); + } else if(status == RPL_DAO_ACK_TIMEOUT) { /* timeout = no ack */ + /* punish the total lack of ACK with a similar punishment */ + link_stats_packet_sent(rpl_get_parent_lladdr(p), MAC_TX_OK, 10); + } +} +#endif /* RPL_WITH_DAO_ACK */ +/*---------------------------------------------------------------------------*/ +static uint16_t +parent_link_metric(rpl_parent_t *p) +{ + /* OF0 operates without metric container; the only metric we have is ETX */ + const struct link_stats *stats = rpl_get_parent_link_stats(p); + return stats != NULL ? stats->etx : 0xffff; +} +/*---------------------------------------------------------------------------*/ +static uint16_t +parent_rank_increase(rpl_parent_t *p) +{ + uint16_t min_hoprankinc; + if(p == NULL || p->dag == NULL || p->dag->instance == NULL) { return INFINITE_RANK; } - return base_rank + increment; - + min_hoprankinc = p->dag->instance->min_hoprankinc; + return (RANK_FACTOR * STEP_OF_RANK(p) + RANK_STRETCH) * min_hoprankinc; } - -static rpl_dag_t * -best_dag(rpl_dag_t *d1, rpl_dag_t *d2) +/*---------------------------------------------------------------------------*/ +static uint16_t +parent_path_cost(rpl_parent_t *p) { - if(d1->grounded) { - if (!d2->grounded) { - return d1; - } - } else if(d2->grounded) { - return d2; + if(p == NULL) { + return 0xffff; } - - if(d1->preference < d2->preference) { - return d2; + /* path cost upper bound: 0xffff */ + return MIN((uint32_t)p->rank + parent_link_metric(p), 0xffff); +} +/*---------------------------------------------------------------------------*/ +static rpl_rank_t +rank_via_parent(rpl_parent_t *p) +{ + if(p == NULL) { + return INFINITE_RANK; } else { - if(d1->preference > d2->preference) { - return d1; - } - } - - if(d2->rank < d1->rank) { - return d2; - } else { - return d1; + return MIN((uint32_t)p->rank + parent_rank_increase(p), INFINITE_RANK); } } - +/*---------------------------------------------------------------------------*/ +static int +parent_is_acceptable(rpl_parent_t *p) +{ + return STEP_OF_RANK(p) >= MIN_STEP_OF_RANK + && STEP_OF_RANK(p) <= MAX_STEP_OF_RANK; +} +/*---------------------------------------------------------------------------*/ +static int +parent_has_usable_link(rpl_parent_t *p) +{ + return parent_is_acceptable(p); +} +/*---------------------------------------------------------------------------*/ static rpl_parent_t * best_parent(rpl_parent_t *p1, rpl_parent_t *p2) { - rpl_rank_t r1, r2; - rpl_dag_t *dag; - uip_ds6_nbr_t *nbr1, *nbr2; - nbr1 = rpl_get_nbr(p1); - nbr2 = rpl_get_nbr(p2); + rpl_dag_t *dag; + uint16_t p1_cost; + uint16_t p2_cost; + int p1_is_acceptable; + int p2_is_acceptable; - dag = (rpl_dag_t *)p1->dag; /* Both parents must be in the same DAG. */ + p1_is_acceptable = p1 != NULL && parent_is_acceptable(p1); + p2_is_acceptable = p2 != NULL && parent_is_acceptable(p2); - if(nbr1 == NULL || nbr2 == NULL) { - return dag->preferred_parent; + if(!p1_is_acceptable) { + return p2_is_acceptable ? p2 : NULL; + } + if(!p2_is_acceptable) { + return p1_is_acceptable ? p1 : NULL; } - PRINTF("RPL: Comparing parent "); - PRINT6ADDR(rpl_get_parent_ipaddr(p1)); - PRINTF(" (confidence %d, rank %d) with parent ", - nbr1->link_metric, p1->rank); - PRINT6ADDR(rpl_get_parent_ipaddr(p2)); - PRINTF(" (confidence %d, rank %d)\n", - nbr2->link_metric, p2->rank); + dag = p1->dag; /* Both parents are in the same DAG. */ + p1_cost = parent_path_cost(p1); + p2_cost = parent_path_cost(p2); - - r1 = DAG_RANK(p1->rank, p1->dag->instance) * RPL_MIN_HOPRANKINC + - nbr1->link_metric; - r2 = DAG_RANK(p2->rank, p1->dag->instance) * RPL_MIN_HOPRANKINC + - nbr2->link_metric; - /* Compare two parents by looking both and their rank and at the ETX - for that parent. We choose the parent that has the most - favourable combination. */ - - if(r1 < r2 + MIN_DIFFERENCE && - r1 > r2 - MIN_DIFFERENCE) { - return dag->preferred_parent; - } else if(r1 < r2) { - return p1; + /* Paths costs coarse-grained (multiple of min_hoprankinc), we operate without hysteresis */ + if(p1_cost != p2_cost) { + /* Pick parent with lowest path cost */ + return p1_cost < p2_cost ? p1 : p2; } else { - return p2; + /* We have a tie! */ + /* Stik to current preferred parent if possible */ + if(p1 == dag->preferred_parent || p2 == dag->preferred_parent) { + return dag->preferred_parent; + } + /* None of the nodes is the current preferred parent, + * choose parent with best link metric */ + return parent_link_metric(p1) < parent_link_metric(p2) ? p1 : p2; } } +/*---------------------------------------------------------------------------*/ +static rpl_dag_t * +best_dag(rpl_dag_t *d1, rpl_dag_t *d2) +{ + if(d1->grounded != d2->grounded) { + return d1->grounded ? d1 : d2; + } + if(d1->preference != d2->preference) { + return d1->preference > d2->preference ? d1 : d2; + } + + return d1->rank < d2->rank ? d1 : d2; +} +/*---------------------------------------------------------------------------*/ static void update_metric_container(rpl_instance_t *instance) { instance->mc.type = RPL_DAG_MC_NONE; } +/*---------------------------------------------------------------------------*/ +rpl_of_t rpl_of0 = { + reset, +#if RPL_WITH_DAO_ACK + dao_ack_callback, +#endif + parent_link_metric, + parent_has_usable_link, + parent_path_cost, + rank_via_parent, + best_parent, + best_dag, + update_metric_container, + RPL_OCP_OF0 +}; /** @}*/ diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index e1d95697b..bb7af2a04 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -44,6 +44,8 @@ #include "sys/clock.h" #include "sys/ctimer.h" #include "net/ipv6/uip-ds6.h" +#include "net/ipv6/uip-ds6-route.h" +#include "net/rpl/rpl-ns.h" #include "net/ipv6/multicast/uip-mcast6.h" /*---------------------------------------------------------------------------*/ @@ -90,10 +92,21 @@ #define RPL_DAO_K_FLAG 0x80 /* DAO ACK requested */ #define RPL_DAO_D_FLAG 0x40 /* DODAG ID present */ + +#define RPL_DAO_ACK_UNCONDITIONAL_ACCEPT 0 +#define RPL_DAO_ACK_ACCEPT 1 /* 1 - 127 is OK but not good */ +#define RPL_DAO_ACK_UNABLE_TO_ACCEPT 128 /* >127 is fail */ +#define RPL_DAO_ACK_UNABLE_TO_ADD_ROUTE_AT_ROOT 255 /* root can not accept */ + +#define RPL_DAO_ACK_TIMEOUT -1 + /*---------------------------------------------------------------------------*/ /* RPL IPv6 extension header option. */ #define RPL_HDR_OPT_LEN 4 #define RPL_HOP_BY_HOP_LEN (RPL_HDR_OPT_LEN + 2 + 2) +#define RPL_RH_LEN 4 +#define RPL_SRH_LEN 4 +#define RPL_RH_TYPE_SRH 3 #define RPL_HDR_OPT_DOWN 0x80 #define RPL_HDR_OPT_DOWN_SHIFT 7 #define RPL_HDR_OPT_RANK_ERR 0x40 @@ -117,6 +130,18 @@ #define RPL_NOPATH_REMOVAL_DELAY 60 #endif /* RPL_CONF_NOPATH_REMOVAL_DELAY */ +#ifdef RPL_CONF_DAO_MAX_RETRANSMISSIONS +#define RPL_DAO_MAX_RETRANSMISSIONS RPL_CONF_DAO_MAX_RETRANSMISSIONS +#else +#define RPL_DAO_MAX_RETRANSMISSIONS 5 +#endif /* RPL_CONF_DAO_MAX_RETRANSMISSIONS */ + +#ifdef RPL_CONF_DAO_RETRANSMISSION_TIMEOUT +#define RPL_DAO_RETRANSMISSION_TIMEOUT RPL_CONF_DAO_RETRANSMISSION_TIMEOUT +#else +#define RPL_DAO_RETRANSMISSION_TIMEOUT (5 * CLOCK_SECOND) +#endif /* RPL_CONF_DAO_RETRANSMISSION_TIMEOUT */ + /* Special value indicating immediate removal. */ #define RPL_ZERO_LIFETIME 0 @@ -124,11 +149,28 @@ ((unsigned long)(instance)->lifetime_unit * (lifetime)) #ifndef RPL_CONF_MIN_HOPRANKINC +/* RFC6550 defines the default MIN_HOPRANKINC as 256. + * However, we use MRHOF as a default Objective Function (RFC6719), + * which recommends setting MIN_HOPRANKINC with care, in particular + * when used with ETX as a metric. ETX is computed as a fixed point + * real with a divisor of 128 (RFC6719, RFC6551). We choose to also + * use 128 for RPL_MIN_HOPRANKINC, resulting in a rank equal to the + * ETX path cost. Larger values may also be desirable, as discussed + * in section 6.1 of RFC6719. */ +#if RPL_OF_OCP == RPL_OCP_MRHOF +#define RPL_MIN_HOPRANKINC 128 +#else /* RPL_OF_OCP == RPL_OCP_MRHOF */ #define RPL_MIN_HOPRANKINC 256 -#else +#endif /* RPL_OF_OCP == RPL_OCP_MRHOF */ +#else /* RPL_CONF_MIN_HOPRANKINC */ #define RPL_MIN_HOPRANKINC RPL_CONF_MIN_HOPRANKINC -#endif +#endif /* RPL_CONF_MIN_HOPRANKINC */ + +#ifndef RPL_CONF_MAX_RANKINC #define RPL_MAX_RANKINC (7 * RPL_MIN_HOPRANKINC) +#else /* RPL_CONF_MAX_RANKINC */ +#define RPL_MAX_RANKINC RPL_CONF_MAX_RANKINC +#endif /* RPL_CONF_MAX_RANKINC */ #define DAG_RANK(fixpt_rank, instance) \ ((fixpt_rank) / (instance)->min_hoprankinc) @@ -157,18 +199,56 @@ #define RPL_MOP_STORING_NO_MULTICAST 2 #define RPL_MOP_STORING_MULTICAST 3 +/* RPL Mode of operation */ #ifdef RPL_CONF_MOP #define RPL_MOP_DEFAULT RPL_CONF_MOP #else /* RPL_CONF_MOP */ -#if RPL_CONF_MULTICAST +#if RPL_WITH_MULTICAST #define RPL_MOP_DEFAULT RPL_MOP_STORING_MULTICAST #else #define RPL_MOP_DEFAULT RPL_MOP_STORING_NO_MULTICAST -#endif /* UIP_IPV6_MULTICAST_RPL */ +#endif /* RPL_WITH_MULTICAST */ #endif /* RPL_CONF_MOP */ +/* + * Embed support for storing mode + */ +#ifdef RPL_CONF_WITH_STORING +#define RPL_WITH_STORING RPL_CONF_WITH_STORING +#else /* RPL_CONF_WITH_STORING */ +/* By default: embed support for non-storing if and only if the configured MOP is not non-storing */ +#define RPL_WITH_STORING (RPL_MOP_DEFAULT != RPL_MOP_NON_STORING) +#endif /* RPL_CONF_WITH_STORING */ + +/* + * Embed support for non-storing mode + */ +#ifdef RPL_CONF_WITH_NON_STORING +#define RPL_WITH_NON_STORING RPL_CONF_WITH_NON_STORING +#else /* RPL_CONF_WITH_NON_STORING */ +/* By default: embed support for non-storing if and only if the configured MOP is non-storing */ +#define RPL_WITH_NON_STORING (RPL_MOP_DEFAULT == RPL_MOP_NON_STORING) +#endif /* RPL_CONF_WITH_NON_STORING */ + +#if RPL_WITH_STORING && (UIP_DS6_ROUTE_NB == 0) +#error "RPL with storing mode included but #routes == 0. Set UIP_CONF_MAX_ROUTES accordingly." +#if !RPL_WITH_NON_STORING && (RPL_NS_LINK_NUM > 0) +#error "You might also want to set RPL_NS_CONF_LINK_NUM to 0." +#endif +#endif + +#if RPL_WITH_NON_STORING && (RPL_NS_LINK_NUM == 0) +#error "RPL with non-storing mode included but #links == 0. Set RPL_NS_CONF_LINK_NUM accordingly." +#if !RPL_WITH_STORING && (UIP_DS6_ROUTE_NB > 0) +#error "You might also want to set UIP_CONF_MAX_ROUTES to 0." +#endif +#endif + +#define RPL_IS_STORING(instance) (RPL_WITH_STORING && ((instance) != NULL) && ((instance)->mop > RPL_MOP_NON_STORING)) +#define RPL_IS_NON_STORING(instance) (RPL_WITH_NON_STORING && ((instance) != NULL) && ((instance)->mop == RPL_MOP_NON_STORING)) + /* Emit a pre-processor error if the user configured multicast with bad MOP */ -#if RPL_CONF_MULTICAST && (RPL_MOP_DEFAULT != RPL_MOP_STORING_MULTICAST) +#if RPL_WITH_MULTICAST && (RPL_MOP_DEFAULT != RPL_MOP_STORING_MULTICAST) #error "RPL Multicast requires RPL_MOP_DEFAULT==3. Check contiki-conf.h" #endif @@ -179,13 +259,6 @@ #define RPL_MCAST_LIFETIME 3 #endif -/* - * The ETX in the metric container is expressed as a fixed-point value - * whose integer part can be obtained by dividing the value by - * RPL_DAG_MC_ETX_DIVISOR. - */ -#define RPL_DAG_MC_ETX_DIVISOR 256 - /* DIS related */ #define RPL_DIS_SEND 1 @@ -250,6 +323,8 @@ typedef struct rpl_stats rpl_stats_t; extern rpl_stats_t rpl_stats; #endif + + /*---------------------------------------------------------------------------*/ /* RPL macros. */ @@ -268,8 +343,10 @@ void dis_output(uip_ipaddr_t *addr); void dio_output(rpl_instance_t *, uip_ipaddr_t *uc_addr); void dao_output(rpl_parent_t *, uint8_t lifetime); void dao_output_target(rpl_parent_t *, uip_ipaddr_t *, uint8_t lifetime); -void dao_ack_output(rpl_instance_t *, uip_ipaddr_t *, uint8_t); +void dao_ack_output(rpl_instance_t *, uip_ipaddr_t *, uint8_t, uint8_t); void rpl_icmp6_register_handlers(void); +uip_ds6_nbr_t *rpl_icmp6_update_nbr_table(uip_ipaddr_t *from, + nbr_table_reason_t r, void *data); /* RPL logic functions. */ void rpl_join_dag(uip_ipaddr_t *from, rpl_dio_t *dio); diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index f8c913b61..05384fc14 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -43,6 +43,8 @@ #include "contiki-conf.h" #include "net/rpl/rpl-private.h" +#include "net/rpl/rpl-ns.h" +#include "net/link-stats.h" #include "net/ipv6/multicast/uip-mcast6.h" #include "lib/random.h" #include "sys/ctimer.h" @@ -55,6 +57,14 @@ void RPL_CALLBACK_NEW_DIO_INTERVAL(uint8_t dio_interval); #endif /* RPL_CALLBACK_NEW_DIO_INTERVAL */ +#ifdef RPL_PROBING_SELECT_FUNC +rpl_parent_t *RPL_PROBING_SELECT_FUNC(rpl_dag_t *dag); +#endif /* RPL_PROBING_SELECT_FUNC */ + +#ifdef RPL_PROBING_DELAY_FUNC +clock_time_t RPL_PROBING_DELAY_FUNC(rpl_dag_t *dag); +#endif /* RPL_PROBING_DELAY_FUNC */ + /*---------------------------------------------------------------------------*/ static struct ctimer periodic_timer; @@ -71,14 +81,23 @@ static uint8_t dio_send_ok; static void handle_periodic_timer(void *ptr) { + rpl_dag_t *dag = rpl_get_any_dag(); + rpl_purge_dags(); - rpl_purge_routes(); + if(dag != NULL) { + if(RPL_IS_STORING(dag->instance)) { + rpl_purge_routes(); + } + if(RPL_IS_NON_STORING(dag->instance)) { + rpl_ns_periodic(); + } + } rpl_recalculate_ranks(); /* handle DIS */ #if RPL_DIS_SEND next_dis++; - if(rpl_get_any_dag() == NULL && next_dis >= RPL_DIS_INTERVAL) { + if(dag == NULL && next_dis >= RPL_DIS_INTERVAL) { next_dis = 0; dis_output(NULL); } @@ -161,7 +180,7 @@ handle_dio_timer(void *ptr) #endif /* RPL_CONF_STATS */ dio_output(instance, NULL); } else { - PRINTF("RPL: Supressing DIO transmission (%d >= %d)\n", + PRINTF("RPL: Suppressing DIO transmission (%d >= %d)\n", instance->dio_counter, instance->dio_redundancy); } instance->dio_send = 0; @@ -224,6 +243,8 @@ set_dao_lifetime_timer(rpl_instance_t *instance) expiration_time = (clock_time_t)instance->default_lifetime * (clock_time_t)instance->lifetime_unit * CLOCK_SECOND / 2; + /* make the time for the re registration be betwen 1/2 - 3/4 of lifetime */ + expiration_time = expiration_time + (random_rand() % (expiration_time / 2)); PRINTF("RPL: Scheduling DAO lifetime timer %u ticks in the future\n", (unsigned)expiration_time); ctimer_set(&instance->dao_lifetime_timer, expiration_time, @@ -235,7 +256,7 @@ static void handle_dao_timer(void *ptr) { rpl_instance_t *instance; -#if RPL_CONF_MULTICAST +#if RPL_WITH_MULTICAST uip_mcast6_route_t *mcast_route; uint8_t i; #endif @@ -254,7 +275,7 @@ handle_dao_timer(void *ptr) /* Set the route lifetime to the default value. */ dao_output(instance->current_dag->preferred_parent, instance->default_lifetime); -#if RPL_CONF_MULTICAST +#if RPL_WITH_MULTICAST /* Send DAOs for multicast prefixes only if the instance is in MOP 3 */ if(instance->mop == RPL_MOP_STORING_MULTICAST) { /* Send a DAO for own multicast addresses */ @@ -356,42 +377,57 @@ rpl_schedule_unicast_dio_immediately(rpl_instance_t *instance) } /*---------------------------------------------------------------------------*/ #if RPL_WITH_PROBING -static rpl_parent_t * +clock_time_t +get_probing_delay(rpl_dag_t *dag) +{ + if(dag != NULL && dag->instance != NULL + && dag->instance->urgent_probing_target != NULL) { + /* Urgent probing needed (to find out if a neighbor may become preferred parent) */ + return random_rand() % (CLOCK_SECOND * 10); + } else { + /* Else, use normal probing interval */ + return ((RPL_PROBING_INTERVAL) / 2) + random_rand() % (RPL_PROBING_INTERVAL); + } +} +/*---------------------------------------------------------------------------*/ +rpl_parent_t * get_probing_target(rpl_dag_t *dag) { - /* Returns the next probing target. The current implementation probes the current - * preferred parent if we have not updated its link for RPL_PROBING_EXPIRATION_TIME. + /* Returns the next probing target. The current implementation probes the urgent + * probing target if any, or the preferred parent if its link statistics need refresh. * Otherwise, it picks at random between: - * (1) selecting the best parent not updated for RPL_PROBING_EXPIRATION_TIME + * (1) selecting the best parent with non-fresh link statistics * (2) selecting the least recently updated parent */ rpl_parent_t *p; rpl_parent_t *probing_target = NULL; rpl_rank_t probing_target_rank = INFINITE_RANK; - /* min_last_tx is the clock time RPL_PROBING_EXPIRATION_TIME in the past */ - clock_time_t min_last_tx = clock_time(); - min_last_tx = min_last_tx > 2 * RPL_PROBING_EXPIRATION_TIME - ? min_last_tx - RPL_PROBING_EXPIRATION_TIME : 1; + clock_time_t probing_target_age = 0; + clock_time_t clock_now = clock_time(); if(dag == NULL || - dag->instance == NULL || - dag->preferred_parent == NULL) { + dag->instance == NULL) { return NULL; } - /* Our preferred parent needs probing */ - if(dag->preferred_parent->last_tx_time < min_last_tx) { - probing_target = dag->preferred_parent; + /* There is an urgent probing target */ + if(dag->instance->urgent_probing_target != NULL) { + return dag->instance->urgent_probing_target; } - /* With 50% probability: probe best parent not updated for RPL_PROBING_EXPIRATION_TIME */ - if(probing_target == NULL && (random_rand() % 2) == 0) { + /* The preferred parent needs probing */ + if(dag->preferred_parent != NULL && !rpl_parent_is_fresh(dag->preferred_parent)) { + return dag->preferred_parent; + } + + /* With 50% probability: probe best non-fresh parent */ + if(random_rand() % 2 == 0) { p = nbr_table_head(rpl_parents); while(p != NULL) { - if(p->dag == dag && p->last_tx_time < min_last_tx) { + if(p->dag == dag && !rpl_parent_is_fresh(p)) { /* p is in our dag and needs probing */ - rpl_rank_t p_rank = dag->instance->of->calculate_rank(p, 0); + rpl_rank_t p_rank = rpl_rank_via_parent(p); if(probing_target == NULL || p_rank < probing_target_rank) { probing_target = p; @@ -402,14 +438,16 @@ get_probing_target(rpl_dag_t *dag) } } - /* The default probing target is the least recently updated parent */ + /* If we still do not have a probing target: pick the least recently updated parent */ if(probing_target == NULL) { p = nbr_table_head(rpl_parents); while(p != NULL) { - if(p->dag == dag) { + const struct link_stats *stats =rpl_get_parent_link_stats(p); + if(p->dag == dag && stats != NULL) { if(probing_target == NULL - || p->last_tx_time < probing_target->last_tx_time) { + || clock_now - stats->last_tx_time > probing_target_age) { probing_target = p; + probing_target_age = clock_now - stats->last_tx_time; } } p = nbr_table_next(rpl_parents, p); @@ -428,11 +466,17 @@ handle_probing_timer(void *ptr) /* Perform probing */ if(target_ipaddr != NULL) { - PRINTF("RPL: probing %u ((last tx %u min ago))\n", - nbr_table_get_lladdr(rpl_parents, probing_target)->u8[7], - (unsigned)((clock_time() - probing_target->last_tx_time) / (60 * CLOCK_SECOND))); - /* Send probe (unicast DIO or DIS) */ + const struct link_stats *stats = rpl_get_parent_link_stats(probing_target); + (void)stats; + PRINTF("RPL: probing %u %s last tx %u min ago\n", + rpl_get_parent_lladdr(probing_target)->u8[7], + instance->urgent_probing_target != NULL ? "(urgent)" : "", + probing_target != NULL ? + (unsigned)((clock_time() - stats->last_tx_time) / (60 * CLOCK_SECOND)) : 0 + ); + /* Send probe, e.g. unicast DIO or DIS */ RPL_PROBING_SEND_FUNC(instance, target_ipaddr); + instance->urgent_probing_target = NULL; } /* Schedule next probing */ @@ -446,7 +490,7 @@ handle_probing_timer(void *ptr) void rpl_schedule_probing(rpl_instance_t *instance) { - ctimer_set(&instance->probing_timer, RPL_PROBING_DELAY_FUNC(), + ctimer_set(&instance->probing_timer, RPL_PROBING_DELAY_FUNC(instance->current_dag), handle_probing_timer, instance); } #endif /* RPL_WITH_PROBING */ diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index 82b11721a..92ea2b309 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -47,6 +47,7 @@ #include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-icmp6.h" #include "net/rpl/rpl-private.h" +#include "net/rpl/rpl-ns.h" #include "net/ipv6/multicast/uip-mcast6.h" #define DEBUG DEBUG_NONE @@ -113,7 +114,7 @@ rpl_purge_routes(void) uip_ds6_route_t *r; uip_ipaddr_t prefix; rpl_dag_t *dag; -#if RPL_CONF_MULTICAST +#if RPL_WITH_MULTICAST uip_mcast6_route_t *mcast_route; #endif @@ -158,7 +159,7 @@ rpl_purge_routes(void) } } -#if RPL_CONF_MULTICAST +#if RPL_WITH_MULTICAST mcast_route = uip_mcast6_route_list_head(); while(mcast_route != NULL) { @@ -177,7 +178,7 @@ void rpl_remove_routes(rpl_dag_t *dag) { uip_ds6_route_t *r; -#if RPL_CONF_MULTICAST +#if RPL_WITH_MULTICAST uip_mcast6_route_t *mcast_route; #endif @@ -192,7 +193,7 @@ rpl_remove_routes(rpl_dag_t *dag) } } -#if RPL_CONF_MULTICAST +#if RPL_WITH_MULTICAST mcast_route = uip_mcast6_route_list_head(); while(mcast_route != NULL) { @@ -215,12 +216,10 @@ rpl_remove_routes_by_nexthop(uip_ipaddr_t *nexthop, rpl_dag_t *dag) while(r != NULL) { if(uip_ipaddr_cmp(uip_ds6_route_nexthop(r), nexthop) && - r->state.dag == dag) { - uip_ds6_route_rm(r); - r = uip_ds6_route_head(); - } else { - r = uip_ds6_route_next(r); + r->state.dag == dag) { + r->state.lifetime = 0; } + r = uip_ds6_route_next(r); } ANNOTATE("#L %u 0\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]); } @@ -238,7 +237,8 @@ rpl_add_route(rpl_dag_t *dag, uip_ipaddr_t *prefix, int prefix_len, rep->state.dag = dag; rep->state.lifetime = RPL_LIFETIME(dag->instance, dag->instance->default_lifetime); - rep->state.learned_from = RPL_ROUTE_FROM_INTERNAL; + /* always clear state flags for the no-path received when adding/refreshing */ + RPL_ROUTE_CLEAR_NOPATH_RECEIVED(rep); PRINTF("RPL: Added a route to "); PRINT6ADDR(prefix); @@ -267,10 +267,6 @@ rpl_link_neighbor_callback(const linkaddr_t *addr, int status, int numtx) /* Trigger DAG rank recalculation. */ PRINTF("RPL: rpl_link_neighbor_callback triggering update\n"); parent->flags |= RPL_PARENT_FLAG_UPDATED; - if(instance->of->neighbor_link_callback != NULL) { - instance->of->neighbor_link_callback(parent, status, numtx); - parent->last_tx_time = clock_time(); - } } } } @@ -285,7 +281,11 @@ rpl_ipv6_neighbor_callback(uip_ds6_nbr_t *nbr) PRINTF("RPL: Neighbor state changed for "); PRINT6ADDR(&nbr->ipaddr); +#if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA PRINTF(", nscount=%u, state=%u\n", nbr->nscount, nbr->state); +#else /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA */ + PRINTF(", state=%u\n", nbr->state); +#endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA */ for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES; instance < end; ++instance) { if(instance->used == 1 ) { p = rpl_find_parent_any_dag(instance, &nbr->ipaddr); @@ -346,7 +346,9 @@ rpl_init(void) memset(&rpl_stats, 0, sizeof(rpl_stats)); #endif - RPL_OF.reset(NULL); +#if RPL_WITH_NON_STORING + rpl_ns_init(); +#endif /* RPL_WITH_NON_STORING */ } /*---------------------------------------------------------------------------*/ diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index c3d693b26..26ee71edc 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -49,8 +49,8 @@ typedef uint16_t rpl_rank_t; typedef uint16_t rpl_ocp_t; /*---------------------------------------------------------------------------*/ -/* DAG Metric Container Object Types, to be confirmed by IANA. */ -#define RPL_DAG_MC_NONE 0 /* Local identifier for empty MC */ +/* IANA Routing Metric/Constraint Type as defined in RFC6551 */ +#define RPL_DAG_MC_NONE 0 /* Local identifier for empty MC */ #define RPL_DAG_MC_NSA 1 /* Node State and Attributes */ #define RPL_DAG_MC_ENERGY 2 /* Node Energy */ #define RPL_DAG_MC_HOPCOUNT 3 /* Hop Count */ @@ -60,27 +60,31 @@ typedef uint16_t rpl_ocp_t; #define RPL_DAG_MC_ETX 7 /* Expected Transmission Count */ #define RPL_DAG_MC_LC 8 /* Link Color */ -/* DAG Metric Container flags. */ -#define RPL_DAG_MC_FLAG_P 0x8 -#define RPL_DAG_MC_FLAG_C 0x4 -#define RPL_DAG_MC_FLAG_O 0x2 -#define RPL_DAG_MC_FLAG_R 0x1 +/* IANA Routing Metric/Constraint Common Header Flag field as defined in RFC6551 (bit indexes) */ +#define RPL_DAG_MC_FLAG_P 5 +#define RPL_DAG_MC_FLAG_C 6 +#define RPL_DAG_MC_FLAG_O 7 +#define RPL_DAG_MC_FLAG_R 8 -/* DAG Metric Container aggregation mode. */ +/* IANA Routing Metric/Constraint Common Header A Field as defined in RFC6551 */ #define RPL_DAG_MC_AGGR_ADDITIVE 0 #define RPL_DAG_MC_AGGR_MAXIMUM 1 #define RPL_DAG_MC_AGGR_MINIMUM 2 #define RPL_DAG_MC_AGGR_MULTIPLICATIVE 3 -/* The bit index within the flags field of - the rpl_metric_object_energy structure. */ -#define RPL_DAG_MC_ENERGY_INCLUDED 3 -#define RPL_DAG_MC_ENERGY_TYPE 1 -#define RPL_DAG_MC_ENERGY_ESTIMATION 0 +/* The bit index within the flags field of the rpl_metric_object_energy structure. */ +#define RPL_DAG_MC_ENERGY_INCLUDED 3 +#define RPL_DAG_MC_ENERGY_TYPE 1 +#define RPL_DAG_MC_ENERGY_ESTIMATION 0 -#define RPL_DAG_MC_ENERGY_TYPE_MAINS 0 -#define RPL_DAG_MC_ENERGY_TYPE_BATTERY 1 -#define RPL_DAG_MC_ENERGY_TYPE_SCAVENGING 2 +/* IANA Node Type Field as defined in RFC6551 */ +#define RPL_DAG_MC_ENERGY_TYPE_MAINS 0 +#define RPL_DAG_MC_ENERGY_TYPE_BATTERY 1 +#define RPL_DAG_MC_ENERGY_TYPE_SCAVENGING 2 + +/* IANA Objective Code Point as defined in RFC6550 */ +#define RPL_OCP_OF0 0 +#define RPL_OCP_MRHOF 1 struct rpl_metric_object_energy { uint8_t flags; @@ -109,11 +113,10 @@ struct rpl_dag; struct rpl_parent { struct rpl_dag *dag; -#if RPL_DAG_MC != RPL_DAG_MC_NONE +#if RPL_WITH_MC rpl_metric_container_t mc; -#endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */ +#endif /* RPL_WITH_MC */ rpl_rank_t rank; - clock_time_t last_tx_time; uint8_t dtsn; uint8_t flags; }; @@ -155,11 +158,25 @@ typedef struct rpl_instance rpl_instance_t; * Resets the objective function state for a specific DAG. This function is * called when doing a global repair on the DAG. * - * neighbor_link_callback(parent, known, etx) + * parent_link_metric(parent) * - * Receives link-layer neighbor information. The parameter "known" is set - * either to 0 or 1. The "etx" parameter specifies the current - * ETX(estimated transmissions) for the neighbor. + * Returns the link metric of a parent + * + * parent_has_usable_link(parent) + * + * Returns 1 iff we have a usable link to this parent + * + * parent_path_cost(parent) + * + * Returns the path cost of a parent + * + * rank_via_parent(parent) + * + * Returns our rank if we select a given parent as preferred parent + * + * parent_is_acceptable + * + * Returns 1 if a parent is usable as preferred parent, 0 otherwise * * best_parent(parent1, parent2) * @@ -169,32 +186,34 @@ typedef struct rpl_instance rpl_instance_t; * * Compares two DAGs and returns the best one, according to the OF. * - * calculate_rank(parent, base_rank) - * - * Calculates a rank value using the parent rank and a base rank. - * If "parent" is NULL, the objective function selects a default increment - * that is adds to the "base_rank". Otherwise, the OF uses information known - * about "parent" to select an increment to the "base_rank". - * * update_metric_container(dag) * * Updates the metric container for outgoing DIOs in a certain DAG. - * If the objective function of the DAG does not use metric containers, + * If the objective function of the DAG does not use metric containers, * the function should set the object type to RPL_DAG_MC_NONE. + * + * dao_ack_callback(parent, status) + * + * A callback on the result of the DAO ACK. Similar to the neighbor link + * callback. A failed DAO_ACK (NACK) can be used for switching to another + * parent via changed link metric or other mechanisms. */ struct rpl_of { void (*reset)(struct rpl_dag *); - void (*neighbor_link_callback)(rpl_parent_t *, int, int); +#if RPL_WITH_DAO_ACK + void (*dao_ack_callback)(rpl_parent_t *, int status); +#endif + uint16_t (*parent_link_metric)(rpl_parent_t *); + int (*parent_has_usable_link)(rpl_parent_t *); + uint16_t (*parent_path_cost)(rpl_parent_t *); + rpl_rank_t (*rank_via_parent)(rpl_parent_t *); rpl_parent_t *(*best_parent)(rpl_parent_t *, rpl_parent_t *); rpl_dag_t *(*best_dag)(rpl_dag_t *, rpl_dag_t *); - rpl_rank_t (*calculate_rank)(rpl_parent_t *, rpl_rank_t); void (*update_metric_container)( rpl_instance_t *); rpl_ocp_t ocp; }; typedef struct rpl_of rpl_of_t; -/* Declare the selected objective function. */ -extern rpl_of_t RPL_OF; /*---------------------------------------------------------------------------*/ /* Instance */ struct rpl_instance { @@ -216,6 +235,11 @@ struct rpl_instance { uint8_t dio_intcurrent; uint8_t dio_send; /* for keeping track of which mode the timer is in */ uint8_t dio_counter; + /* my last registered DAO that I might be waiting for ACK on */ + uint8_t my_dao_seqno; + uint8_t my_dao_transmissions; + /* this is intended to keep track if this instance have a route downward */ + uint8_t has_downward_route; rpl_rank_t max_rankinc; rpl_rank_t min_hoprankinc; uint16_t lifetime_unit; /* lifetime in seconds = l_u * d_l */ @@ -227,12 +251,16 @@ struct rpl_instance { clock_time_t dio_next_delay; /* delay for completion of dio interval */ #if RPL_WITH_PROBING struct ctimer probing_timer; + rpl_parent_t *urgent_probing_target; #endif /* RPL_WITH_PROBING */ struct ctimer dio_timer; struct ctimer dao_timer; struct ctimer dao_lifetime_timer; struct ctimer unicast_dio_timer; rpl_parent_t *unicast_dio_target; +#if RPL_WITH_DAO_ACK + struct ctimer dao_retransmit_timer; +#endif /* RPL_WITH_DAO_ACK */ }; /*---------------------------------------------------------------------------*/ @@ -243,21 +271,28 @@ rpl_dag_t *rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id); int rpl_set_prefix(rpl_dag_t *dag, uip_ipaddr_t *prefix, unsigned len); int rpl_repair_root(uint8_t instance_id); int rpl_set_default_route(rpl_instance_t *instance, uip_ipaddr_t *from); +rpl_dag_t *rpl_get_dag(const uip_ipaddr_t *addr); rpl_dag_t *rpl_get_any_dag(void); rpl_instance_t *rpl_get_instance(uint8_t instance_id); -int rpl_update_header_empty(void); -int rpl_update_header_final(uip_ipaddr_t *addr); -int rpl_verify_header(int); +int rpl_update_header(void); +int rpl_finalize_header(uip_ipaddr_t *addr); +int rpl_verify_hbh_header(int); void rpl_insert_header(void); void rpl_remove_header(void); -uint8_t rpl_invert_header(void); +const struct link_stats *rpl_get_parent_link_stats(rpl_parent_t *p); +int rpl_parent_is_fresh(rpl_parent_t *p); +int rpl_parent_is_reachable(rpl_parent_t *p); +uint16_t rpl_get_parent_link_metric(rpl_parent_t *p); +rpl_rank_t rpl_rank_via_parent(rpl_parent_t *p); +const linkaddr_t *rpl_get_parent_lladdr(rpl_parent_t *p); uip_ipaddr_t *rpl_get_parent_ipaddr(rpl_parent_t *nbr); rpl_parent_t *rpl_get_parent(uip_lladdr_t *addr); rpl_rank_t rpl_get_parent_rank(uip_lladdr_t *addr); -uint16_t rpl_get_parent_link_metric(const uip_lladdr_t *addr); void rpl_dag_init(void); uip_ds6_nbr_t *rpl_get_nbr(rpl_parent_t *parent); -void rpl_print_neighbor_list(); +void rpl_print_neighbor_list(void); +int rpl_process_srh_header(void); +int rpl_srh_get_next_hop(uip_ipaddr_t *ipaddr); /* Per-parent RPL information */ NBR_TABLE_DECLARE(rpl_parents); @@ -293,5 +328,13 @@ enum rpl_mode rpl_set_mode(enum rpl_mode mode); */ enum rpl_mode rpl_get_mode(void); + +/** + * Get the RPL's best guess on if we have downward route or not. + * + * \retval 1 if we have a downward route from RPL Root, 0 if not. + */ +int rpl_has_downward_route(void); + /*---------------------------------------------------------------------------*/ #endif /* RPL_H */ diff --git a/core/sys/process.c b/core/sys/process.c index b2ed5701c..f98057cd3 100644 --- a/core/sys/process.c +++ b/core/sys/process.c @@ -245,10 +245,10 @@ do_poll(void) static void do_event(void) { - static process_event_t ev; - static process_data_t data; - static struct process *receiver; - static struct process *p; + process_event_t ev; + process_data_t data; + struct process *receiver; + struct process *p; /* * If there are any events in the queue, take the first one and walk @@ -321,7 +321,7 @@ process_nevents(void) int process_post(struct process *p, process_event_t ev, process_data_t data) { - static process_num_events_t snum; + process_num_events_t snum; if(PROCESS_CURRENT() == NULL) { PRINTF("process_post: NULL process posts event %d to process '%s', nevents %d\n", diff --git a/core/sys/rtimer.h b/core/sys/rtimer.h index 91c23b932..a89ed8299 100644 --- a/core/sys/rtimer.h +++ b/core/sys/rtimer.h @@ -55,10 +55,12 @@ #include "contiki-conf.h" -#ifndef RTIMER_CLOCK_LT +#ifndef RTIMER_CLOCK_DIFF typedef unsigned short rtimer_clock_t; -#define RTIMER_CLOCK_LT(a,b) ((signed short)((a)-(b)) < 0) -#endif /* RTIMER_CLOCK_LT */ +#define RTIMER_CLOCK_DIFF(a,b) ((signed short)((a)-(b))) +#endif /* RTIMER_CLOCK_DIFF */ + +#define RTIMER_CLOCK_LT(a, b) (RTIMER_CLOCK_DIFF((a),(b)) < 0) #include "rtimer-arch.h" diff --git a/cpu/6502/Makefile.6502 b/cpu/6502/Makefile.6502 index 4d9034a8f..07e8e3af6 100644 --- a/cpu/6502/Makefile.6502 +++ b/cpu/6502/Makefile.6502 @@ -31,10 +31,6 @@ # Author: Oliver Schmidt # -ifndef CC65_HOME - ${error CC65_HOME not defined! You must specify where cc65 resides} -endif - .SUFFIXES: CONTIKI_TARGET_DIRS = . lib sys @@ -70,3 +66,5 @@ ASFLAGS = -t $(TARGET) CFLAGS += -t $(TARGET) -Or -W -unused-param LDFLAGS = -t $(TARGET) -m contiki-$(TARGET).map -D __STACKSIZE__=0x200 AROPTS = a + +CC65_TARGET_DIR := $(shell $(CC) --print-target-path)/$(TARGET) diff --git a/cpu/6502/lib/pfs.h b/cpu/6502/lib/pfs.h index 25c62e8bf..73102ce55 100644 --- a/cpu/6502/lib/pfs.h +++ b/cpu/6502/lib/pfs.h @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * This file is part of the Contiki operating system. - * + * * Author: Oliver Schmidt * */ @@ -35,11 +35,13 @@ #ifndef PFS_H_ #define PFS_H_ -int __fastcall__ pfs_open(const char* name, int flags); -void __fastcall__ pfs_close(int fd); -int __fastcall__ pfs_read(int fd, void* buf, unsigned int len); -int __fastcall__ pfs_write(int fd, void* buf, unsigned int len); -int __fastcall__ pfs_seek(int fd, int offset, int whence); -int __fastcall__ pfs_remove(const char *name); +#include + +int __fastcall__ pfs_open(const char *name, int flags); +void __fastcall__ pfs_close(int fd); +int __fastcall__ pfs_read(int fd, void *buf, unsigned int len); +int __fastcall__ pfs_write(int fd, const void *buf, unsigned int len); +off_t __fastcall__ pfs_seek(int fd, off_t offset, int whence); +int __fastcall__ pfs_remove(const char *name); #endif /* PFS_H_ */ diff --git a/cpu/6502/net/w5100.S b/cpu/6502/net/w5100.S index 8fb040b01..3d8160170 100644 --- a/cpu/6502/net/w5100.S +++ b/cpu/6502/net/w5100.S @@ -97,7 +97,8 @@ fixup: .byte fixup02-fixup01, fixup03-fixup02, fixup04-fixup03 .byte fixup20-fixup19, fixup21-fixup20, fixup22-fixup21 .byte fixup23-fixup22, fixup24-fixup23, fixup25-fixup24 .byte fixup26-fixup25, fixup27-fixup26, fixup28-fixup27 - .byte fixup29-fixup28, fixup30-fixup29 + .byte fixup29-fixup28, fixup30-fixup29, fixup31-fixup30 + .byte fixup32-fixup31 fixups = * - fixup @@ -164,44 +165,64 @@ fixup04:eor data sec rts + ; Check for W5100 shared access + ; RX Memory Size Register: Assign 4+2+1+1KB to socket 0 to 3 ? +: ; ldx #$00 ; Hibyte + ldy #$1A ; Lobyte + jsr set_addr +fixup05:lda data + cmp #$06 + beq :+++ + ; S/W Reset -: lda #$80 -fixup05:sta mode + lda #$80 +fixup06:sta mode : -fixup06:lda mode +fixup07:lda mode bmi :- ; Indirect Bus I/F mode, Address Auto-Increment, Ping Block lda #$13 -fixup07:sta mode +fixup08:sta mode ; Source Hardware Address Register: MAC Address ldx #$00 ; Hibyte ldy #$09 ; Lobyte jsr set_addr : lda mac,x -fixup08:sta data +fixup09:sta data inx cpx #$06 bcc :- - ; RX Memory Size Register: Assign 8KB to socket 0 - ; TX Memory Size Register: Assign 8KB to socket 0 + ; RX Memory Size Register: Assign 4KB each to socket 0 and 1 + ; TX Memory Size Register: Assign 4KB each to socket 0 and 1 ldx #$00 ; Hibyte ldy #$1A ; Lobyte jsr set_addr - lda #$03 -fixup09:sta data + lda #$0A fixup10:sta data +fixup11:sta data + + ; MAC Address: Source Hardware Address Register +: ; ldx #$00 ; Hibyte + ldy #$09 ; Lobyte + jsr set_addr +: +fixup12:lda data + sta mac,x + inx + cpx #$06 + bcc :- ; Socket 0 Mode Register: MACRAW, MAC Filter ; Socket 0 Command Register: OPEN ldy #$00 jsr set_addrsocket0 lda #$44 -fixup11:sta data +fixup13:sta data lda #$01 -fixup12:sta data +fixup14:sta data tya tax clc @@ -213,7 +234,7 @@ poll: ; Check for completion of previous command ; Socket 0 Command Register: = 0 ? jsr set_addrcmdreg0 -fixup13:lda data +fixup15:lda data beq :++ ; No data available @@ -225,8 +246,8 @@ fixup13:lda data ; Socket 0 RX Received Size Register: != 0 ? : ldy #$26 ; Socket RX Received Size Register jsr set_addrsocket0 -fixup14:lda data ; Hibyte -fixup15:ora data ; Lobyte +fixup16:lda data ; Hibyte +fixup17:ora data ; Lobyte beq :-- ; Process the incoming data @@ -243,8 +264,8 @@ fixup15:ora data ; Lobyte ; Calculate and set physical address jsr set_addrphysical - ; Move physical address shadow to $E000-$FFFF - ora #>$8000 + ; Move physical address shadow to $F000-$FFFF + ora #>$F000 tax ; Read MAC raw 2byte packet size header @@ -292,13 +313,13 @@ common: jsr set_addrsocket0 tax lda reg+1 adc adv+1 -fixup16:sta data ; Hibyte -fixup17:stx data ; Lobyte +fixup18:sta data ; Hibyte +fixup19:stx data ; Lobyte ; Set command register tya ; Restore command jsr set_addrcmdreg0 -fixup18:sta data +fixup20:sta data ; Return data length (will be ignored for send) lda len @@ -325,14 +346,14 @@ send: ; Wait for completion of previous command ; Socket 0 Command Register: = 0 ? : jsr set_addrcmdreg0 -fixup19:lda data +fixup21:lda data bne :- ; Socket 0 TX Free Size Register: < length ? : ldy #$20 ; Socket TX Free Size Register jsr set_addrsocket0 -fixup20:lda data ; Hibyte -fixup21:ldx data ; Lobyte +fixup22:lda data ; Hibyte +fixup23:ldx data ; Lobyte cpx len sbc len+1 bcc :- @@ -362,16 +383,16 @@ exit: ;--------------------------------------------------------------------- set_addrphysical: -fixup22:lda data ; Hibyte -fixup23:ldy data ; Lobyte +fixup24:lda data ; Hibyte +fixup25:ldy data ; Lobyte sty reg sta reg+1 - and #>$1FFF ; Socket Mask Address (hibyte) + and #>$0FFF ; Socket Mask Address (hibyte) ora bas ; Socket Base Address (hibyte) tax set_addr: -fixup24:stx addr ; Hibyte -fixup25:sty addr+1 ; Lobyte +fixup26:stx addr ; Hibyte +fixup27:sty addr+1 ; Lobyte rts set_addrcmdreg0: @@ -386,7 +407,7 @@ set_addrbase: beq set_addr ; Always get_datacheckaddr: -fixup26:lda data +fixup28:lda data iny ; Physical address shadow (lobyte) bne :+ inx ; Physical address shadow (hibyte) @@ -399,7 +420,7 @@ set_parameters: ; Setup variables in zero page sta bas ; Socket Base Address clc - adc #>$2000 ; Socket memory size + adc #>$1000 ; Socket memory size sta lim ; Socket memory limit stx dir ; Transfer direction @@ -427,10 +448,10 @@ mov_data: ; R/W without address wraparound possible because ; highest R/W address > actual R/W address ? ; sec -fixup27:sbc addr+1 ; Lobyte +fixup29:sbc addr+1 ; Lobyte tay txa -fixup28:sbc addr ; Hibyte +fixup30:sbc addr ; Hibyte tax tya bcs :+ @@ -491,7 +512,7 @@ rw_data:eor #$FF ; Two's complement part 1 ; Read data : -fixup29:lda data +fixup31:lda data sta (ptr),y iny bne :- @@ -502,7 +523,7 @@ fixup29:lda data ; Write data : lda (ptr),y -fixup30:sta data +fixup32:sta data iny bne :- inc ptr+1 diff --git a/cpu/arm/aducrf101/aducrf101-contiki.h b/cpu/arm/aducrf101/aducrf101-contiki.h index 00fd8765d..4610c49d6 100644 --- a/cpu/arm/aducrf101/aducrf101-contiki.h +++ b/cpu/arm/aducrf101/aducrf101-contiki.h @@ -46,7 +46,7 @@ typedef uint32_t clock_time_t; typedef uint16_t uip_stats_t; typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_LT(a, b) ((int32_t)((a) - (b)) < 0) +#define RTIMER_CLOCK_DIFF(a, b) ((int32_t)((a) - (b))) rtimer_clock_t rtimer_arch_now(void); #endif diff --git a/cpu/avr/Makefile.avr b/cpu/avr/Makefile.avr index 34537caa9..bc94010a2 100644 --- a/cpu/avr/Makefile.avr +++ b/cpu/avr/Makefile.avr @@ -12,7 +12,7 @@ CONTIKI_CPU=$(CONTIKI)/cpu/avr ### These directories will be searched for the specified source files ### TARGETLIBS are platform-specific routines in the contiki library path -CONTIKI_CPU_DIRS = . dev +CONTIKI_CPU_DIRS = . dev dev/arduino AVR = clock.c mtarch.c eeprom.c flash.c rs232.c leds-arch.c \ watchdog.c rtimer-arch.c bootloader.c ELFLOADER = elfloader.c elfloader-avr.c symtab-avr.c @@ -202,23 +202,30 @@ endif ### Upload image #Let avrdude use defaults if port or programmer not defined AVRDUDE ?= avrdude -ifdef AVRDUDE_PORT - AVRDUDE_PORT:=-P $(AVRDUDE_PORT) -endif -ifdef AVRDUDE_PROGRAMMER - AVRDUDE_PROGRAMMER:=-c $(AVRDUDE_PROGRAMMER) -endif ifdef AVRDUDE_MCU - AVRDUDE_MCU:=-p $(AVRDUDE_MCU) + DUDE_MCU:=-p $(AVRDUDE_MCU) else - AVRDUDE_MCU:=-p $(MCU) + DUDE_MCU:=-p $(MCU) endif %.u: %.hex - $(AVRDUDE) $(AVRDUDE_MCU) $(AVRDUDE_OPTIONS) $(AVRDUDE_PORT) $(AVRDUDE_PROGRAMMER) -U flash:w:$< + $(AVRDUDE) $(DUDE_MCU) $(AVRDUDE_OPTIONS) -P $(AVRDUDE_PORT) \ + -c $(AVRDUDE_PROGRAMMER) -U flash:w:$<:i %.eu: %.eep - $(AVRDUDE) $(AVRDUDE_MCU) ${AVRDUDE_OPTIONS} ${AVRDUDE_PORT} ${AVRDUDE_PROGRAMMER} -U eeprom:w:$< + $(AVRDUDE) $(DUDE_MCU) ${AVRDUDE_OPTIONS} -P ${AVRDUDE_PORT} \ + -c ${AVRDUDE_PROGRAMMER} -U eeprom:w:$<:i symbols.c: cp ${CONTIKI}/tools/empty-symbols.c symbols.c cp ${CONTIKI}/tools/empty-symbols.h symbols.h + +# Generic rules for .hex, .eep and .sz (size) file: +%.$(TARGET).hex: %.$(TARGET) + $(OBJCOPY) -j .text -j .data -O ihex $< $@ + +%.$(TARGET).eep: %.$(TARGET) + $(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ + --change-section-lma .eeprom=0 -O ihex $< $@ + +%.$(TARGET).sz: %.$(TARGET) + $(ELF_SIZE) $< diff --git a/platform/osd-merkur/dev/adc.c b/cpu/avr/dev/adc.c similarity index 100% rename from platform/osd-merkur/dev/adc.c rename to cpu/avr/dev/adc.c diff --git a/platform/osd-merkur/dev/adc.h b/cpu/avr/dev/adc.h similarity index 100% rename from platform/osd-merkur/dev/adc.h rename to cpu/avr/dev/adc.h diff --git a/platform/osd-merkur/dev/arduino/Arduino.h b/cpu/avr/dev/arduino/Arduino.h similarity index 100% rename from platform/osd-merkur/dev/arduino/Arduino.h rename to cpu/avr/dev/arduino/Arduino.h diff --git a/platform/osd-merkur/dev/arduino/Print.cpp b/cpu/avr/dev/arduino/Print.cpp similarity index 100% rename from platform/osd-merkur/dev/arduino/Print.cpp rename to cpu/avr/dev/arduino/Print.cpp diff --git a/platform/osd-merkur/dev/arduino/Print.h b/cpu/avr/dev/arduino/Print.h similarity index 100% rename from platform/osd-merkur/dev/arduino/Print.h rename to cpu/avr/dev/arduino/Print.h diff --git a/platform/osd-merkur/dev/arduino/Printable.h b/cpu/avr/dev/arduino/Printable.h similarity index 100% rename from platform/osd-merkur/dev/arduino/Printable.h rename to cpu/avr/dev/arduino/Printable.h diff --git a/platform/osd-merkur/dev/arduino/Stream.cpp b/cpu/avr/dev/arduino/Stream.cpp similarity index 100% rename from platform/osd-merkur/dev/arduino/Stream.cpp rename to cpu/avr/dev/arduino/Stream.cpp diff --git a/platform/osd-merkur/dev/arduino/Stream.h b/cpu/avr/dev/arduino/Stream.h similarity index 100% rename from platform/osd-merkur/dev/arduino/Stream.h rename to cpu/avr/dev/arduino/Stream.h diff --git a/platform/osd-merkur/dev/arduino/WMath.cpp b/cpu/avr/dev/arduino/WMath.cpp similarity index 100% rename from platform/osd-merkur/dev/arduino/WMath.cpp rename to cpu/avr/dev/arduino/WMath.cpp diff --git a/platform/osd-merkur/dev/arduino/WString.cpp b/cpu/avr/dev/arduino/WString.cpp similarity index 100% rename from platform/osd-merkur/dev/arduino/WString.cpp rename to cpu/avr/dev/arduino/WString.cpp diff --git a/platform/osd-merkur/dev/arduino/WString.h b/cpu/avr/dev/arduino/WString.h similarity index 100% rename from platform/osd-merkur/dev/arduino/WString.h rename to cpu/avr/dev/arduino/WString.h diff --git a/platform/osd-merkur/dev/arduino/Wire.cpp b/cpu/avr/dev/arduino/Wire.cpp similarity index 100% rename from platform/osd-merkur/dev/arduino/Wire.cpp rename to cpu/avr/dev/arduino/Wire.cpp diff --git a/platform/osd-merkur/dev/arduino/Wire.h b/cpu/avr/dev/arduino/Wire.h similarity index 100% rename from platform/osd-merkur/dev/arduino/Wire.h rename to cpu/avr/dev/arduino/Wire.h diff --git a/platform/osd-merkur/dev/binary.h b/cpu/avr/dev/arduino/binary.h similarity index 100% rename from platform/osd-merkur/dev/binary.h rename to cpu/avr/dev/arduino/binary.h diff --git a/platform/osd-merkur/dev/arduino/hw-arduino.h b/cpu/avr/dev/arduino/hw-arduino.h similarity index 100% rename from platform/osd-merkur/dev/arduino/hw-arduino.h rename to cpu/avr/dev/arduino/hw-arduino.h diff --git a/platform/osd-merkur/dev/arduino/new.cpp b/cpu/avr/dev/arduino/new.cpp similarity index 100% rename from platform/osd-merkur/dev/arduino/new.cpp rename to cpu/avr/dev/arduino/new.cpp diff --git a/platform/osd-merkur/dev/arduino/new.h b/cpu/avr/dev/arduino/new.h similarity index 100% rename from platform/osd-merkur/dev/arduino/new.h rename to cpu/avr/dev/arduino/new.h diff --git a/platform/osd-merkur/dev/arduino/twi.c b/cpu/avr/dev/arduino/twi.c similarity index 100% rename from platform/osd-merkur/dev/arduino/twi.c rename to cpu/avr/dev/arduino/twi.c diff --git a/platform/osd-merkur/dev/arduino/twi.h b/cpu/avr/dev/arduino/twi.h similarity index 100% rename from platform/osd-merkur/dev/arduino/twi.h rename to cpu/avr/dev/arduino/twi.h diff --git a/platform/osd-merkur/dev/arduino/wiring_digital.c b/cpu/avr/dev/arduino/wiring_digital.c similarity index 100% rename from platform/osd-merkur/dev/arduino/wiring_digital.c rename to cpu/avr/dev/arduino/wiring_digital.c diff --git a/platform/osd-merkur/dev/arduino/wiring_private.h b/cpu/avr/dev/arduino/wiring_private.h similarity index 100% rename from platform/osd-merkur/dev/arduino/wiring_private.h rename to cpu/avr/dev/arduino/wiring_private.h diff --git a/platform/osd-merkur/dev/batmon.c b/cpu/avr/dev/batmon.c similarity index 100% rename from platform/osd-merkur/dev/batmon.c rename to cpu/avr/dev/batmon.c diff --git a/platform/osd-merkur/dev/batmon.h b/cpu/avr/dev/batmon.h similarity index 100% rename from platform/osd-merkur/dev/batmon.h rename to cpu/avr/dev/batmon.h diff --git a/platform/osd-merkur/dev/battery-sensor.c b/cpu/avr/dev/battery-sensor.c similarity index 100% rename from platform/osd-merkur/dev/battery-sensor.c rename to cpu/avr/dev/battery-sensor.c diff --git a/platform/osd-merkur/dev/battery-sensor.h b/cpu/avr/dev/battery-sensor.h similarity index 100% rename from platform/osd-merkur/dev/battery-sensor.h rename to cpu/avr/dev/battery-sensor.h diff --git a/platform/osd-merkur/dev/button-sensor.c b/cpu/avr/dev/button-sensor.c similarity index 100% rename from platform/osd-merkur/dev/button-sensor.c rename to cpu/avr/dev/button-sensor.c diff --git a/cpu/avr/dev/clock-avr.h b/cpu/avr/dev/clock-avr.h index 97a79ee23..662bd21d3 100644 --- a/cpu/avr/dev/clock-avr.h +++ b/cpu/avr/dev/clock-avr.h @@ -73,7 +73,7 @@ TIMSK0 = _BV (OCIE0A); -#elif defined (__AVR_ATmega1284P__) || (__AVR_AT90USB1287__) || (__AVR_ATmega1281__) || defined (__AVR_ATmega128RFA1__) +#elif defined (__AVR_ATmega1284P__) || (__AVR_AT90USB1287__) || (__AVR_ATmega1281__) || defined (__AVR_ATmega128RFA1__) || defined (__AVR_ATmega128RFR2__) || defined (__AVR_ATmega256RFR2__) /* The Raven has a 32768Hz watch crystal that can be used to clock the timer while the 1284p is sleeping. The Jackdaw has pads for a crystal. The crystal diff --git a/platform/osd-merkur/dev/dht11.c b/cpu/avr/dev/dht11.c similarity index 100% rename from platform/osd-merkur/dev/dht11.c rename to cpu/avr/dev/dht11.c diff --git a/platform/osd-merkur/dev/dht11.h b/cpu/avr/dev/dht11.h similarity index 100% rename from platform/osd-merkur/dev/dht11.h rename to cpu/avr/dev/dht11.h diff --git a/platform/osd-merkur/dev/ds1820.c b/cpu/avr/dev/ds1820.c similarity index 100% rename from platform/osd-merkur/dev/ds1820.c rename to cpu/avr/dev/ds1820.c diff --git a/platform/osd-merkur/dev/ds1820.h b/cpu/avr/dev/ds1820.h similarity index 100% rename from platform/osd-merkur/dev/ds1820.h rename to cpu/avr/dev/ds1820.h diff --git a/platform/osd-merkur/dev/i2c.c b/cpu/avr/dev/i2c.c similarity index 100% rename from platform/osd-merkur/dev/i2c.c rename to cpu/avr/dev/i2c.c diff --git a/platform/osd-merkur/dev/i2c.h b/cpu/avr/dev/i2c.h similarity index 100% rename from platform/osd-merkur/dev/i2c.h rename to cpu/avr/dev/i2c.h diff --git a/platform/osd-merkur/dev/key.c b/cpu/avr/dev/key.c similarity index 100% rename from platform/osd-merkur/dev/key.c rename to cpu/avr/dev/key.c diff --git a/platform/osd-merkur/dev/key.h b/cpu/avr/dev/key.h similarity index 100% rename from platform/osd-merkur/dev/key.h rename to cpu/avr/dev/key.h diff --git a/platform/osd-merkur/dev/led.c b/cpu/avr/dev/led.c similarity index 100% rename from platform/osd-merkur/dev/led.c rename to cpu/avr/dev/led.c diff --git a/cpu/avr/dev/led.h b/cpu/avr/dev/led.h new file mode 100644 index 000000000..60ce30b01 --- /dev/null +++ b/cpu/avr/dev/led.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012 Harald Pichler + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holders nor the names of + * 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 OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * + * \brief + * This file provides Raven LED support. + * + * \author + * Harald Pichler harald@the-develop.net + * + */ + +#ifndef __LED_H__ +#define __LED_H__ + +#include + +/* Some io.h definitions of shift vary among processors */ +#ifndef DDE0 +#define DDE0 DDRE0 +#define DDE1 DDRE1 +#define DDE2 DDRE2 +#define DDE3 DDRE3 +#define DDE4 DDRE4 +#define DDE5 DDRE5 +#define DDE6 DDRE6 +#define DDE7 DDRE7 +#endif + + +/** @name LED Functions */ +/** @{ */ +void led1_on(void); +void led1_off(void); +void led2_on(void); +void led2_off(void); +/** @} */ + +#endif /* __LED_H__ */ diff --git a/platform/osd-merkur/dev/optriac-sensor.c b/cpu/avr/dev/optriac-sensor.c similarity index 100% rename from platform/osd-merkur/dev/optriac-sensor.c rename to cpu/avr/dev/optriac-sensor.c diff --git a/platform/osd-merkur/dev/optriac-sensor.h b/cpu/avr/dev/optriac-sensor.h similarity index 100% rename from platform/osd-merkur/dev/optriac-sensor.h rename to cpu/avr/dev/optriac-sensor.h diff --git a/platform/osd-merkur/dev/pir-sensor.c b/cpu/avr/dev/pir-sensor.c similarity index 100% rename from platform/osd-merkur/dev/pir-sensor.c rename to cpu/avr/dev/pir-sensor.c diff --git a/platform/osd-merkur/dev/pir-sensor.h b/cpu/avr/dev/pir-sensor.h similarity index 100% rename from platform/osd-merkur/dev/pir-sensor.h rename to cpu/avr/dev/pir-sensor.h diff --git a/platform/osd-merkur/dev/relay-sensor.c b/cpu/avr/dev/relay-sensor.c similarity index 100% rename from platform/osd-merkur/dev/relay-sensor.c rename to cpu/avr/dev/relay-sensor.c diff --git a/platform/osd-merkur/dev/relay-sensor.h b/cpu/avr/dev/relay-sensor.h similarity index 100% rename from platform/osd-merkur/dev/relay-sensor.h rename to cpu/avr/dev/relay-sensor.h diff --git a/platform/osd-merkur/dev/relay.c b/cpu/avr/dev/relay.c similarity index 100% rename from platform/osd-merkur/dev/relay.c rename to cpu/avr/dev/relay.c diff --git a/platform/osd-merkur/dev/relay.h b/cpu/avr/dev/relay.h similarity index 100% rename from platform/osd-merkur/dev/relay.h rename to cpu/avr/dev/relay.h diff --git a/cpu/avr/dev/rs232.c b/cpu/avr/dev/rs232.c index 94cf5035f..2df263491 100644 --- a/cpu/avr/dev/rs232.c +++ b/cpu/avr/dev/rs232.c @@ -83,7 +83,7 @@ #define NUMPORTS RS232_CONF_NUMPORTS #endif -#if defined (__AVR_ATmega128__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega128RFA1__) +#if defined (__AVR_ATmega128__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) #ifndef NUMPORTS #define NUMPORTS 2 #elif NUMPORTS > 2 diff --git a/cpu/avr/dev/rs232.h b/cpu/avr/dev/rs232.h index 08a3d4f9f..e55ace99a 100644 --- a/cpu/avr/dev/rs232.h +++ b/cpu/avr/dev/rs232.h @@ -49,6 +49,10 @@ #include "dev/rs232_at90usb1287.h" #elif defined (__AVR_ATmega128RFA1__) #include "dev/rs232_atmega128rfa1.h" +#elif defined (__AVR_ATmega128RFR2__) +#include "dev/rs232_atmega128rfa1.h" +#elif defined (__AVR_ATmega256RFR2__) +#include "dev/rs232_atmega256rfr2.h" #elif defined (__AVR_ATmega644__) || defined (__AVR_ATmega328P__) #include "dev/rs232_atmega644.h" #elif defined (__AVR_ATmega8__) || defined (__AVR_ATmega8515__) \ diff --git a/cpu/avr/dev/rs232_atmega256rfr2.h b/cpu/avr/dev/rs232_atmega256rfr2.h new file mode 100644 index 000000000..abd32f7b7 --- /dev/null +++ b/cpu/avr/dev/rs232_atmega256rfr2.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2006, Technical University of Munich + * 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 + * AVR specific definitions for the rs232 port. + * + * \author + * Simon Barner + +/******************************************************************************/ +/*** RS232 ports */ +/******************************************************************************/ +#define RS232_PORT_0 0 +#define RS232_PORT_1 1 + +/******************************************************************************/ +/*** Baud rates */ +/******************************************************************************/ +#if (F_CPU == 16000000UL) +/* Single speed operation (U2X = 0)*/ +#define USART_BAUD_2400 416 +#define USART_BAUD_4800 207 +#define USART_BAUD_9600 103 +#define USART_BAUD_14400 68 +#define USART_BAUD_19200 51 +#define USART_BAUD_28800 34 +#define USART_BAUD_38400 25 +#define USART_BAUD_57600 16 +#define USART_BAUD_76800 12 +#define USART_BAUD_115200 8 +#define USART_BAUD_230400 3 +#define USART_BAUD_250000 3 +#define USART_BAUD_500000 1 +#define USART_BAUD_1000000 0 +#elif (F_CPU == 8000000UL) +/* Single speed operation (U2X = 0)*/ +#define USART_BAUD_2400 207 +#define USART_BAUD_4800 103 +#define USART_BAUD_9600 51 +#define USART_BAUD_14400 34 +#define USART_BAUD_19200 25 +#define USART_BAUD_28800 16 +#define USART_BAUD_38400 12 +#define USART_BAUD_57600 8 +#define USART_BAUD_76800 6 +#define USART_BAUD_115200 3 +#define USART_BAUD_230400 1 +#define USART_BAUD_250000 1 +#define USART_BAUD_500000 0 +#else +#error "Please define the baud rates for your CPU clock (see ATmega256rfr2 datasheet) \ +or set the rate in contiki-conf.h" +#endif + + +/******************************************************************************/ +/*** Interrupt settings */ +/******************************************************************************/ +#define USART_INTERRUPT_RX_COMPLETE _BV (RXCIE0) +#define USART_INTERRUPT_TX_COMPLETE _BV (TXCIE0) +#define USART_INTERRUPT_DATA_REG_EMPTY _BV (UDRIE0) + +/******************************************************************************/ +/*** Receiver / transmitter */ +/******************************************************************************/ +#define USART_RECEIVER_ENABLE _BV (RXEN0) +#define USART_TRANSMITTER_ENABLE _BV (TXEN0) + +/******************************************************************************/ +/*** Mode select */ +/******************************************************************************/ +#define USART_MODE_ASYNC 0x00 +#define USART_MODE_SYNC _BV (UMSEL00) + +/******************************************************************************/ +/*** Parity */ +/******************************************************************************/ +#define USART_PARITY_NONE 0x00 +#define USART_PARITY_EVEN _BV (UPM01) +#define USART_PARITY_ODD _BV (UPM01) | _BV (UPM00) + +/******************************************************************************/ +/*** Stop bits */ +/******************************************************************************/ +#define USART_STOP_BITS_1 0x00 +#define USART_STOP_BITS_2 _BV (USBS) + +/******************************************************************************/ +/*** Character size */ +/******************************************************************************/ +#define USART_DATA_BITS_5 0x00 +#define USART_DATA_BITS_6 _BV (UCSZ00) +#define USART_DATA_BITS_7 _BV (UCSZ01) +#define USART_DATA_BITS_8 _BV (UCSZ01) | _BV (UCSZ00) +// #define USART_DATA_BITS_9 (needs also UCSZ2 bit in UCSRnB) + +/******************************************************************************/ +/*** Clock polarity */ +/******************************************************************************/ +#define USART_RISING_XCKN_EDGE 0x00 +#define USART_FALLING_XCKN_EDGE _BV (UCPOL0) + +#endif /* #ifndef __RS232_ATMEGA128RFA1__ */ diff --git a/platform/osd-merkur/dev/servo-sensor.c b/cpu/avr/dev/servo-sensor.c similarity index 100% rename from platform/osd-merkur/dev/servo-sensor.c rename to cpu/avr/dev/servo-sensor.c diff --git a/platform/osd-merkur/dev/servo-sensor.h b/cpu/avr/dev/servo-sensor.h similarity index 100% rename from platform/osd-merkur/dev/servo-sensor.h rename to cpu/avr/dev/servo-sensor.h diff --git a/platform/osd-merkur/dev/servo.c b/cpu/avr/dev/servo.c similarity index 100% rename from platform/osd-merkur/dev/servo.c rename to cpu/avr/dev/servo.c diff --git a/platform/osd-merkur/dev/servo.h b/cpu/avr/dev/servo.h similarity index 100% rename from platform/osd-merkur/dev/servo.h rename to cpu/avr/dev/servo.h diff --git a/cpu/avr/dev/sg-ready.c b/cpu/avr/dev/sg-ready.c new file mode 100644 index 000000000..93c1990bc --- /dev/null +++ b/cpu/avr/dev/sg-ready.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2015 Bernhard Trinnes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holders nor the names of + * 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 OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * + * \brief + * Smart Grid Ready Module - guhRF + * + * \author + * Bernhard Trinnes bernhard.trinnes@guh.guru + guh Gmbh + * + */ + +#include "sg-ready.h" +#include + + +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + + + +/** + * \addtogroup relay + * \{ +*/ +/*---------------------------------------------------------------------------*/ +/** + * \brief init RELAY PINS - direction & pull-ups +*/ +void +sg_relay_init(uint8_t state) +{ + /*2 latching dual coal relay + RELAY 1 Coil 1 PB4 - ON + Coil 2 PB5 - OFF + Feedback PD5 + RELAY 2 Coil 1 PB6 - ON + Coil 2 PB7 - OFF + Feedback PD7 + + */ + + PRINTF("SET DDRB\n"); + DDRB |= (RELAY1_ON | RELAY1_OFF | RELAY2_ON | RELAY2_OFF); + PRINTF("SET PORTB\n"); + PORTB &= ~(RELAY1_ON | RELAY1_OFF | RELAY2_ON | RELAY2_OFF); + + PRINTF("SET DDRD\n"); + DDRD &= ~(RELAY1_FB | RELAY2_FB); + PRINTF("SET PORTD\n"); + PORTD |= (RELAY1_FB | RELAY2_FB); + + PRINTF("SET STATE\n"); + sg_set_state(state); // set default state - heat pump normal operation +} + +/** + * \brief +*/ + +void +sg_set_state(uint8_t state) +{ + /* State 1 - Relays 1:0 + State 2 - Relays 0:0 + State 3 - Relays 0:1 + State 4 - Relays 1:1 + uint8_t i = 0; + */ + uint8_t current_state; + + PRINTF("GET STATE\n"); + current_state = sg_get_state(); + + PRINTF("SET DIFFERENCE: %u %u\n", current_state, state); + sg_switch_difference(current_state, state); + + + +/* while ( i<=3 || (current_state != state)){ + i++; + sg_switch_difference(current_state, state); + current_state = sg_get_state(); + } +*/ +} +/** + * \brief +*/ + + +uint8_t +sg_get_state() +{ + uint8_t state; + /* Pull up -> Pin high = Relay Open */ + if ((~PIND & RELAY1_FB) && (~PIND & RELAY2_FB)){ + state = 4; + }else if (~PIND & RELAY1_FB){ + state = 1; + } else if (~PIND & RELAY2_FB){ + state = 3; + } else { + state = 2; + } + return state; +} +/** + * \brief +*/ + +void +sg_switch_difference(uint8_t old_state, uint8_t new_state) +{ + switch(old_state) { + case 1: + switch(new_state) { + case 2: + PORTB |= RELAY1_OFF; + PORTB &= ~(RELAY1_ON | RELAY2_ON | RELAY2_OFF); + _delay_us(LATCH_TIME); + PORTB &= ~(RELAY1_OFF); + break; + case 3: + PORTB |= (RELAY1_OFF | RELAY2_ON ); + PORTB &= ~(RELAY1_ON | RELAY2_OFF); + _delay_us(LATCH_TIME); + PORTB &= ~(RELAY1_OFF | RELAY2_ON); + break; + case 4: + PORTB |= RELAY2_ON; + PORTB &= ~(RELAY1_ON | RELAY1_OFF | RELAY2_OFF); + _delay_us(LATCH_TIME); + PORTB &= ~(RELAY2_ON); + break; + } + break; + case 2: + switch(new_state) { + case 1: + PORTB |= RELAY1_ON; + PORTB &= ~(RELAY1_OFF | RELAY2_ON | RELAY2_OFF); + _delay_us(LATCH_TIME); + PORTB &= ~(RELAY1_ON); + break; + case 3: + PORTB |= (RELAY2_ON); + PORTB &= ~(RELAY1_ON | RELAY1_OFF | RELAY2_OFF); + _delay_us(LATCH_TIME); + PORTB &= ~(RELAY2_ON); + break; + case 4: + PORTB |= (RELAY1_ON | RELAY2_ON); + PORTB &= ~(RELAY1_OFF | RELAY2_OFF); + _delay_us(LATCH_TIME); + PORTB &= ~(RELAY1_ON | RELAY2_ON); + break; + } + + break; + case 3: + switch(new_state) { + case 1: + PORTB |= (RELAY1_ON | RELAY2_OFF); + PORTB &= ~(RELAY1_OFF | RELAY2_ON); + _delay_us(LATCH_TIME); + PORTB &= ~(RELAY1_ON | RELAY2_OFF); + break; + case 2: + PORTB |= RELAY2_OFF; + PORTB &= ~(RELAY1_ON | RELAY1_OFF | RELAY2_ON); + _delay_us(LATCH_TIME); + PORTB &= ~(RELAY2_OFF); + break; + case 4: + PORTB |= RELAY1_ON; + PORTB &= ~(RELAY1_OFF | RELAY2_ON | RELAY2_OFF); + _delay_us(LATCH_TIME); + PORTB &= ~(RELAY1_ON); + break; + } + break; + case 4: + switch(new_state) { + case 1: + PORTB |= RELAY2_OFF; + PORTB &= ~(RELAY1_ON | RELAY1_OFF | RELAY2_ON); + _delay_us(LATCH_TIME); + PORTB &= ~(RELAY2_OFF); + break; + case 2: + PORTB |= (RELAY1_OFF | RELAY2_OFF); + PORTB &= ~(RELAY1_ON | RELAY2_ON ); + _delay_us(LATCH_TIME); + PORTB &= ~(RELAY1_OFF | RELAY2_OFF); + break; + case 3: + PORTB |= RELAY1_OFF; + PORTB &= ~(RELAY1_ON | RELAY2_ON | RELAY2_OFF); + _delay_us(LATCH_TIME); + PORTB &= ~(RELAY1_OFF); + break; + } + break; + } +} + diff --git a/cpu/avr/dev/sg-ready.h b/cpu/avr/dev/sg-ready.h new file mode 100644 index 000000000..644df6109 --- /dev/null +++ b/cpu/avr/dev/sg-ready.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015 Bernhard Trinnes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holders nor the names of + * 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 OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * + * \brief + * + * + * \author + * Bernhard Trinnes bernhard.trinnes@guh.guru + * + */ + +#ifndef __SGREADY_H__ +#define __SGREADY_H__ + +#include + +/* Some other io settings of io include define DDRxx as DDxx */ +#ifndef DDRB0 +#define DDRB0 DDB0 +#define DDRB1 DDB1 +#define DDRB2 DDB2 +#define DDRB3 DDB3 +#define DDRB4 DDB4 +#define DDRB5 DDB5 +#define DDRB6 DDB6 +#define DDRB7 DDB7 +#endif + +#ifndef DDRD0 +#define DDRD0 DDD0 +#define DDRD1 DDD1 +#define DDRD2 DDD2 +#define DDRD3 DDD3 +#define DDRD4 DDD4 +#define DDRD5 DDD5 +#define DDRD6 DDD6 +#define DDRD7 DDD7 +#endif + +#define LATCH_TIME 3000 // time in micro seconds + +#define RELAY1_ON (1< #include "atmega128rfa1_registermap.h" +#elif defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) +#include "atmega256rfr2_registermap.h" #else #include "at86rf230_registermap.h" #endif @@ -88,7 +89,7 @@ volatile extern signed char rf230_last_rssi; /*============================ IMPLEMENTATION ================================*/ -#if defined(__AVR_ATmega128RFA1__) +#if defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) /* AVR1281 with internal RF231 radio */ #include @@ -158,8 +159,7 @@ inline uint8_t spiWrite(uint8_t byte) /** \brief This function initializes the Hardware Abstraction Layer. */ -#if defined(__AVR_ATmega128RFA1__) - +#if defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) void hal_init(void) { @@ -241,8 +241,7 @@ hal_init(void) } #endif /* !__AVR__ */ - -#if defined(__AVR_ATmega128RFA1__) +#if defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) /* Hack for internal radio registers. hal_register_read and hal_register_write are handled through defines, but the preprocesser can't parse a macro containing another #define with multiple arguments, e.g. using @@ -279,7 +278,7 @@ hal_subregister_write(uint16_t address, uint8_t mask, uint8_t position, HAL_LEAVE_CRITICAL_REGION(); } -#else /* defined(__AVR_ATmega128RFA1__) */ +#else /* defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) */ /*----------------------------------------------------------------------------*/ /** \brief This function reads data from one of the radio transceiver's registers. * @@ -383,7 +382,7 @@ hal_subregister_write(uint8_t address, uint8_t mask, uint8_t position, /* Write the modified register value. */ hal_register_write(address, value); } -#endif /* defined(__AVR_ATmega128RFA1__) */ +#endif /* defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) */ /*----------------------------------------------------------------------------*/ /** \brief Transfer a frame from the radio transceiver to a RAM buffer * @@ -399,7 +398,7 @@ hal_subregister_write(uint8_t address, uint8_t mask, uint8_t position, void hal_frame_read(hal_rx_frame_t *rx_frame) { -#if defined(__AVR_ATmega128RFA1__) +#if defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) uint8_t frame_length,*rx_data,*rx_buffer; @@ -431,8 +430,8 @@ hal_frame_read(hal_rx_frame_t *rx_frame) * Else show the crc has passed the hardware check. */ rx_frame->crc = true; - -#else /* defined(__AVR_ATmega128RFA1__) */ + +#else /* defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega256RFR2__) */ uint8_t frame_length, *rx_data; @@ -487,7 +486,8 @@ hal_frame_read(hal_rx_frame_t *rx_frame) HAL_SPI_TRANSFER_CLOSE(); -#endif /* defined(__AVR_ATmega128RFA1__) */ + +#endif /* defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) */ } /*----------------------------------------------------------------------------*/ @@ -500,7 +500,7 @@ hal_frame_read(hal_rx_frame_t *rx_frame) void hal_frame_write(uint8_t *write_buffer, uint8_t length) { -#if defined(__AVR_ATmega128RFA1__) +#if defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) uint8_t *tx_buffer; tx_buffer=(uint8_t *)0x180; //start of fifo in i/o space /* Write frame length, including the two byte checksum */ @@ -518,7 +518,7 @@ hal_frame_write(uint8_t *write_buffer, uint8_t length) #endif do _SFR_MEM8(tx_buffer++)= *write_buffer++; while (--length); -#else /* defined(__AVR_ATmega128RFA1__) */ +#else /* defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) */ /* Optionally truncate length to maximum frame length. * Not doing this is a fast way to know when the application needs fixing! */ @@ -540,7 +540,7 @@ hal_frame_write(uint8_t *write_buffer, uint8_t length) do HAL_SPI_TRANSFER(*write_buffer++); while (--length); HAL_SPI_TRANSFER_CLOSE(); -#endif /* defined(__AVR_ATmega128RFA1__) */ +#endif /* defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) */ } /*----------------------------------------------------------------------------*/ @@ -632,7 +632,7 @@ volatile char rf230interruptflag; #define INTERRUPTDEBUG(arg) #endif -#if defined(__AVR_ATmega128RFA1__) +#if defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) /* The atmega128rfa1 has individual interrupts for the integrated radio' * Whichever are enabled by the RF230 driver must be present even if not used! */ @@ -715,7 +715,7 @@ ISR(TRX24_CCA_ED_DONE_vect) rf230_ccawait=0; } -#else /* defined(__AVR_ATmega128RFA1__) */ +#else /* defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) */ /* Separate RF230 has a single radio interrupt and the source must be read from the IRQ_STATUS register */ HAL_RF230_ISR() { @@ -805,7 +805,7 @@ HAL_RF230_ISR() ; } } -#endif /* defined(__AVR_ATmega128RFA1__) */ +#endif /* defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) */ # endif /* defined(DOXYGEN) */ /** @} */ diff --git a/cpu/avr/radio/rf230bb/rf230bb.c b/cpu/avr/radio/rf230bb/rf230bb.c index d00a24d72..a6b7572cf 100644 --- a/cpu/avr/radio/rf230bb/rf230bb.c +++ b/cpu/avr/radio/rf230bb/rf230bb.c @@ -212,7 +212,7 @@ static unsigned long total_time_for_transmission, total_transmission_len; static int num_transmissions; #endif -#if defined(__AVR_ATmega128RFA1__) +#if defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) volatile uint8_t rf230_wakewait, rf230_txendwait, rf230_ccawait; #endif @@ -433,7 +433,21 @@ rf230_waitidle(void) } } -/*----------------------------------------------------------------------------*/ +/* Set reduced power consumption for AtMegaXXXRFR2 MCU's. See AT02594 */ + +static uint8_t rpc = 0xFF; /* Default max power save */ +void +rf230_set_rpc(uint8_t data) +{ + rpc = data; +} + +uint8_t +rf230_get_rpc(void) +{ + return rpc; +} + /** \brief This function will change the current state of the radio * transceiver's internal state machine. * @@ -507,6 +521,10 @@ radio_set_trx_state(uint8_t new_state) /* When the PLL is active most states can be reached in 1us. However, from */ /* TRX_OFF the PLL needs time to activate. */ if (current_state == TRX_OFF){ + +#if defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) + hal_subregister_write(SR_TRX_RPC, rpc); /* Enable RPC features */ +#endif delay_us(TIME_TRX_OFF_TO_PLL_ACTIVE); } else { delay_us(TIME_STATE_TRANSITION_PLL_ACTIVE); @@ -535,7 +553,7 @@ rf230_set_promiscuous_mode(bool isPromiscuous) { #if RF230_CONF_AUTOACK is_promiscuous = isPromiscuous; /* TODO: Figure out when to pass promisc state to 802.15.4 */ -// radio_set_trx_state(is_promiscuous?RX_ON:RX_AACK_ON); + radio_set_trx_state(is_promiscuous?RX_ON:RX_AACK_ON); #endif } @@ -585,7 +603,7 @@ radio_on(void) #if RF230BB_CONF_LEDONPORTE1 PORTE|=(1<1 { uint8_t i; @@ -1658,7 +1714,7 @@ rf230_cca(void) /* Start the CCA, wait till done, return result */ /* Note reading the TRX_STATUS register clears both CCA_STATUS and CCA_DONE bits */ -#if defined(__AVR_ATmega128RFA1__) +#if defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) #if 1 //interrupt method /* Disable rx transitions to busy (RX_PDT_BIT) */ /* Note: for speed this resets rx threshold to the compiled default */ diff --git a/cpu/avr/radio/rf230bb/rf230bb.h b/cpu/avr/radio/rf230bb/rf230bb.h index 30de9a1e5..c441e09ab 100644 --- a/cpu/avr/radio/rf230bb/rf230bb.h +++ b/cpu/avr/radio/rf230bb/rf230bb.h @@ -57,6 +57,8 @@ #include "hal.h" #if defined(__AVR_ATmega128RFA1__) #include "atmega128rfa1_registermap.h" +#elif defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) +#include "atmega256rfr2_registermap.h" #else #include "at86rf230_registermap.h" #endif @@ -68,7 +70,7 @@ #define RF230_REVB ( 2 ) #define SUPPORTED_MANUFACTURER_ID ( 31 ) -#if defined(__AVR_ATmega128RFA1__) +#if defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega128RFR2__) || defined(__AVR_ATmega256RFR2__) #define RF230_SUPPORTED_INTERRUPT_MASK ( 0xFF ) #else /* RF230 does not support RX_START interrupts in extended mode, but it seems harmless to always enable it. */ @@ -215,6 +217,8 @@ uint8_t rf230_get_channel(void); void rf230_set_pan_addr(unsigned pan,unsigned addr,const uint8_t ieee_addr[8]); void rf230_set_txpower(uint8_t power); uint8_t rf230_get_txpower(void); +void rf230_set_rpc(uint8_t rpc); +uint8_t rf230_get_rpc(void); void rf230_set_promiscuous_mode(bool isPromiscuous); bool rf230_is_ready_to_send(); diff --git a/cpu/cc2538/Makefile.cc2538 b/cpu/cc2538/Makefile.cc2538 index a11dc2b87..218f05200 100644 --- a/cpu/cc2538/Makefile.cc2538 +++ b/cpu/cc2538/Makefile.cc2538 @@ -51,7 +51,7 @@ CONTIKI_CPU_DIRS += ../arm/common/dbg-io CONTIKI_CPU_DIRS += ../cc253x/usb/common ../cc253x/usb/common/cdc-acm ### CPU-dependent source files -CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c uart.c watchdog.c +CONTIKI_CPU_SOURCEFILES += soc.c clock.c rtimer-arch.c uart.c watchdog.c CONTIKI_CPU_SOURCEFILES += nvic.c cpu.c sys-ctrl.c gpio.c ioc.c spi.c adc.c CONTIKI_CPU_SOURCEFILES += crypto.c aes.c ecb.c cbc.c ctr.c cbc-mac.c gcm.c CONTIKI_CPU_SOURCEFILES += ccm.c sha256.c @@ -115,8 +115,7 @@ CUSTOM_RULE_LINK=1 cp $< $@ ### This rule is used to generate the correct linker script -LDGENFLAGS += $(addprefix -D,$(subst $(COMMA), ,$(DEFINES))) -LDGENFLAGS += $(addprefix -I,$(SOURCEDIRS)) +LDGENFLAGS += $(CFLAGS) LDGENFLAGS += -imacros "contiki-conf.h" -imacros "dev/cc2538-dev.h" LDGENFLAGS += -imacros "dev/flash.h" -imacros "cfs-coffee-arch.h" LDGENFLAGS += -x c -P -E diff --git a/cpu/cc2538/cc2538.lds b/cpu/cc2538/cc2538.lds index 189968717..ef465409e 100644 --- a/cpu/cc2538/cc2538.lds +++ b/cpu/cc2538/cc2538.lds @@ -35,8 +35,7 @@ */ MEMORY { - FLASH_FW (rx) : ORIGIN = COFFEE_START + COFFEE_SIZE, - LENGTH = FLASH_CCA_ADDR - (COFFEE_START + COFFEE_SIZE) + FLASH_FW (rx) : ORIGIN = FLASH_FW_ADDR, LENGTH = FLASH_FW_SIZE FLASH_CCA (RX) : ORIGIN = FLASH_CCA_ADDR, LENGTH = FLASH_CCA_SIZE /* diff --git a/cpu/cc2538/cfs-coffee-arch.h b/cpu/cc2538/cfs-coffee-arch.h index 9d53994e5..a0bf3dd75 100644 --- a/cpu/cc2538/cfs-coffee-arch.h +++ b/cpu/cc2538/cfs-coffee-arch.h @@ -102,6 +102,8 @@ /** Maximal amount of log table entries read in one batch */ #ifdef COFFEE_CONF_LOG_TABLE_LIMIT #define COFFEE_LOG_TABLE_LIMIT COFFEE_CONF_LOG_TABLE_LIMIT +#else +#define COFFEE_LOG_TABLE_LIMIT 16 #endif /** Default reserved file size */ #ifdef COFFEE_CONF_DYN_SIZE @@ -112,6 +114,8 @@ /** Default micro-log size */ #ifdef COFFEE_CONF_LOG_SIZE #define COFFEE_LOG_SIZE COFFEE_CONF_LOG_SIZE +#else +#define COFFEE_LOG_SIZE (4 * COFFEE_PAGE_SIZE) #endif /** Whether Coffee will use micro logs */ #ifdef COFFEE_CONF_MICRO_LOGS diff --git a/cpu/cc2538/dev/aes.c b/cpu/cc2538/dev/aes.c index 429def67b..2b9e11a17 100644 --- a/cpu/cc2538/dev/aes.c +++ b/cpu/cc2538/dev/aes.c @@ -226,12 +226,14 @@ aes_auth_crypt_start(uint32_t ctrl, uint8_t key_area, const void *iv, REG(AES_CTRL_ALG_SEL) = 0x00000000; return CRYPTO_DMA_BUS_ERROR; } + + /* Clear interrupt status */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE; } } - /* Clear interrupt status */ - REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE | - AES_CTRL_INT_CLR_RESULT_AV; + /* Enable result available bit in interrupt enable */ + REG(AES_CTRL_INT_EN) = AES_CTRL_INT_EN_RESULT_AV; if(process != NULL) { crypto_register_process_notification(process); @@ -239,9 +241,6 @@ aes_auth_crypt_start(uint32_t ctrl, uint8_t key_area, const void *iv, nvic_interrupt_enable(NVIC_INT_AES); } - /* Enable result available bit in interrupt enable */ - REG(AES_CTRL_INT_EN) = AES_CTRL_INT_EN_RESULT_AV; - if(data_len != 0) { /* Configure DMAC * Enable DMA channel 0 */ diff --git a/cpu/cc2538/dev/cc2538-aes-128.c b/cpu/cc2538/dev/cc2538-aes-128.c index a1031c2c8..aa5b5e8e6 100644 --- a/cpu/cc2538/dev/cc2538-aes-128.c +++ b/cpu/cc2538/dev/cc2538-aes-128.c @@ -40,6 +40,7 @@ #include "contiki.h" #include "dev/ecb.h" #include "dev/cc2538-aes-128.h" +#include "dev/sys-ctrl.h" #include #include @@ -82,6 +83,7 @@ set_key(const uint8_t *key) CC2538_AES_128_KEY_AREA); if(ret != CRYPTO_SUCCESS) { PRINTF("%s: aes_load_keys() error %u\n", MODULE_NAME, ret); + sys_ctrl_reset(); } restore_crypto(crypto_enabled); @@ -99,13 +101,13 @@ encrypt(uint8_t *plaintext_and_result) plaintext_and_result, AES_128_BLOCK_SIZE, NULL); if(ret != CRYPTO_SUCCESS) { PRINTF("%s: ecb_crypt_start() error %u\n", MODULE_NAME, ret); - restore_crypto(crypto_enabled); - return; + sys_ctrl_reset(); } while((res = ecb_crypt_check_status()) == CRYPTO_PENDING); if(res != CRYPTO_SUCCESS) { PRINTF("%s: ecb_crypt_check_status() error %d\n", MODULE_NAME, res); + sys_ctrl_reset(); } restore_crypto(crypto_enabled); diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index 58b464fc5..52708e0ca 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -119,6 +119,25 @@ static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /** Snif */ #else #define CC2538_RF_AUTOACK 1 #endif +/*--------------------------------------------------------------------------- + * MAC timer + *---------------------------------------------------------------------------*/ +/* Timer conversion */ +#define RADIO_TO_RTIMER(X) ((uint32_t)((uint64_t)(X) * RTIMER_ARCH_SECOND / SYS_CTRL_32MHZ)) + +#define CLOCK_STABLE() do { \ + while ( !(REG(SYS_CTRL_CLOCK_STA) & (SYS_CTRL_CLOCK_STA_XOSC_STB))); \ + } while(0) +/*---------------------------------------------------------------------------*/ +/* Are we currently in poll mode? Disabled by default */ +static uint8_t volatile poll_mode = 0; +/* Do we perform a CCA before sending? Enabled by default. */ +static uint8_t send_on_cca = 1; +static int8_t rssi; +static uint8_t crc_corr; + +void mac_timer_init(void); +uint32_t get_sfd_timestamp(void); /*---------------------------------------------------------------------------*/ static uint8_t rf_flags; static uint8_t rf_channel = CC2538_RF_CHANNEL; @@ -329,6 +348,28 @@ set_frame_filtering(uint8_t enable) } /*---------------------------------------------------------------------------*/ static void +set_poll_mode(uint8_t enable) +{ + poll_mode = enable; + + if(enable) { + mac_timer_init(); + REG(RFCORE_XREG_RFIRQM0) &= ~RFCORE_XREG_RFIRQM0_FIFOP; // mask out FIFOP interrupt source + REG(RFCORE_SFR_RFIRQF0) &= ~RFCORE_SFR_RFIRQF0_FIFOP; // clear pending FIFOP interrupt + nvic_interrupt_disable(NVIC_INT_RF_RXTX); // disable RF interrupts + } else { + REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP; // enable FIFOP interrupt source + nvic_interrupt_enable(NVIC_INT_RF_RXTX); // enable RF interrupts + } +} +/*---------------------------------------------------------------------------*/ +static void +set_send_on_cca(uint8_t enable) +{ + send_on_cca = enable; +} +/*---------------------------------------------------------------------------*/ +static void set_auto_ack(uint8_t enable) { if(enable) { @@ -395,7 +436,9 @@ off(void) /* Wait for ongoing TX to complete (e.g. this could be an outgoing ACK) */ while(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_TX_ACTIVE); - CC2538_RF_CSP_ISFLUSHRX(); + if(!(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP)) { + CC2538_RF_CSP_ISFLUSHRX(); + } /* Don't turn off if we are off as this will trigger a Strobe Error */ if(REG(RFCORE_XREG_RXENABLE) != 0) { @@ -459,10 +502,6 @@ init(void) set_channel(rf_channel); - /* Acknowledge RF interrupts, FIFOP only */ - REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP; - nvic_interrupt_enable(NVIC_INT_RF_RXTX); - /* Acknowledge all RF Error interrupts */ REG(RFCORE_XREG_RFERRM) = RFCORE_XREG_RFERRM_RFERRM; nvic_interrupt_enable(NVIC_INT_RF_ERR); @@ -488,6 +527,8 @@ init(void) */ udma_set_channel_src(CC2538_RF_CONF_RX_DMA_CHAN, RFCORE_SFR_RFDATA); } + + set_poll_mode(poll_mode); process_start(&cc2538_rf_process, NULL); @@ -571,9 +612,11 @@ transmit(unsigned short transmit_len) while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME)); } - if(channel_clear() == CC2538_RF_CCA_BUSY) { - RIMESTATS_ADD(contentiondrop); - return RADIO_TX_COLLISION; + if(send_on_cca) { + if(channel_clear() == CC2538_RF_CCA_BUSY) { + RIMESTATS_ADD(contentiondrop); + return RADIO_TX_COLLISION; + } } /* @@ -630,8 +673,6 @@ read(void *buf, unsigned short bufsize) { uint8_t i; uint8_t len; - uint8_t crc_corr; - int8_t rssi; PRINTF("RF: Read\n"); @@ -731,14 +772,18 @@ read(void *buf, unsigned short bufsize) flush(); #endif - /* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */ - if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) { - if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFO) { - process_poll(&cc2538_rf_process); - } else { - CC2538_RF_CSP_ISFLUSHRX(); + if(!poll_mode) { + /* If FIFOP==1 and FIFO==0 then we had a FIFO overflow at some point. */ + if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFOP) { + if(REG(RFCORE_XREG_FSMSTAT1) & RFCORE_XREG_FSMSTAT1_FIFO) { + process_poll(&cc2538_rf_process); + } else { + CC2538_RF_CSP_ISFLUSHRX(); + } } } + + CC2538_RF_CSP_ISFLUSHRX(); return (len); } @@ -796,6 +841,15 @@ get_value(radio_param_t param, radio_value_t *value) if(REG(RFCORE_XREG_FRMCTRL0) & RFCORE_XREG_FRMCTRL0_AUTOACK) { *value |= RADIO_RX_MODE_AUTOACK; } + if(poll_mode) { + *value |= RADIO_RX_MODE_POLL_MODE; + } + return RADIO_RESULT_OK; + case RADIO_PARAM_TX_MODE: + *value = 0; + if(send_on_cca) { + *value |= RADIO_TX_MODE_SEND_ON_CCA; + } return RADIO_RESULT_OK; case RADIO_PARAM_TXPOWER: *value = get_tx_power(); @@ -806,6 +860,12 @@ get_value(radio_param_t param, radio_value_t *value) case RADIO_PARAM_RSSI: *value = get_rssi(); return RADIO_RESULT_OK; + case RADIO_PARAM_LAST_RSSI: + *value = rssi; + return RADIO_RESULT_OK; + case RADIO_PARAM_LAST_LINK_QUALITY: + *value = crc_corr & LQI_BIT_MASK; + return RADIO_RESULT_OK; case RADIO_CONST_CHANNEL_MIN: *value = CC2538_RF_CHANNEL_MIN; return RADIO_RESULT_OK; @@ -854,13 +914,21 @@ set_value(radio_param_t param, radio_value_t value) return RADIO_RESULT_OK; case RADIO_PARAM_RX_MODE: if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER | - RADIO_RX_MODE_AUTOACK)) { + RADIO_RX_MODE_AUTOACK | + RADIO_RX_MODE_POLL_MODE)) { return RADIO_RESULT_INVALID_VALUE; } set_frame_filtering((value & RADIO_RX_MODE_ADDRESS_FILTER) != 0); set_auto_ack((value & RADIO_RX_MODE_AUTOACK) != 0); + set_poll_mode((value & RADIO_RX_MODE_POLL_MODE) != 0); + return RADIO_RESULT_OK; + case RADIO_PARAM_TX_MODE: + if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) { + return RADIO_RESULT_INVALID_VALUE; + } + set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0); return RADIO_RESULT_OK; case RADIO_PARAM_TXPOWER: if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) { @@ -895,6 +963,15 @@ get_object(radio_param_t param, void *dest, size_t size) return RADIO_RESULT_OK; } + + if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) { + if(size != sizeof(rtimer_clock_t) || !dest) { + return RADIO_RESULT_INVALID_VALUE; + } + *(rtimer_clock_t*)dest = get_sfd_timestamp(); + return RADIO_RESULT_OK; + } + return RADIO_RESULT_NOT_SUPPORTED; } /*---------------------------------------------------------------------------*/ @@ -950,15 +1027,18 @@ PROCESS_THREAD(cc2538_rf_process, ev, data) PROCESS_BEGIN(); while(1) { - PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL); + /* Only if we are not in poll mode oder we are in poll mode and transceiver has to be reset */ + PROCESS_YIELD_UNTIL((!poll_mode || (poll_mode && (rf_flags & RF_MUST_RESET))) && (ev == PROCESS_EVENT_POLL)); - packetbuf_clear(); - len = read(packetbuf_dataptr(), PACKETBUF_SIZE); + if(!poll_mode) { + packetbuf_clear(); + len = read(packetbuf_dataptr(), PACKETBUF_SIZE); - if(len > 0) { - packetbuf_set_datalen(len); + if(len > 0) { + packetbuf_set_datalen(len); - NETSTACK_RDC.input(); + NETSTACK_RDC.input(); + } } /* If we were polled due to an RF error, reset the transceiver */ @@ -995,8 +1075,10 @@ void cc2538_rf_rx_tx_isr(void) { ENERGEST_ON(ENERGEST_TYPE_IRQ); - - process_poll(&cc2538_rf_process); + + if(!poll_mode) { + process_poll(&cc2538_rf_process); + } /* We only acknowledge FIFOP so we can safely wipe out the entire SFR */ REG(RFCORE_SFR_RFIRQF0) = 0; @@ -1045,4 +1127,44 @@ cc2538_rf_set_promiscous_mode(char p) set_frame_filtering(p); } /*---------------------------------------------------------------------------*/ +uint32_t get_sfd_timestamp(void) +{ + uint64_t sfd, timer_val, buffer; + + REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMSEL) | 0x00000000; + REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_LATCH_MODE; + timer_val = REG(RFCORE_SFR_MTM0) & RFCORE_SFR_MTM0_MTM0; + timer_val |= ((REG(RFCORE_SFR_MTM1) & RFCORE_SFR_MTM1_MTM1) << 8); + REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMOVFSEL) | 0x00000000; + timer_val |= ((REG(RFCORE_SFR_MTMOVF0) & RFCORE_SFR_MTMOVF0_MTMOVF0) << 16); + timer_val |= ((REG(RFCORE_SFR_MTMOVF1) & RFCORE_SFR_MTMOVF1_MTMOVF1) << 24); + buffer = REG(RFCORE_SFR_MTMOVF2) & RFCORE_SFR_MTMOVF2_MTMOVF2; + timer_val |= (buffer << 32); + + REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMSEL) | 0x00000001; + REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_LATCH_MODE; + sfd = REG(RFCORE_SFR_MTM0) & RFCORE_SFR_MTM0_MTM0; + sfd |= ((REG(RFCORE_SFR_MTM1) & RFCORE_SFR_MTM1_MTM1) << 8); + REG(RFCORE_SFR_MTMSEL) = (REG(RFCORE_SFR_MTMSEL) & ~RFCORE_SFR_MTMSEL_MTMOVFSEL) | 0x00000010; + sfd |= ((REG(RFCORE_SFR_MTMOVF0) & RFCORE_SFR_MTMOVF0_MTMOVF0) << 16); + sfd |= ((REG(RFCORE_SFR_MTMOVF1) & RFCORE_SFR_MTMOVF1_MTMOVF1) << 24); + buffer = REG(RFCORE_SFR_MTMOVF2) & RFCORE_SFR_MTMOVF2_MTMOVF2; + sfd |= (buffer << 32); + + return (RTIMER_NOW() - RADIO_TO_RTIMER(timer_val - sfd)); +} +/*---------------------------------------------------------------------------*/ +void mac_timer_init(void) +{ + CLOCK_STABLE(); + REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_SYNC; + REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_RUN; + while(!(REG(RFCORE_SFR_MTCTRL) & RFCORE_SFR_MTCTRL_STATE)); + REG(RFCORE_SFR_MTCTRL) &= ~RFCORE_SFR_MTCTRL_RUN; + while(REG(RFCORE_SFR_MTCTRL) & RFCORE_SFR_MTCTRL_STATE); + REG(RFCORE_SFR_MTCTRL) |= RFCORE_SFR_MTCTRL_SYNC; + REG(RFCORE_SFR_MTCTRL) |= (RFCORE_SFR_MTCTRL_RUN); + while(!(REG(RFCORE_SFR_MTCTRL) & RFCORE_SFR_MTCTRL_STATE)); +} +/*---------------------------------------------------------------------------*/ /** @} */ diff --git a/cpu/cc2538/dev/flash.h b/cpu/cc2538/dev/flash.h index 6af19723e..49db85b20 100644 --- a/cpu/cc2538/dev/flash.h +++ b/cpu/cc2538/dev/flash.h @@ -48,6 +48,7 @@ #define FLASH_H_ #include "dev/cc2538-dev.h" +#include "cfs-coffee-arch.h" #include /*---------------------------------------------------------------------------*/ @@ -90,6 +91,23 @@ #define FLASH_CCA_LOCK_DEBUG_BIT 7 /**< Debug lock bit position in the corresponding lock byte */ /** @} */ /*---------------------------------------------------------------------------*/ +/** \name Firmware location in flash memory + * @{ + */ +#ifdef FLASH_CONF_FW_ADDR +#define FLASH_FW_ADDR FLASH_CONF_FW_ADDR +#elif !defined(COFFEE_CONF_CUSTOM_PORT) +#define FLASH_FW_ADDR (COFFEE_START + COFFEE_SIZE) +#else +#define FLASH_FW_ADDR CC2538_DEV_FLASH_ADDR +#endif +#ifdef FLASH_CONF_FW_SIZE +#define FLASH_FW_SIZE FLASH_CONF_FW_SIZE +#else +#define FLASH_FW_SIZE (FLASH_CCA_ADDR - FLASH_FW_ADDR) +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ /** \name Flash lock bit page and CCA layout * @{ */ diff --git a/cpu/cc2538/dev/sys-ctrl.c b/cpu/cc2538/dev/sys-ctrl.c index c2e8777ad..92592b942 100644 --- a/cpu/cc2538/dev/sys-ctrl.c +++ b/cpu/cc2538/dev/sys-ctrl.c @@ -50,6 +50,26 @@ #define SYS_CTRL_OSCS SYS_CTRL_CLOCK_CTRL_OSC32K #endif /*---------------------------------------------------------------------------*/ +int +sys_ctrl_get_reset_cause(void) +{ + return (REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_RST) >> + SYS_CTRL_CLOCK_STA_RST_S; +} +/*---------------------------------------------------------------------------*/ +const char * +sys_ctrl_get_reset_cause_str(void) +{ + static const char *reset_cause[] = { + "POR", + "External reset", + "WDT", + "CLD or software reset" + }; + + return reset_cause[sys_ctrl_get_reset_cause()]; +} +/*---------------------------------------------------------------------------*/ void sys_ctrl_init() { diff --git a/cpu/cc2538/dev/sys-ctrl.h b/cpu/cc2538/dev/sys-ctrl.h index 3fda071fe..22dece434 100644 --- a/cpu/cc2538/dev/sys-ctrl.h +++ b/cpu/cc2538/dev/sys-ctrl.h @@ -115,6 +115,11 @@ #define SYS_CTRL_CLOCK_STA_OSC32K_CALDIS 0x02000000 #define SYS_CTRL_CLOCK_STA_OSC32K 0x01000000 #define SYS_CTRL_CLOCK_STA_RST 0x00C00000 +#define SYS_CTRL_CLOCK_STA_RST_S 22 +#define SYS_CTRL_CLOCK_STA_RST_POR 0 +#define SYS_CTRL_CLOCK_STA_RST_EXT 1 +#define SYS_CTRL_CLOCK_STA_RST_WDT 2 +#define SYS_CTRL_CLOCK_STA_RST_CLD_SW 3 #define SYS_CTRL_CLOCK_STA_SOURCE_CHANGE 0x00100000 #define SYS_CTRL_CLOCK_STA_XOSC_STB 0x00080000 #define SYS_CTRL_CLOCK_STA_HSOSC_STB 0x00040000 @@ -302,6 +307,17 @@ /** \name SysCtrl functions * @{ */ + +/** \brief Gets the cause of the last reset + * \return A \c SYS_CTRL_CLOCK_STA_RST_x reset cause + */ +int sys_ctrl_get_reset_cause(void); + +/** \brief Gets a string describing the cause of the last reset + * \return Last reset cause as a string + */ +const char *sys_ctrl_get_reset_cause_str(void); + /** \brief Initialises the System Control Driver. The main purpose of this * function is to power up and select clocks and oscillators * \note This function depends on ioc_init() having been called beforehand. */ diff --git a/cpu/cc2538/rtimer-arch.h b/cpu/cc2538/rtimer-arch.h index ddb020af1..45ebc5c5d 100644 --- a/cpu/cc2538/rtimer-arch.h +++ b/cpu/cc2538/rtimer-arch.h @@ -65,6 +65,20 @@ #define RTIMER_ARCH_SECOND 32768 +/* Do the math in 32bits to save precision. + * Round to nearest integer rather than truncate. */ +#define US_TO_RTIMERTICKS(US) ((US) >= 0 ? \ + (((int32_t)(US) * (RTIMER_ARCH_SECOND) + 500000) / 1000000L) : \ + ((int32_t)(US) * (RTIMER_ARCH_SECOND) - 500000) / 1000000L) + +#define RTIMERTICKS_TO_US(T) ((T) >= 0 ? \ + (((int32_t)(T) * 1000000L + ((RTIMER_ARCH_SECOND) / 2)) / (RTIMER_ARCH_SECOND)) : \ + ((int32_t)(T) * 1000000L - ((RTIMER_ARCH_SECOND) / 2)) / (RTIMER_ARCH_SECOND)) + +/* A 64-bit version because the 32-bit one cannot handle T >= 4295 ticks. + Intended only for positive values of T. */ +#define RTIMERTICKS_TO_US_64(T) ((uint32_t)(((uint64_t)(T) * 1000000 + ((RTIMER_ARCH_SECOND) / 2)) / (RTIMER_ARCH_SECOND))) + /** \sa RTIMER_NOW() */ rtimer_clock_t rtimer_arch_now(void); diff --git a/cpu/cc2538/soc.c b/cpu/cc2538/soc.c new file mode 100644 index 000000000..58ebb3692 --- /dev/null +++ b/cpu/cc2538/soc.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2016, Benoît Thébaudeau + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc2538-soc + * @{ + * + * \file + * Implementation of the cc2538 SoC driver + */ +#include "contiki-conf.h" +#include "dev/rom-util.h" +#include "dev/sys-ctrl.h" +#include "reg.h" +#include "soc.h" + +#include +#include +/*----------------------------------------------------------------------------*/ +#define DIECFG0 0x400d3014 +#define DIECFG0_SRAM_SIZE_OFS 7 +#define DIECFG0_SRAM_SIZE_SZ 3 +#define DIECFG0_SRAM_SIZE_MSK (((1 << DIECFG0_SRAM_SIZE_SZ) - 1) << \ + DIECFG0_SRAM_SIZE_OFS) +#define DIECFG2 0x400d301c +#define DIECFG2_DIE_REV_OFS 8 +#define DIECFG2_DIE_REV_SZ 8 +#define DIECFG2_DIE_REV_MSK (((1 << DIECFG2_DIE_REV_SZ) - 1) << \ + DIECFG2_DIE_REV_OFS) +#define DIECFG2_AES_EN 0x00000002 +#define DIECFG2_PKA_EN 0x00000001 +/*----------------------------------------------------------------------------*/ +uint8_t +soc_get_rev(void) +{ + uint8_t rev = (REG(DIECFG2) & DIECFG2_DIE_REV_MSK) >> DIECFG2_DIE_REV_OFS; + + /* PG1.0 is encoded as 0x00. */ + if(!(rev >> 4)) + rev += 0x10; + return rev; +} +/*----------------------------------------------------------------------------*/ +uint32_t +soc_get_sram_size(void) +{ + uint32_t size_code = (REG(DIECFG0) & DIECFG0_SRAM_SIZE_MSK) >> + DIECFG0_SRAM_SIZE_OFS; + + return size_code <= 1 ? (2 - size_code) << 13 : 32 << 10; +} +/*----------------------------------------------------------------------------*/ +uint32_t +soc_get_features(void) +{ + return REG(DIECFG2) & (DIECFG2_AES_EN | DIECFG2_PKA_EN); +} +/*----------------------------------------------------------------------------*/ +void +soc_print_info(void) +{ + uint8_t rev = soc_get_rev(); + uint32_t features = soc_get_features(); + + printf("CC2538: ID: 0x%04lx, rev.: PG%d.%d, Flash: %lu KiB, SRAM: %lu KiB, " + "AES/SHA: %u, ECC/RSA: %u\n" + "System clock: %lu Hz\n" + "I/O clock: %lu Hz\n" + "Reset cause: %s\n", + rom_util_get_chip_id(), + rev >> 4, rev & 0x0f, + rom_util_get_flash_size() >> 10, + soc_get_sram_size() >> 10, + !!(features & SOC_FEATURE_AES_SHA), + !!(features & SOC_FEATURE_ECC_RSA), + sys_ctrl_get_sys_clock(), + sys_ctrl_get_io_clock(), + sys_ctrl_get_reset_cause_str()); +} + +/** @} */ diff --git a/cpu/cc2538/soc.h b/cpu/cc2538/soc.h new file mode 100644 index 000000000..d8bf939de --- /dev/null +++ b/cpu/cc2538/soc.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016, Benoît Thébaudeau + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc2538 + * @{ + * + * \defgroup cc2538-soc cc2538 SoC + * + * Driver for the cc2538 SoC + * @{ + * + * \file + * Header file with macro and function declarations for the cc2538 SoC + */ +#ifndef SOC_H_ +#define SOC_H_ + +#include "contiki-conf.h" + +#include +/*----------------------------------------------------------------------------*/ +/** \name SoC features + * @{ + */ +#define SOC_FEATURE_AES_SHA 0x00000002 /**< Security HW AES/SHA */ +#define SOC_FEATURE_ECC_RSA 0x00000001 /**< Security HW ECC/RSA */ +/** @} */ +/*----------------------------------------------------------------------------*/ +/** \name SoC functions + * @{ + */ + +/** \brief Gets the SoC revision + * \return The SoC revision as a byte with nibbles representing the major and + * minor revisions + */ +uint8_t soc_get_rev(void); + +/** \brief Gets the SRAM size of the SoC + * \return The SRAM size in bytes + */ +uint32_t soc_get_sram_size(void); + +/** \brief Gets the hardware features of the SoC that are enabled + * \return The enabled hardware features as a bitmask of \c SOC_FEATURE_x values + */ +uint32_t soc_get_features(void); + +/** \brief Prints SoC information */ +void soc_print_info(void); + +/** @} */ + +#endif /* SOC_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx b/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx index f6ac275da..6922b45fc 100644 --- a/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx +++ b/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx @@ -68,8 +68,8 @@ CONTIKI_CPU_DIRS += ../arm/common/dbg-io ### CPU-dependent source files CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c soc-rtc.c uart.c -CONTIKI_CPU_SOURCEFILES += contiki-watchdog.c -CONTIKI_CPU_SOURCEFILES += putchar.c ieee-addr.c batmon-sensor.c +CONTIKI_CPU_SOURCEFILES += contiki-watchdog.c aux-ctrl.c +CONTIKI_CPU_SOURCEFILES += putchar.c ieee-addr.c batmon-sensor.c adc-sensor.c CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c cc26xx-uart.c lpm.c CONTIKI_CPU_SOURCEFILES += gpio-interrupt.c oscillators.c CONTIKI_CPU_SOURCEFILES += rf-core.c rf-ble.c ieee-mode.c @@ -81,6 +81,15 @@ CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) $(DEBUG_IO_SOURCEFILES) TARGET_START_SOURCEFILES += fault-handlers.c $(TI_XXWARE_STARTUP_SRCS) TARGET_STARTFILES = $(addprefix $(OBJECTDIR)/,$(call oname, $(TARGET_START_SOURCEFILES))) +PYTHON = python +BSL_FLAGS += -e -w -v + +ifdef PORT + BSL_FLAGS += -p $(PORT) +endif + +BSL = $(CONTIKI)/tools/cc2538-bsl/cc2538-bsl.py + ### Don't treat the .elf as intermediate .PRECIOUS: %.elf %.hex %.bin @@ -125,3 +134,31 @@ STACK_SIZE = 0 @$(SIZE) -A $< | egrep "data|bss" | awk '{s+=$$2} END {s=s+$(STACK_SIZE); f=$(RAM_SIZE)-s; printf "[RAM] used %6d, free %6d\n",s,f;}' @$(SIZE) -A $< | egrep "text|isr_vector" | awk '{s+=$$2} END {f=$(FLASH_SIZE)-s; printf "[Flash] used %6d, free %6d\n",s,f;}' +ifeq ($(BOARD_SUPPORTS_BSL),1) +%.upload: %.bin +ifeq ($(wildcard $(BSL)), ) + @echo "ERROR: Could not find the cc2538-bsl script. Did you run 'git submodule update --init' ?" +else + $(PYTHON) $(BSL) $(BSL_FLAGS) $< +endif +else +%.upload: + @echo "This board cannot be programmed through the ROM bootloader and therefore does not support the .upload target." +endif + +# Check if we are running under Windows +ifeq ($(HOST_OS),Windows) + SERIALDUMP ?= $(CONTIKI)/tools/sky/serialdump-windows +else +ifeq ($(HOST_OS),Darwin) + SERIALDUMP ?= $(CONTIKI)/tools/sky/serialdump-macos +else + # Else assume Linux + SERIALDUMP ?= $(CONTIKI)/tools/sky/serialdump-linux +endif +endif + +UART_BAUDRATE = 115200 + +login: + $(SERIALDUMP) -b$(UART_BAUDRATE) $(PORT) diff --git a/cpu/cc26xx-cc13xx/clock.c b/cpu/cc26xx-cc13xx/clock.c index 4f6df056f..85ea6e444 100644 --- a/cpu/cc26xx-cc13xx/clock.c +++ b/cpu/cc26xx-cc13xx/clock.c @@ -118,6 +118,9 @@ clock_init(void) /* GPT0 / Timer B: One shot, PWM interrupt enable */ HWREG(GPT0_BASE + GPT_O_TBMR) = ((TIMER_CFG_B_ONE_SHOT >> 8) & 0xFF) | GPT_TBMR_TBPWMIE; + + /* enable sync with radio timer */ + HWREGBITW(AON_RTC_BASE + AON_RTC_O_CTL, AON_RTC_CTL_RTC_UPD_EN_BITN) = 1; } /*---------------------------------------------------------------------------*/ static void diff --git a/cpu/cc26xx-cc13xx/dev/adc-sensor.c b/cpu/cc26xx-cc13xx/dev/adc-sensor.c new file mode 100644 index 000000000..3ccf90e6d --- /dev/null +++ b/cpu/cc26xx-cc13xx/dev/adc-sensor.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2016, 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 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-adc-sensor + * @{ + * + * \file + * Driver for the CC13xx/CC26xx ADC + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/sensors.h" +#include "dev/adc-sensor.h" +#include "gpio-interrupt.h" +#include "sys/timer.h" +#include "lpm.h" + +#include "ti-lib.h" +#include "driverlib/aux_adc.h" +#include "aux-ctrl.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +static uint8_t channel = ADC_COMPB_IN_AUXIO0; +static bool is_active = false; + +static aux_consumer_module_t adc_aux = { + .clocks = AUX_WUC_ADI_CLOCK | AUX_WUC_ANAIF_CLOCK | AUX_WUC_SMPH_CLOCK +}; +/*---------------------------------------------------------------------------*/ +static int +config(int type, int c) +{ + switch(type) { + case SENSORS_ACTIVE: + is_active = c; + + if(is_active) { + /* Request AUX access, with ADI and SMPH clocks */ + aux_ctrl_register_consumer(&adc_aux); + + ti_lib_aux_adc_select_input(channel); + } else { + aux_ctrl_unregister_consumer(&adc_aux); + } + break; + + case ADC_SENSOR_SET_CHANNEL: + channel = c; + if(is_active) { + ti_lib_aux_adc_select_input(channel); + } + break; + + default: + break; + } + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + if(is_active) { + return 1; + } + break; + default: + break; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + if(type == ADC_SENSOR_VALUE) { + int val; + + if(!is_active) { + puts("ADC not active"); + return 0; + } + + ti_lib_aux_adc_enable_sync(AUXADC_REF_FIXED, AUXADC_SAMPLE_TIME_2P7_US, + AUXADC_TRIGGER_MANUAL); + + ti_lib_aux_adc_gen_manual_trigger(); + val = ti_lib_aux_adc_read_fifo(); + + ti_lib_aux_adc_disable(); + + return val; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(adc_sensor, ADC_SENSOR, value, config, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc26xx-cc13xx/dev/adc-sensor.h b/cpu/cc26xx-cc13xx/dev/adc-sensor.h new file mode 100644 index 000000000..fd8f71537 --- /dev/null +++ b/cpu/cc26xx-cc13xx/dev/adc-sensor.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2016, 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 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 + * @{ + * + * \defgroup cc26xx-adc-sensor CC13xx/CC26xx ADC Sensor + * @{ + * + * \file + * Header file for the CC13xx/CC26xx ADC driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef ADC_SENSOR_H_ +#define ADC_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define ADC_SENSOR "ADC" +/*---------------------------------------------------------------------------*/ +#define ADC_SENSOR_VALUE 0 +/*---------------------------------------------------------------------------*/ +/* configuration commands */ +#define ADC_SENSOR_SET_CHANNEL 1 /* takes ADC_COMPB_IN_AUXIxx as parameter */ +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor adc_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* ADC_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx-cc13xx/dev/aux-ctrl.c b/cpu/cc26xx-cc13xx/dev/aux-ctrl.c new file mode 100644 index 000000000..eb316d3df --- /dev/null +++ b/cpu/cc26xx-cc13xx/dev/aux-ctrl.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016, University of Bristol - http://www.bris.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 copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/aux-ctrl.h" +#include "lib/list.h" + +#include "ti-lib.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +LIST(consumers_list); +/*---------------------------------------------------------------------------*/ +void +aux_ctrl_register_consumer(aux_consumer_module_t *consumer) +{ + bool interrupts_disabled = ti_lib_int_master_disable(); + + list_add(consumers_list, consumer); + + aux_ctrl_power_up(); + + ti_lib_aux_wuc_clock_enable(consumer->clocks); + while(ti_lib_aux_wuc_clock_status(consumer->clocks) != AUX_WUC_CLOCK_READY); + + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } +} +/*---------------------------------------------------------------------------*/ +void +aux_ctrl_unregister_consumer(aux_consumer_module_t *consumer) +{ + bool interrupts_disabled = ti_lib_int_master_disable(); + + list_remove(consumers_list, consumer); + + aux_ctrl_power_down(false); + + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } +} +/*---------------------------------------------------------------------------*/ +void +aux_ctrl_power_up() +{ + /* Don't if we have no consumers */ + if(list_head(consumers_list) == NULL) { + return; + } + + ti_lib_aon_wuc_aux_wakeup_event(AONWUC_AUX_WAKEUP); + while(!(ti_lib_aon_wuc_power_status_get() & AONWUC_AUX_POWER_ON)); +} +/*---------------------------------------------------------------------------*/ +void +aux_ctrl_power_down(bool force) +{ + aux_consumer_module_t *consumer; + uint32_t clocks_in_use = 0; + + if(!force) { + /* Visit all modules and release clocks */ + for(consumer = list_head(consumers_list); consumer != NULL; + consumer = consumer->next) { + clocks_in_use |= consumer->clocks; + } + + /* If any clocks are still in use, AUX needs to stay powered and clocked */ + if(clocks_in_use) { + ti_lib_aon_wuc_aux_power_down_config(AONWUC_CLOCK_SRC_LF); + return; + } + } + + /* No clock for AUX in power down */ + ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK); + + /* Disable retention */ + ti_lib_aon_wuc_aux_sram_config(false); + + /* Turn off AUX */ + ti_lib_aon_wuc_aux_wakeup_event(AONWUC_AUX_ALLOW_SLEEP); + ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF); + while(ti_lib_aon_wuc_power_status_get() & AONWUC_AUX_POWER_ON); +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/cc26xx-cc13xx/dev/aux-ctrl.h b/cpu/cc26xx-cc13xx/dev/aux-ctrl.h new file mode 100644 index 000000000..8e65a7844 --- /dev/null +++ b/cpu/cc26xx-cc13xx/dev/aux-ctrl.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2016, University of Bristol - http://www.bris.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 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 + * @{ + * + * \defgroup cc26xx-aux-ctrl CC13xx/CC26xx AUX domain controller + * + * CC13xx/CC26xx AUX domain power management controller + * + * @{ + * + * \file + * Header file for the management of the CC13xx/CC26xx AUX domain + */ +/*---------------------------------------------------------------------------*/ +#ifndef AUX_CTRL_H_ +#define AUX_CTRL_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include "ti-lib.h" + +#include +/*---------------------------------------------------------------------------*/ +/** + * \brief The data structure to be used for modules that require access to AUX + * + * The clocks field should specify the clocks (within AUX) that your module + * requires in order to perform its functionality. Those clocks are an ORd + * value of AUX_WUC_xxxx_CLOCK. For instance, the oscillators module specifies + * AUX_WUC_OSCCTRL_CLOCK | AUX_WUC_SMPH_CLOCK + */ +typedef struct aux_consumer_module { + struct aux_consumer_module *next; + uint32_t clocks; +} aux_consumer_module_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief Register a module that no longer requires access to the AUX power domain + * \param consumer A pointer to the data structure of your AUX consumer + * + * Call this function if you are developing a module that requires access to + * hardware within the AUX PD. Calling this function will achieve a number of + * things: + * + * - It will power up the AUX PD + * - It will enable the AUX clocks that you require + * + * If you call this function, AUX will stay powered-on and clocked during deep + * sleep, and retention will be enabled (so that you can e.g. use the sensor + * controller to monitor peripherals while the main MCU in deep sleep). If you + * do not need AUX enabled during deep sleep, you must release it by calling + * aux_ctrl_unregister_consumer() + * + * \sa aux_ctrl_unregister_consumer + */ +void aux_ctrl_register_consumer(aux_consumer_module_t *consumer); + +/** + * \brief Deregister a module that no longer requires access to the AUX power domain + * \param consumer A pointer to the data structure of your AUX consumer + * + * When your module is finished using features provided from within the AUX + * domain, you should call this function to signal that AUX is no longer + * required, so that the LPM module can power it down in deep sleep. If there + * are no more registered consumers left, this function will also power down + * AUX. + * + * \sa aux_ctrl_register_consumer + * \sa aux_ctrl_power_down + */ +void aux_ctrl_unregister_consumer(aux_consumer_module_t *consumer); + +/** + * \brief Power-up the AUX power domain + * + * This function will power up the AUX power-domain, but only if there are + * registered consumers for it. If there are not, the PD will stay off. + * + * This function will automatically get called by the LPM module whenever the + * chip comes out of deep sleep. + * + * User applications will normally not need to call this function. if you are + * developing a user application that requires access, to AUX, you should + * normally call aux_ctrl_register_consumer(), which will automatically power + * up AUX for you, if it's not already powered. + */ +void aux_ctrl_power_up(void); + +/** + * \brief Power down the AUX power domain + * \param force Force the power down irrespective of registered consumers + * + * This function will shut down the AUX power-domain. + * + * The shutdown is unconditional if force is true. If force is false and there + * are registered consumers, the power-down will be suppressed. + * + * This function will automatically get called by the LPM module whenever the + * chip tries to enter deep sleep or shuts down. + * + * User applications will normally not need to call this function. if you are + * developing a user application that no longer requires access, to AUX, you + * should normally simply release it by calling aux_ctrl_unregister_consumer(). + * If no other consumers are using AUX, then the lpm module will shut it down. + */ +void aux_ctrl_power_down(bool force); +/*---------------------------------------------------------------------------*/ +#endif /* AUX_CTRL_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx-cc13xx/dev/oscillators.c b/cpu/cc26xx-cc13xx/dev/oscillators.c index 99ba8f841..7890a8e55 100644 --- a/cpu/cc26xx-cc13xx/dev/oscillators.c +++ b/cpu/cc26xx-cc13xx/dev/oscillators.c @@ -37,44 +37,18 @@ */ /*---------------------------------------------------------------------------*/ #include "ti-lib.h" +#include "aux-ctrl.h" #include /*---------------------------------------------------------------------------*/ -static uint32_t -osc_interface_en(void) -{ - uint32_t smph_clk_state; - - /* Enable OSC DIG interface to change clock sources */ - ti_lib_osc_interface_enable(); - - /* Save the state of the SMPH clock within AUX */ - smph_clk_state = ti_lib_aux_wuc_clock_status(AUX_WUC_SMPH_CLOCK); - - /* Make sure the SMPH clock within AUX is enabled */ - ti_lib_aux_wuc_clock_enable(AUX_WUC_SMPH_CLOCK); - while(ti_lib_aux_wuc_clock_status(AUX_WUC_SMPH_CLOCK) != AUX_WUC_CLOCK_READY); - - return smph_clk_state; -} -/*---------------------------------------------------------------------------*/ -static void -osc_interface_dis(uint32_t smph_clk_state) -{ - /* If the SMPH clock was off, turn it back off */ - if(smph_clk_state == AUX_WUC_CLOCK_OFF) { - ti_lib_aux_wuc_clock_disable(AUX_WUC_SMPH_CLOCK); - } - - /* Disable OSC DIG interface */ - ti_lib_osc_interface_disable(); -} -/*---------------------------------------------------------------------------*/ void oscillators_select_lf_xosc(void) { - /* Enable the Osc interface and remember the state of the SMPH clock */ - uint32_t smph_clk_state = osc_interface_en(); + /* Request AUX access, with OSCCTRL and SMPH clocks */ + aux_consumer_module_t osc = { + .clocks = AUX_WUC_OSCCTRL_CLOCK | AUX_WUC_SMPH_CLOCK + }; + aux_ctrl_register_consumer(&osc); /* Switch LF clock source to the LF XOSC if required */ if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_XOSC_LF) { @@ -91,15 +65,18 @@ oscillators_select_lf_xosc(void) 0x3); } - /* Restore the SMPH clock and disable the OSC interface */ - osc_interface_dis(smph_clk_state); + /* Release the OSC AUX consumer */ + aux_ctrl_unregister_consumer(&osc); } /*---------------------------------------------------------------------------*/ void oscillators_select_lf_rcosc(void) { - /* Enable the Osc interface and remember the state of the SMPH clock */ - uint32_t smph_clk_state = osc_interface_en(); + /* Request AUX access, with OSCCTRL and SMPH clocks */ + aux_consumer_module_t osc = { + .clocks = AUX_WUC_OSCCTRL_CLOCK | AUX_WUC_SMPH_CLOCK + }; + aux_ctrl_register_consumer(&osc); /* Switch LF clock source to the LF XOSC if required */ if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_RCOSC_LF) { @@ -109,15 +86,18 @@ oscillators_select_lf_rcosc(void) while(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_RCOSC_LF); } - /* Restore the SMPH clock and disable the OSC interface */ - osc_interface_dis(smph_clk_state); + /* Release the OSC AUX consumer */ + aux_ctrl_unregister_consumer(&osc); } /*---------------------------------------------------------------------------*/ void oscillators_request_hf_xosc(void) { - /* Enable the Osc interface and remember the state of the SMPH clock */ - uint32_t smph_clk_state = osc_interface_en(); + /* Request AUX access, with OSCCTRL and SMPH clocks */ + aux_consumer_module_t osc = { + .clocks = AUX_WUC_OSCCTRL_CLOCK | AUX_WUC_SMPH_CLOCK + }; + aux_ctrl_register_consumer(&osc); if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_XOSC_HF) { /* @@ -128,30 +108,36 @@ oscillators_request_hf_xosc(void) ti_lib_osc_clock_source_set(OSC_SRC_CLK_MF | OSC_SRC_CLK_HF, OSC_XOSC_HF); } - /* Restore the SMPH clock and disable the OSC interface */ - osc_interface_dis(smph_clk_state); + /* Release the OSC AUX consumer */ + aux_ctrl_unregister_consumer(&osc); } /*---------------------------------------------------------------------------*/ void oscillators_switch_to_hf_xosc(void) { - /* Enable the Osc interface and remember the state of the SMPH clock */ - uint32_t smph_clk_state = osc_interface_en(); + /* Request AUX access, with OSCCTRL and SMPH clocks */ + aux_consumer_module_t osc = { + .clocks = AUX_WUC_OSCCTRL_CLOCK | AUX_WUC_SMPH_CLOCK + }; + aux_ctrl_register_consumer(&osc); if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_XOSC_HF) { /* Switch the HF clock source (cc26xxware executes this from ROM) */ ti_lib_osc_hf_source_switch(); } - /* Restore the SMPH clock and disable the OSC interface */ - osc_interface_dis(smph_clk_state); + /* Release the OSC AUX consumer */ + aux_ctrl_unregister_consumer(&osc); } /*---------------------------------------------------------------------------*/ void oscillators_switch_to_hf_rc(void) { - /* Enable the Osc interface and remember the state of the SMPH clock */ - uint32_t smph_clk_state = osc_interface_en(); + /* Request AUX access, with OSCCTRL and SMPH clocks */ + aux_consumer_module_t osc = { + .clocks = AUX_WUC_OSCCTRL_CLOCK | AUX_WUC_SMPH_CLOCK + }; + aux_ctrl_register_consumer(&osc); /* Set all clock sources to the HF RC Osc */ ti_lib_osc_clock_source_set(OSC_SRC_CLK_MF | OSC_SRC_CLK_HF, OSC_RCOSC_HF); @@ -162,8 +148,8 @@ oscillators_switch_to_hf_rc(void) ti_lib_osc_hf_source_switch(); } - /* Restore the SMPH clock and disable the OSC interface */ - osc_interface_dis(smph_clk_state); + /* Release the OSC AUX consumer */ + aux_ctrl_unregister_consumer(&osc); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/cpu/cc26xx-cc13xx/dev/soc-rtc.c b/cpu/cc26xx-cc13xx/dev/soc-rtc.c index 08d9a7cce..398f14d6a 100644 --- a/cpu/cc26xx-cc13xx/dev/soc-rtc.c +++ b/cpu/cc26xx-cc13xx/dev/soc-rtc.c @@ -81,11 +81,13 @@ soc_rtc_init(void) ti_lib_aon_rtc_event_clear(AON_RTC_CH0); ti_lib_aon_rtc_event_clear(AON_RTC_CH1); + ti_lib_aon_rtc_event_clear(AON_RTC_CH2); /* Setup the wakeup event */ ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU0, AON_EVENT_RTC_CH0); ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU1, AON_EVENT_RTC_CH1); - ti_lib_aon_rtc_combined_event_config(AON_RTC_CH0 | AON_RTC_CH1); + ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU2, AON_EVENT_RTC_CH2); + ti_lib_aon_rtc_combined_event_config(AON_RTC_CH0 | AON_RTC_CH1 | AON_RTC_CH2); HWREG(AON_RTC_BASE + AON_RTC_O_SEC) = SOC_RTC_START_TICK_COUNT; @@ -123,7 +125,7 @@ soc_rtc_get_next_trigger() void soc_rtc_schedule_one_shot(uint32_t channel, uint32_t ticks) { - if((channel != AON_RTC_CH0) && (channel != AON_RTC_CH1)) { + if((channel != AON_RTC_CH0) && (channel != AON_RTC_CH1) && (channel != AON_RTC_CH2)) { return; } @@ -170,6 +172,12 @@ soc_rtc_isr(void) rtimer_run_next(); } + if(ti_lib_aon_rtc_event_get(AON_RTC_CH2)) { + /* after sleep; since a rtimer is already scheduled, do nothing */ + ti_lib_aon_rtc_channel_disable(AON_RTC_CH2); + HWREG(AON_RTC_BASE + AON_RTC_O_EVFLAGS) = AON_RTC_EVFLAGS_CH2; + } + ENERGEST_OFF(ENERGEST_TYPE_IRQ); } /*---------------------------------------------------------------------------*/ diff --git a/cpu/cc26xx-cc13xx/lpm.c b/cpu/cc26xx-cc13xx/lpm.c index 6af58e899..3253202c2 100644 --- a/cpu/cc26xx-cc13xx/lpm.c +++ b/cpu/cc26xx-cc13xx/lpm.c @@ -46,6 +46,7 @@ #include "lpm.h" #include "sys/energest.h" #include "lib/list.h" +#include "dev/aux-ctrl.h" #include "dev/leds.h" #include "dev/watchdog.h" #include "dev/soc-rtc.h" @@ -53,6 +54,7 @@ #include #include +#include /*---------------------------------------------------------------------------*/ #if ENERGEST_CONF_ON static unsigned long irq_energest = 0; @@ -75,7 +77,13 @@ LIST(modules_list); * Don't consider standby mode if the next AON RTC event is scheduled to fire * in less than STANDBY_MIN_DURATION rtimer ticks */ -#define STANDBY_MIN_DURATION (RTIMER_SECOND >> 11) +#define STANDBY_MIN_DURATION (RTIMER_SECOND / 100) /* 10.0 ms */ + +/* Wake up this much time earlier before the next rtimer */ +#define SLEEP_GUARD_TIME (RTIMER_SECOND / 1000) /* 1.0 ms */ + +#define MAX_SLEEP_TIME RTIMER_SECOND +#define MINIMAL_SAFE_SCHEDULE 8u /*---------------------------------------------------------------------------*/ /* Prototype of a function in clock.c. Called every time we come out of DS */ void clock_update(void); @@ -85,8 +93,8 @@ lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on) { lpm_registered_module_t *module; int i; - uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | io_pull | - wake_on; + uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | io_pull | wake_on; + aux_consumer_module_t aux = { .clocks = AUX_WUC_OSCCTRL_CLOCK }; /* This procedure may not be interrupted */ ti_lib_int_master_disable(); @@ -130,16 +138,16 @@ lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on) ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH); + /* Register an aux-ctrl consumer to avoid powercycling AUX twice in a row */ + aux_ctrl_register_consumer(&aux); oscillators_switch_to_hf_rc(); oscillators_select_lf_rcosc(); - /* Configure clock sources for MCU and AUX: No clock */ + /* Configure clock sources for MCU: No clock */ ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK); - ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK); - /* Disable SRAM and AUX retentions */ + /* Disable SRAM retention */ ti_lib_aon_wuc_mcu_sram_config(0); - ti_lib_aon_wuc_aux_sram_config(false); /* * Request CPU, SYSBYS and VIMS PD off. @@ -152,9 +160,8 @@ lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on) ti_lib_aon_wuc_jtag_power_off(); /* Turn off AUX */ - ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF); + aux_ctrl_power_down(true); ti_lib_aon_wuc_domain_power_down_enable(); - while(ti_lib_aon_wuc_power_status_get() & AONWUC_AUX_POWER_ON); /* * Request MCU VD power off. @@ -217,6 +224,9 @@ wake_up(void) /* Check operating conditions, optimally choose DCDC versus GLDO */ ti_lib_sys_ctrl_dcdc_voltage_conditional_control(); + /* Fire up AUX is the user has requested this */ + aux_ctrl_power_up(); + /* * We may or may not have been woken up by an AON RTC tick. If not, we need * to adjust our software tick counter @@ -232,186 +242,92 @@ wake_up(void) module->wakeup(); } } + +#if CC2650_FAST_RADIO_STARTUP + /* + * Trigger a switch to the XOSC, so that we can subsequently use the RF FS + */ + oscillators_request_hf_xosc(); +#endif } /*---------------------------------------------------------------------------*/ -void -lpm_drop() +static int +setup_sleep_mode(rtimer_clock_t *next_timer) { lpm_registered_module_t *module; uint8_t max_pm = LPM_MODE_MAX_SUPPORTED; - uint8_t module_pm; - clock_time_t next_event; - uint32_t domains = LOCKABLE_DOMAINS; + rtimer_clock_t now = RTIMER_NOW(); + const rtimer_clock_t max_sleep = now + MAX_SLEEP_TIME; - /* Critical. Don't get interrupted! */ - ti_lib_int_master_disable(); + /* next_timer will hold the time of the next system wakeup due to a timer*/ + *next_timer = max_sleep; /* Check if any events fired before we turned interrupts off. If so, abort */ - if(process_nevents()) { - ti_lib_int_master_enable(); - return; + if(LPM_MODE_MAX_SUPPORTED == LPM_MODE_AWAKE || process_nevents()) { + return LPM_MODE_AWAKE; } - if(RTIMER_CLOCK_LT(soc_rtc_get_next_trigger(), - RTIMER_NOW() + STANDBY_MIN_DURATION)) { - ti_lib_int_master_enable(); - lpm_sleep(); - return; + if(ti_lib_aon_rtc_channel_active(AON_RTC_CH0)) { + rtimer_clock_t next_rtimer; + /* find out the timer of the next rtimer interrupt */ + next_rtimer = ti_lib_aon_rtc_compare_value_get(AON_RTC_CH0); + if(RTIMER_CLOCK_LT(next_rtimer, now + 2)) { + return LPM_MODE_AWAKE; + } + if(RTIMER_CLOCK_LT(next_rtimer, now + STANDBY_MIN_DURATION)) { + return LPM_MODE_SLEEP; + } + *next_timer = next_rtimer; + } + + /* also find out the timer of the next etimer */ + if(etimer_pending()) { + int32_t until_next_etimer; + rtimer_clock_t next_etimer; + + until_next_etimer = (int32_t)etimer_next_expiration_time() - (int32_t)clock_time(); + if(until_next_etimer < 1) { + return LPM_MODE_AWAKE; + } + + next_etimer = soc_rtc_last_isr_time() + (until_next_etimer * (RTIMER_SECOND / CLOCK_SECOND)); + if(RTIMER_CLOCK_LT(next_etimer, now + STANDBY_MIN_DURATION)) { + /* ensure that we schedule sleep a minimal number of ticks into the + future */ + soc_rtc_schedule_one_shot(AON_RTC_CH1, now + MINIMAL_SAFE_SCHEDULE); + return LPM_MODE_SLEEP; + } + + if(RTIMER_CLOCK_LT(max_sleep, next_etimer)) { + /* if max_pm is LPM_MODE_SLEEP, we could trigger the watchdog if we slept + for too long. */ + if(RTIMER_CLOCK_LT(max_sleep, *next_timer)) { + soc_rtc_schedule_one_shot(AON_RTC_CH1, max_sleep); + } + } else { + /* Reschedule AON RTC CH1 to fire just in time for the next etimer event */ + soc_rtc_schedule_one_shot(AON_RTC_CH1, next_etimer); + } + + if(RTIMER_CLOCK_LT(next_etimer, *next_timer)) { + /* set `next_timer` to the time the first etimer fires */ + *next_timer = next_etimer; + } } /* Collect max allowed PM permission from interested modules */ for(module = list_head(modules_list); module != NULL; module = module->next) { if(module->request_max_pm) { - module_pm = module->request_max_pm(); + uint8_t module_pm = module->request_max_pm(); if(module_pm < max_pm) { max_pm = module_pm; } } } - /* Reschedule AON RTC CH1 to fire just in time for the next etimer event */ - next_event = etimer_next_expiration_time(); - - if(etimer_pending()) { - next_event = next_event - clock_time(); - soc_rtc_schedule_one_shot(AON_RTC_CH1, soc_rtc_last_isr_time() + - (next_event * (RTIMER_SECOND / CLOCK_SECOND))); - } - - /* Drop */ - if(max_pm == LPM_MODE_SLEEP) { - ti_lib_int_master_enable(); - lpm_sleep(); - } else { - /* - * Notify all registered modules that we are dropping to mode X. We do not - * need to do this for simple sleep. - * - * This is a chance for modules to delay us a little bit until an ongoing - * operation has finished (e.g. uart TX) or to configure themselves for - * deep sleep. - * - * At this stage, we also collect power domain locks, if any. - * The argument to PRCMPowerDomainOff() is a bitwise OR, so every time - * we encounter a lock we just clear the respective bits in the 'domains' - * variable as required by the lock. In the end the domains variable will - * just hold whatever has not been cleared - */ - for(module = list_head(modules_list); module != NULL; - module = module->next) { - if(module->shutdown) { - module->shutdown(max_pm); - } - - /* Clear the bits specified in the lock */ - domains &= ~module->domain_lock; - } - - /* Pat the dog: We don't want it to shout right after we wake up */ - watchdog_periodic(); - - /* Clear unacceptable bits, just in case a lock provided a bad value */ - domains &= LOCKABLE_DOMAINS; - - /* - * Freeze the IOs on the boundary between MCU and AON. We only do this if - * PERIPH is not needed - */ - if(domains & PRCM_DOMAIN_PERIPH) { - ti_lib_aon_ioc_freeze_enable(); - } - - /* - * Among LOCKABLE_DOMAINS, turn off those that are not locked - * - * If domains is != 0, pass it as-is - */ - if(domains) { - ti_lib_prcm_power_domain_off(domains); - } - - /* - * Before entering Deep Sleep, we must switch off the HF XOSC. The HF XOSC - * is predominantly controlled by the RF driver. In a build with radio - * cycling (e.g. ContikiMAC), the RF driver will request the XOSC before - * using the Freq. Synth, and switch back to the RC when it is about to - * turn back off. - * - * If the radio is on, we won't even reach here, and if it's off the HF - * clock source should already be the HF RC. - * - * Nevertheless, request the switch to the HF RC explicitly here. - */ - oscillators_switch_to_hf_rc(); - - /* Configure clock sources for MCU and AUX: No clock */ - ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK); - ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK); - - /* Full RAM retention. */ - ti_lib_aon_wuc_mcu_sram_config(MCU_RAM0_RETENTION | MCU_RAM1_RETENTION | - MCU_RAM2_RETENTION | MCU_RAM3_RETENTION); - - /* Disable retention of AUX RAM */ - ti_lib_aon_wuc_aux_sram_config(false); - - /* - * Always turn off RFCORE, CPU, SYSBUS and VIMS. RFCORE should be off - * already - */ - ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_CPU | - PRCM_DOMAIN_VIMS | PRCM_DOMAIN_SYSBUS); - - /* Request JTAG domain power off */ - ti_lib_aon_wuc_jtag_power_off(); - - /* Turn off AUX */ - ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF); - ti_lib_aon_wuc_domain_power_down_enable(); - while(ti_lib_aon_wuc_power_status_get() & AONWUC_AUX_POWER_ON); - - /* Configure the recharge controller */ - ti_lib_sys_ctrl_set_recharge_before_power_down(XOSC_IN_HIGH_POWER_MODE); - - /* - * If both PERIPH and SERIAL PDs are off, request the uLDO as the power - * source while in deep sleep. - */ - if(domains == LOCKABLE_DOMAINS) { - ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_ULDO); - } - - /* We are only interested in IRQ energest while idle or in LPM */ - ENERGEST_IRQ_RESTORE(irq_energest); - ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM); - - /* Sync the AON interface to ensure all writes have gone through. */ - ti_lib_sys_ctrl_aon_sync(); - - /* - * Explicitly turn off VIMS cache, CRAM and TRAM. Needed because of - * retention mismatch between VIMS logic and cache. We wait to do this - * until right before deep sleep to be able to use the cache for as long - * as possible. - */ - ti_lib_prcm_cache_retention_disable(); - ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF); - - /* Deep Sleep */ - ti_lib_prcm_deep_sleep(); - - /* - * When we reach here, some interrupt woke us up. The global interrupt - * flag is off, hence we have a chance to run things here. We will wake up - * the chip properly, and then we will enable the global interrupt without - * unpending events so the handlers can fire - */ - wake_up(); - - ti_lib_int_master_enable(); - } + return max_pm; } /*---------------------------------------------------------------------------*/ void @@ -433,6 +349,164 @@ lpm_sleep(void) ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU); } /*---------------------------------------------------------------------------*/ +static void +deep_sleep(rtimer_clock_t next_timer) +{ + uint32_t domains = LOCKABLE_DOMAINS; + lpm_registered_module_t *module; + +#if CC2650_FAST_RADIO_STARTUP + /* schedule a wakeup briefly before the next etimer/rtimer to wake up the system */ + soc_rtc_schedule_one_shot(AON_RTC_CH2, next_timer - SLEEP_GUARD_TIME); +#endif + + /* + * Notify all registered modules that we are dropping to mode X. We do not + * need to do this for simple sleep. + * + * This is a chance for modules to delay us a little bit until an ongoing + * operation has finished (e.g. uart TX) or to configure themselves for + * deep sleep. + * + * At this stage, we also collect power domain locks, if any. + * The argument to PRCMPowerDomainOff() is a bitwise OR, so every time + * we encounter a lock we just clear the respective bits in the 'domains' + * variable as required by the lock. In the end the domains variable will + * just hold whatever has not been cleared + */ + for(module = list_head(modules_list); module != NULL; + module = module->next) { + if(module->shutdown) { + module->shutdown(LPM_MODE_DEEP_SLEEP); + } + + /* Clear the bits specified in the lock */ + domains &= ~module->domain_lock; + } + + /* Pat the dog: We don't want it to shout right after we wake up */ + watchdog_periodic(); + + /* Clear unacceptable bits, just in case a lock provided a bad value */ + domains &= LOCKABLE_DOMAINS; + + /* + * Freeze the IOs on the boundary between MCU and AON. We only do this if + * PERIPH is not needed + */ + if(domains & PRCM_DOMAIN_PERIPH) { + ti_lib_aon_ioc_freeze_enable(); + } + + /* + * Among LOCKABLE_DOMAINS, turn off those that are not locked + * + * If domains is != 0, pass it as-is + */ + if(domains) { + ti_lib_prcm_power_domain_off(domains); + } + + /* + * Before entering Deep Sleep, we must switch off the HF XOSC. The HF XOSC + * is predominantly controlled by the RF driver. In a build with radio + * cycling (e.g. ContikiMAC), the RF driver will request the XOSC before + * using the Freq. Synth, and switch back to the RC when it is about to + * turn back off. + * + * If the radio is on, we won't even reach here, and if it's off the HF + * clock source should already be the HF RC, unless CC2650_FAST_RADIO_STARTUP + * is defined. + * + * Nevertheless, request the switch to the HF RC explicitly here. + */ + oscillators_switch_to_hf_rc(); + + /* Shut Down the AUX if the user application is not using it */ + aux_ctrl_power_down(false); + + /* Configure clock sources for MCU: No clock */ + ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK); + + /* Full RAM retention. */ + ti_lib_aon_wuc_mcu_sram_config(MCU_RAM0_RETENTION | MCU_RAM1_RETENTION | + MCU_RAM2_RETENTION | MCU_RAM3_RETENTION); + + /* + * Always turn off RFCORE, CPU, SYSBUS and VIMS. RFCORE should be off + * already + */ + ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_CPU | + PRCM_DOMAIN_VIMS | PRCM_DOMAIN_SYSBUS); + + /* Request JTAG domain power off */ + ti_lib_aon_wuc_jtag_power_off(); + + /* Allow MCU and AUX powerdown */ + ti_lib_aon_wuc_domain_power_down_enable(); + + /* Configure the recharge controller */ + ti_lib_sys_ctrl_set_recharge_before_power_down(XOSC_IN_HIGH_POWER_MODE); + + /* + * If both PERIPH and SERIAL PDs are off, request the uLDO as the power + * source while in deep sleep. + */ + if(domains == LOCKABLE_DOMAINS) { + ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_ULDO); + } + + /* We are only interested in IRQ energest while idle or in LPM */ + ENERGEST_IRQ_RESTORE(irq_energest); + ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM); + + /* Sync the AON interface to ensure all writes have gone through. */ + ti_lib_sys_ctrl_aon_sync(); + + /* + * Explicitly turn off VIMS cache, CRAM and TRAM. Needed because of + * retention mismatch between VIMS logic and cache. We wait to do this + * until right before deep sleep to be able to use the cache for as long + * as possible. + */ + ti_lib_prcm_cache_retention_disable(); + ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF); + + /* Deep Sleep */ + ti_lib_prcm_deep_sleep(); + + /* + * When we reach here, some interrupt woke us up. The global interrupt + * flag is off, hence we have a chance to run things here. We will wake up + * the chip properly, and then we will enable the global interrupt without + * unpending events so the handlers can fire + */ + wake_up(); + + ti_lib_int_master_enable(); +} +/*---------------------------------------------------------------------------*/ +void +lpm_drop() +{ + uint8_t max_pm; + rtimer_clock_t next_timer; + + /* Critical. Don't get interrupted! */ + ti_lib_int_master_disable(); + + max_pm = setup_sleep_mode(&next_timer); + + /* Drop */ + if(max_pm == LPM_MODE_SLEEP) { + lpm_sleep(); + } else if(max_pm == LPM_MODE_DEEP_SLEEP) { + deep_sleep(next_timer); + } + + ti_lib_int_master_enable(); +} +/*---------------------------------------------------------------------------*/ void lpm_register_module(lpm_registered_module_t *module) { @@ -451,7 +525,7 @@ lpm_init() list_init(modules_list); /* Always wake up on any DIO edge detection */ - ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU2, AON_EVENT_IO); + ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU3, AON_EVENT_IO); } /*---------------------------------------------------------------------------*/ void diff --git a/cpu/cc26xx-cc13xx/lpm.h b/cpu/cc26xx-cc13xx/lpm.h index cc144809b..2d6f56d00 100644 --- a/cpu/cc26xx-cc13xx/lpm.h +++ b/cpu/cc26xx-cc13xx/lpm.h @@ -49,6 +49,7 @@ #include /*---------------------------------------------------------------------------*/ +#define LPM_MODE_AWAKE 0 #define LPM_MODE_SLEEP 1 #define LPM_MODE_DEEP_SLEEP 2 #define LPM_MODE_SHUTDOWN 3 diff --git a/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c b/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c index fc0ef7cbb..08843d699 100644 --- a/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c +++ b/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c @@ -51,6 +51,7 @@ #include "sys/energest.h" #include "sys/clock.h" #include "sys/rtimer.h" +#include "sys/ctimer.h" #include "sys/cc.h" #include "lpm.h" #include "ti-lib.h" @@ -102,6 +103,9 @@ #define IEEE_MODE_RSSI_THRESHOLD 0xA6 #endif /* IEEE_MODE_CONF_RSSI_THRESHOLD */ /*---------------------------------------------------------------------------*/ +#define STATUS_CRC_OK 0x80 +#define STATUS_CORRELATION 0x7f +/*---------------------------------------------------------------------------*/ /* Data entry status field constants */ #define DATA_ENTRY_STATUS_PENDING 0x00 /* Not in use by the Radio CPU */ #define DATA_ENTRY_STATUS_ACTIVE 0x01 /* Open for r/w by the radio CPU */ @@ -142,6 +146,13 @@ static uint8_t rf_stats[16] = { 0 }; #define RF_CMD_CCA_REQ_CCA_STATE_IDLE 0 /* 00 */ #define RF_CMD_CCA_REQ_CCA_STATE_BUSY 1 /* 01 */ #define RF_CMD_CCA_REQ_CCA_STATE_INVALID 2 /* 10 */ + +#define RF_CMD_CCA_REQ_CCA_CORR_IDLE (0 << 4) +#define RF_CMD_CCA_REQ_CCA_CORR_BUSY (1 << 4) +#define RF_CMD_CCA_REQ_CCA_CORR_INVALID (3 << 4) +#define RF_CMD_CCA_REQ_CCA_CORR_MASK (3 << 4) + +#define RF_CMD_CCA_REQ_CCA_SYNC_BUSY (1 << 6) /*---------------------------------------------------------------------------*/ #define IEEE_MODE_CHANNEL_MIN 11 #define IEEE_MODE_CHANNEL_MAX 26 @@ -186,6 +197,35 @@ static const output_config_t output_power[] = { /* Default TX Power - position in output_power[] */ const output_config_t *tx_power_current = &output_power[0]; /*---------------------------------------------------------------------------*/ +static volatile int8_t last_rssi = 0; +static volatile uint8_t last_corr_lqi = 0; + +extern int32_t rat_offset; + +/*---------------------------------------------------------------------------*/ +/* SFD timestamp in RTIMER ticks */ +static volatile uint32_t last_packet_timestamp = 0; +/* SFD timestamp in RAT ticks (but 64 bits) */ +static uint64_t last_rat_timestamp64 = 0; + +/* For RAT overflow handling */ +static struct ctimer rat_overflow_timer; +static uint32_t rat_overflow_counter = 0; +static rtimer_clock_t last_rat_overflow = 0; + +/* RAT has 32-bit register, overflows once 18 minutes */ +#define RAT_RANGE 4294967296ull +/* approximate value */ +#define RAT_OVERFLOW_PERIOD_SECONDS (60 * 18) + +/* XXX: don't know what exactly is this, looks like the time to Tx 3 octets */ +#define TIMESTAMP_OFFSET -(USEC_TO_RADIO(32 * 3) - 1) /* -95.75 usec */ +/*---------------------------------------------------------------------------*/ +/* Are we currently in poll mode? */ +static uint8_t poll_mode = 0; + +static rfc_CMD_IEEE_MOD_FILT_t filter_cmd; +/*---------------------------------------------------------------------------*/ /* * Buffers used to send commands to the RF core (generic and IEEE commands). * Some of those buffers are re-usable, some are not. @@ -202,7 +242,7 @@ static uint8_t cmd_ieee_rx_buf[RF_CMD_BUFFER_SIZE] CC_ALIGN(4); #define DATA_ENTRY_LENSZ_BYTE 1 #define DATA_ENTRY_LENSZ_WORD 2 /* 2 bytes */ -#define RX_BUF_SIZE 140 +#define RX_BUF_SIZE 144 /* Four receive buffers entries with room for 1 IEEE802.15.4 frame in each */ static uint8_t rx_buf_0[RX_BUF_SIZE] CC_ALIGN(4); static uint8_t rx_buf_1[RX_BUF_SIZE] CC_ALIGN(4); @@ -544,7 +584,7 @@ init_rf_params(void) cmd->rxConfig.bAppendRssi = 1; cmd->rxConfig.bAppendCorrCrc = 1; cmd->rxConfig.bAppendSrcInd = 0; - cmd->rxConfig.bAppendTimestamp = 0; + cmd->rxConfig.bAppendTimestamp = 1; cmd->pRxQ = &rx_data_queue; cmd->pOutput = (rfc_ieeeRxOutput_t *)rf_stats; @@ -568,7 +608,7 @@ init_rf_params(void) cmd->frameFiltOpt.defaultPend = 0; cmd->frameFiltOpt.bPendDataReqOnly = 0; cmd->frameFiltOpt.bPanCoord = 0; - cmd->frameFiltOpt.maxFrameVersion = 1; + cmd->frameFiltOpt.maxFrameVersion = 2; cmd->frameFiltOpt.bStrictLenFilter = 0; /* Receive all frame types */ @@ -584,9 +624,9 @@ init_rf_params(void) /* Configure CCA settings */ cmd->ccaOpt.ccaEnEnergy = 1; cmd->ccaOpt.ccaEnCorr = 1; - cmd->ccaOpt.ccaEnSync = 0; + cmd->ccaOpt.ccaEnSync = 1; cmd->ccaOpt.ccaCorrOp = 1; - cmd->ccaOpt.ccaSyncOp = 1; + cmd->ccaOpt.ccaSyncOp = 0; cmd->ccaOpt.ccaCorrThr = 3; cmd->ccaRssiThr = IEEE_MODE_RSSI_THRESHOLD; @@ -598,6 +638,11 @@ init_rf_params(void) cmd->endTrigger.triggerType = TRIG_NEVER; cmd->endTime = 0x00000000; + + /* set address filter command */ + filter_cmd.commandNo = CMD_IEEE_MOD_FILT; + memcpy(&filter_cmd.newFrameFiltOpt, &cmd->frameFiltOpt, sizeof(cmd->frameFiltOpt)); + memcpy(&filter_cmd.newFrameTypes, &cmd->frameTypes, sizeof(cmd->frameTypes)); } /*---------------------------------------------------------------------------*/ static int @@ -647,13 +692,14 @@ rx_off(void) if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_STOPPED || RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_ABORT) { /* Stopped gracefully */ - ENERGEST_OFF(ENERGEST_TYPE_LISTEN); ret = RF_CORE_CMD_OK; } else { PRINTF("RX off: BG status=0x%04x\n", RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf)); ret = RF_CORE_CMD_ERROR; } + ENERGEST_OFF(ENERGEST_TYPE_LISTEN); + return ret; } /*---------------------------------------------------------------------------*/ @@ -712,6 +758,55 @@ static const rf_core_primary_mode_t mode_ieee = { soft_on, }; /*---------------------------------------------------------------------------*/ +static void +check_rat_overflow(bool first_time) +{ + static uint32_t last_value; + uint32_t current_value; + uint8_t interrupts_enabled; + + interrupts_enabled = ti_lib_int_master_disable(); + if(first_time) { + last_value = HWREG(RFC_RAT_BASE + RATCNT); + } else { + current_value = HWREG(RFC_RAT_BASE + RATCNT); + if(current_value + RAT_RANGE / 4 < last_value) { + /* overflow detected */ + last_rat_overflow = RTIMER_NOW(); + rat_overflow_counter++; + } + last_value = current_value; + } + if(interrupts_enabled) { + ti_lib_int_master_enable(); + } +} +/*---------------------------------------------------------------------------*/ +static void +handle_rat_overflow(void *unused) +{ + uint8_t was_off = 0; + + if(!rf_is_on()) { + was_off = 1; + if(on() != RF_CORE_CMD_OK) { + PRINTF("overflow: on() failed\n"); + ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_PERIOD_SECONDS * CLOCK_SECOND / 2, + handle_rat_overflow, NULL); + return; + } + } + + check_rat_overflow(false); + + if(was_off) { + off(); + } + + ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_PERIOD_SECONDS * CLOCK_SECOND / 2, + handle_rat_overflow, NULL); +} +/*---------------------------------------------------------------------------*/ static int init(void) { @@ -745,6 +840,10 @@ init(void) rf_core_primary_mode_register(&mode_ieee); + check_rat_overflow(true); + ctimer_set(&rat_overflow_timer, RAT_OVERFLOW_PERIOD_SECONDS * CLOCK_SECOND / 2, + handle_rat_overflow, NULL); + process_start(&rf_core_process, NULL); return 1; } @@ -755,7 +854,7 @@ prepare(const void *payload, unsigned short payload_len) int len = MIN(payload_len, TX_BUF_PAYLOAD_LEN); memcpy(&tx_buf[TX_BUF_HDR_LEN], payload, len); - return RF_CORE_CMD_OK; + return 0; } /*---------------------------------------------------------------------------*/ static int @@ -768,6 +867,7 @@ transmit(unsigned short transmit_len) uint8_t tx_active = 0; rtimer_clock_t t0; volatile rfc_CMD_IEEE_TX_t cmd; + uint8_t interrupts_enabled; if(!rf_is_on()) { was_off = 1; @@ -805,8 +905,19 @@ transmit(unsigned short transmit_len) cmd.payloadLen = transmit_len; cmd.pPayload = &tx_buf[TX_BUF_HDR_LEN]; + cmd.startTime = 0; + cmd.startTrigger.triggerType = TRIG_NOW; + + /* XXX: there seems to be no function that gets interrupt state w/o changing it */ + interrupts_enabled = ti_lib_int_master_disable(); + if(interrupts_enabled) { + ti_lib_int_master_enable(); + } + /* Enable the LAST_FG_COMMAND_DONE interrupt, which will wake us up */ - rf_core_cmd_done_en(true); + if(interrupts_enabled) { + rf_core_cmd_done_en(true, poll_mode); + } ret = rf_core_send_cmd((uint32_t)&cmd, &cmd_status); @@ -818,7 +929,14 @@ transmit(unsigned short transmit_len) /* Idle away while the command is running */ while((cmd.status & RF_CORE_RADIO_OP_MASKED_STATUS) == RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING) { - lpm_sleep(); + /* Note: for now sleeping while Tx'ing in polling mode is disabled. + * To enable it: + * 1) make the `lpm_sleep()` call here unconditional; + * 2) change the radio ISR priority to allow radio ISR to interrupt rtimer ISR. + */ + if(interrupts_enabled) { + lpm_sleep(); + } } stat = cmd.status; @@ -848,12 +966,13 @@ transmit(unsigned short transmit_len) ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); ENERGEST_ON(ENERGEST_TYPE_LISTEN); - /* - * Disable LAST_FG_COMMAND_DONE interrupt. We don't really care about it - * except when we are transmitting - */ - rf_core_cmd_done_dis(); - + if(interrupts_enabled) { + /* + * Disable LAST_FG_COMMAND_DONE interrupt. We don't really care about it + * except when we are transmitting + */ + rf_core_cmd_done_dis(poll_mode); + } if(was_off) { off(); @@ -880,13 +999,48 @@ release_data_entry(void) /* Set status to 0 "Pending" in element */ entry->status = DATA_ENTRY_STATUS_PENDING; rx_read_entry = entry->pNextEntry; -}/*---------------------------------------------------------------------------*/ +} +/*---------------------------------------------------------------------------*/ +static uint32_t +calc_last_packet_timestamp(uint32_t rat_timestamp) +{ + uint64_t rat_timestamp64; + uint32_t adjusted_overflow_counter = rat_overflow_counter; + + /* if the timestamp is large and the last oveflow was recently, + assume that the timestamp refers to the time before the overflow */ + if(rat_timestamp > (uint32_t)(RAT_RANGE * 3 / 4)) { + if(RTIMER_CLOCK_LT(RTIMER_NOW(), + last_rat_overflow + RAT_OVERFLOW_PERIOD_SECONDS * RTIMER_SECOND / 4)) { + adjusted_overflow_counter--; + } + } + + /* add the overflowed time to the timestamp */ + rat_timestamp64 = rat_timestamp + RAT_RANGE * adjusted_overflow_counter; + /* correct timestamp so that it refers to the end of the SFD */ + rat_timestamp64 += TIMESTAMP_OFFSET; + + last_rat_timestamp64 = rat_timestamp64 - rat_offset; + + return RADIO_TO_RTIMER(rat_timestamp64 - rat_offset); +} +/*---------------------------------------------------------------------------*/ static int read_frame(void *buf, unsigned short buf_len) { - int8_t rssi; int len = 0; rfc_dataEntryGeneral_t *entry = (rfc_dataEntryGeneral_t *)rx_read_entry; + uint32_t rat_timestamp; + + if(rf_is_on()) { + check_rat_overflow(false); + } + + /* wait for entry to become finished */ + rtimer_clock_t t0 = RTIMER_NOW(); + while(entry->status == DATA_ENTRY_STATUS_BUSY + && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (RTIMER_SECOND / 250))); if(entry->status != DATA_ENTRY_STATUS_FINISHED) { /* No available data */ @@ -901,7 +1055,7 @@ read_frame(void *buf, unsigned short buf_len) return 0; } - len = rx_read_entry[8] - 4; + len = rx_read_entry[8] - 8; if(len > buf_len) { PRINTF("RF: too long\n"); @@ -913,9 +1067,21 @@ read_frame(void *buf, unsigned short buf_len) memcpy(buf, (char *)&rx_read_entry[9], len); - rssi = (int8_t)rx_read_entry[9 + len + 2]; + last_rssi = (int8_t)rx_read_entry[9 + len + 2]; + last_corr_lqi = (uint8_t)rx_read_entry[9 + len + 2] & STATUS_CORRELATION; - packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi); + /* get the timestamp */ + memcpy(&rat_timestamp, (char *)rx_read_entry + 9 + len + 4, 4); + + last_packet_timestamp = calc_last_packet_timestamp(rat_timestamp); + + if(!poll_mode) { + /* Not in poll mode: packetbuf should not be accessed in interrupt context. + * In poll mode, the last packet RSSI and link quality can be obtained through + * RADIO_PARAM_LAST_RSSI and RADIO_PARAM_LAST_LINK_QUALITY */ + packetbuf_set_attr(PACKETBUF_ATTR_RSSI, last_rssi); + packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, last_corr_lqi); + } RIMESTATS_ADD(llrx); release_data_entry(); @@ -983,9 +1149,7 @@ channel_clear(void) static int receiving_packet(void) { - int ret = 0; uint8_t cca_info; - uint8_t was_off = 0; /* * If we are in the middle of a BLE operation, we got called by ContikiMAC @@ -1010,19 +1174,17 @@ receiving_packet(void) cca_info = get_cca_info(); + /* If we can't read CCA info, return "not receiving" */ if(cca_info == RF_GET_CCA_INFO_ERROR) { - /* If we can't read CCA info, return "not receiving" */ - ret = 0; - } else { - /* Return 1 (receiving) if ccaState is busy */ - ret = (cca_info & 0x03) == RF_CMD_CCA_REQ_CCA_STATE_BUSY; + return 0; } - if(was_off) { - off(); + /* If sync has been seen, return 1 (receiving) */ + if(cca_info & RF_CMD_CCA_REQ_CCA_SYNC_BUSY) { + return 1; } - return ret; + return 0; } /*---------------------------------------------------------------------------*/ static int @@ -1033,9 +1195,12 @@ pending_packet(void) /* Go through all RX buffers and check their status */ do { - if(entry->status == DATA_ENTRY_STATUS_FINISHED) { + if(entry->status == DATA_ENTRY_STATUS_FINISHED + || entry->status == DATA_ENTRY_STATUS_BUSY) { rv = 1; - process_poll(&rf_core_process); + if(!poll_mode) { + process_poll(&rf_core_process); + } } entry = (rfc_dataEntry_t *)entry->pNextEntry; @@ -1048,12 +1213,6 @@ pending_packet(void) static int on(void) { - /* - * Request the HF XOSC as the source for the HF clock. Needed before we can - * use the FS. This will only request, it will _not_ perform the switch. - */ - oscillators_request_hf_xosc(); - /* * If we are in the middle of a BLE operation, we got called by ContikiMAC * from within an interrupt context. Abort, but pretend everything is OK. @@ -1063,27 +1222,36 @@ on(void) return RF_CORE_CMD_OK; } +#if !CC2650_FAST_RADIO_STARTUP + /* + * Request the HF XOSC as the source for the HF clock. Needed before we can + * use the FS. This will only request, it will _not_ perform the switch. + */ + oscillators_request_hf_xosc(); +#endif + if(rf_is_on()) { PRINTF("on: We were on. PD=%u, RX=0x%04x \n", rf_core_is_accessible(), RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf)); return RF_CORE_CMD_OK; } + init_rx_buffers(); + + /* + * Trigger a switch to the XOSC, so that we can subsequently use the RF FS + * This will block until the XOSC is actually ready, but give how we + * requested it early on, this won't be too long a wait. + * This should be done before starting the RAT. + */ + oscillators_switch_to_hf_xosc(); + if(rf_core_boot() != RF_CORE_CMD_OK) { PRINTF("on: rf_core_boot() failed\n"); return RF_CORE_CMD_ERROR; } - init_rx_buffers(); - - rf_core_setup_interrupts(); - - /* - * Trigger a switch to the XOSC, so that we can subsequently use the RF FS - * This will block until the XOSC is actually ready, but give how we - * requested it early on, this won't be too long a wait/ - */ - oscillators_switch_to_hf_xosc(); + rf_core_setup_interrupts(poll_mode); if(rf_radio_setup() != RF_CORE_CMD_OK) { PRINTF("on: radio_setup() failed\n"); @@ -1113,8 +1281,12 @@ off(void) ENERGEST_OFF(ENERGEST_TYPE_LISTEN); - /* Switch HF clock source to the RCOSC to preserve power */ +#if !CC2650_FAST_RADIO_STARTUP + /* Switch HF clock source to the RCOSC to preserve power. + * This must be done after stopping RAT. + */ oscillators_switch_to_hf_rc(); +#endif /* We pulled the plug, so we need to restore the status manually */ ((rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf)->status = RF_CORE_RADIO_OP_STATUS_IDLE; @@ -1123,14 +1295,33 @@ off(void) * Just in case there was an ongoing RX (which started after we begun the * shutdown sequence), we don't want to leave the buffer in state == ongoing */ - ((rfc_dataEntry_t *)rx_buf_0)->status = DATA_ENTRY_STATUS_PENDING; - ((rfc_dataEntry_t *)rx_buf_1)->status = DATA_ENTRY_STATUS_PENDING; - ((rfc_dataEntry_t *)rx_buf_2)->status = DATA_ENTRY_STATUS_PENDING; - ((rfc_dataEntry_t *)rx_buf_3)->status = DATA_ENTRY_STATUS_PENDING; + if(((rfc_dataEntry_t *)rx_buf_0)->status == DATA_ENTRY_STATUS_BUSY) { + ((rfc_dataEntry_t *)rx_buf_0)->status = DATA_ENTRY_STATUS_PENDING; + } + if(((rfc_dataEntry_t *)rx_buf_1)->status == DATA_ENTRY_STATUS_BUSY) { + ((rfc_dataEntry_t *)rx_buf_1)->status = DATA_ENTRY_STATUS_PENDING; + } + if(((rfc_dataEntry_t *)rx_buf_2)->status == DATA_ENTRY_STATUS_BUSY) { + ((rfc_dataEntry_t *)rx_buf_2)->status = DATA_ENTRY_STATUS_PENDING; + } + if(((rfc_dataEntry_t *)rx_buf_3)->status == DATA_ENTRY_STATUS_BUSY) { + ((rfc_dataEntry_t *)rx_buf_3)->status = DATA_ENTRY_STATUS_PENDING; + } return RF_CORE_CMD_OK; } /*---------------------------------------------------------------------------*/ +/* Enable or disable CCA before sending */ +static radio_result_t +set_send_on_cca(uint8_t enable) +{ + if(enable) { + /* this driver does not have support for CCA on Tx */ + return RADIO_RESULT_NOT_SUPPORTED; + } + return RADIO_RESULT_OK; +} +/*---------------------------------------------------------------------------*/ static radio_result_t get_value(radio_param_t param, radio_value_t *value) { @@ -1162,7 +1353,13 @@ get_value(radio_param_t param, radio_value_t *value) if(cmd->frameFiltOpt.autoAckEn) { *value |= RADIO_RX_MODE_AUTOACK; } + if(poll_mode) { + *value |= RADIO_RX_MODE_POLL_MODE; + } + return RADIO_RESULT_OK; + case RADIO_PARAM_TX_MODE: + *value = 0; return RADIO_RESULT_OK; case RADIO_PARAM_TXPOWER: *value = get_tx_power(); @@ -1190,6 +1387,12 @@ 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_PARAM_LAST_RSSI: + *value = last_rssi; + return RADIO_RESULT_OK; + case RADIO_PARAM_LAST_LINK_QUALITY: + *value = last_corr_lqi; + return RADIO_RESULT_OK; default: return RADIO_RESULT_NOT_SUPPORTED; } @@ -1198,9 +1401,9 @@ get_value(radio_param_t param, radio_value_t *value) static radio_result_t set_value(radio_param_t param, radio_value_t value) { - uint8_t was_off = 0; radio_result_t rv = RADIO_RESULT_OK; rfc_CMD_IEEE_RX_t *cmd = (rfc_CMD_IEEE_RX_t *)cmd_ieee_rx_buf; + uint8_t old_poll_mode; switch(param) { case RADIO_PARAM_POWER_MODE: @@ -1222,6 +1425,7 @@ set_value(radio_param_t param, radio_value_t value) return RADIO_RESULT_INVALID_VALUE; } + /* Note: this return may lead to long periods when RAT and RTC are not resynchronized */ if(cmd->channel == (uint8_t)value) { /* We already have that very same channel configured. * Nothing to do here. */ @@ -1239,7 +1443,7 @@ set_value(radio_param_t param, radio_value_t value) case RADIO_PARAM_RX_MODE: { if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER | - RADIO_RX_MODE_AUTOACK)) { + RADIO_RX_MODE_AUTOACK | RADIO_RX_MODE_POLL_MODE)) { return RADIO_RESULT_INVALID_VALUE; } @@ -1252,8 +1456,30 @@ set_value(radio_param_t param, radio_value_t value) cmd->frameFiltOpt.bPendDataReqOnly = 0; cmd->frameFiltOpt.bPanCoord = 0; cmd->frameFiltOpt.bStrictLenFilter = 0; + + old_poll_mode = poll_mode; + poll_mode = (value & RADIO_RX_MODE_POLL_MODE) != 0; + if(poll_mode == old_poll_mode) { + uint32_t cmd_status; + + /* do not turn the radio on and off, just send an update command */ + memcpy(&filter_cmd.newFrameFiltOpt, &cmd->frameFiltOpt, sizeof(cmd->frameFiltOpt)); + + if(rf_core_send_cmd((uint32_t)&filter_cmd, &cmd_status) == RF_CORE_CMD_ERROR) { + PRINTF("setting address filter failed: CMDSTA=0x%08lx\n", cmd_status); + return RADIO_RESULT_ERROR; + } + return RADIO_RESULT_OK; + } break; } + + case RADIO_PARAM_TX_MODE: + if(value & ~(RADIO_TX_MODE_SEND_ON_CCA)) { + return RADIO_RESULT_INVALID_VALUE; + } + return set_send_on_cca((value & RADIO_TX_MODE_SEND_ON_CCA) != 0); + case RADIO_PARAM_TXPOWER: if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) { return RADIO_RESULT_INVALID_VALUE; @@ -1262,37 +1488,37 @@ set_value(radio_param_t param, radio_value_t value) set_tx_power(value); return RADIO_RESULT_OK; + case RADIO_PARAM_CCA_THRESHOLD: cmd->ccaRssiThr = (int8_t)value; break; + default: return RADIO_RESULT_NOT_SUPPORTED; } - /* If we reach here we had no errors. Apply new settings */ + /* If off, the new configuration will be applied the next time radio is started */ if(!rf_is_on()) { - was_off = 1; - if(on() != RF_CORE_CMD_OK) { - PRINTF("set_value: on() failed (2)\n"); - return RADIO_RESULT_ERROR; - } + return RADIO_RESULT_OK; } + /* If we reach here we had no errors. Apply new settings */ if(rx_off() != RF_CORE_CMD_OK) { PRINTF("set_value: rx_off() failed\n"); rv = RADIO_RESULT_ERROR; } + /* Restart the radio timer (RAT). + This causes resynchronization between RAT and RTC: useful for TSCH. */ + rf_core_restart_rat(); + + check_rat_overflow(false); + if(rx_on() != RF_CORE_CMD_OK) { PRINTF("set_value: rx_on() failed\n"); rv = RADIO_RESULT_ERROR; } - /* If we were off, turn back off */ - if(was_off) { - off(); - } - return rv; } /*---------------------------------------------------------------------------*/ @@ -1318,13 +1544,22 @@ get_object(radio_param_t param, void *dest, size_t size) return RADIO_RESULT_OK; } + + if(param == RADIO_PARAM_LAST_PACKET_TIMESTAMP) { + if(size != sizeof(rtimer_clock_t) || !dest) { + return RADIO_RESULT_INVALID_VALUE; + } + *(rtimer_clock_t *)dest = last_packet_timestamp; + + return RADIO_RESULT_OK; + } + return RADIO_RESULT_NOT_SUPPORTED; } /*---------------------------------------------------------------------------*/ static radio_result_t set_object(radio_param_t param, const void *src, size_t size) { - uint8_t was_off = 0; radio_result_t rv; int i; uint8_t *dst; @@ -1341,12 +1576,9 @@ set_object(radio_param_t param, const void *src, size_t size) dst[i] = ((uint8_t *)src)[7 - i]; } + /* If off, the new configuration will be applied the next time radio is started */ if(!rf_is_on()) { - was_off = 1; - if(on() != RF_CORE_CMD_OK) { - PRINTF("set_object: on() failed\n"); - return RADIO_RESULT_ERROR; - } + return RADIO_RESULT_OK; } if(rx_off() != RF_CORE_CMD_OK) { @@ -1359,11 +1591,6 @@ set_object(radio_param_t param, const void *src, size_t size) rv = RADIO_RESULT_ERROR; } - /* If we were off, turn back off */ - if(was_off) { - off(); - } - return rv; } return RADIO_RESULT_NOT_SUPPORTED; diff --git a/cpu/cc26xx-cc13xx/rf-core/prop-mode.c b/cpu/cc26xx-cc13xx/rf-core/prop-mode.c index 7515d79b4..94aef33b9 100644 --- a/cpu/cc26xx-cc13xx/rf-core/prop-mode.c +++ b/cpu/cc26xx-cc13xx/rf-core/prop-mode.c @@ -634,7 +634,7 @@ prepare(const void *payload, unsigned short payload_len) int len = MIN(payload_len, TX_BUF_PAYLOAD_LEN); memcpy(&tx_buf[TX_BUF_HDR_LEN], payload, len); - return RF_CORE_CMD_OK; + return 0; } /*---------------------------------------------------------------------------*/ static int @@ -683,7 +683,7 @@ transmit(unsigned short transmit_len) rx_off_prop(); /* Enable the LAST_COMMAND_DONE interrupt to wake us up */ - rf_core_cmd_done_en(false); + rf_core_cmd_done_en(false, false); ret = rf_core_send_cmd((uint32_t)cmd_tx_adv, &cmd_status); @@ -728,7 +728,7 @@ transmit(unsigned short transmit_len) * Disable LAST_FG_COMMAND_DONE interrupt. We don't really care about it * except when we are transmitting */ - rf_core_cmd_done_dis(); + rf_core_cmd_done_dis(false); /* Workaround. Set status to IDLE */ cmd_tx_adv->status = RF_CORE_RADIO_OP_STATUS_IDLE; @@ -893,12 +893,6 @@ pending_packet(void) static int on(void) { - /* - * Request the HF XOSC as the source for the HF clock. Needed before we can - * use the FS. This will only request, it will _not_ perform the switch. - */ - oscillators_request_hf_xosc(); - /* * If we are in the middle of a BLE operation, we got called by ContikiMAC * from within an interrupt context. Abort, but pretend everything is OK. @@ -907,6 +901,12 @@ on(void) return RF_CORE_CMD_OK; } + /* + * Request the HF XOSC as the source for the HF clock. Needed before we can + * use the FS. This will only request, it will _not_ perform the switch. + */ + oscillators_request_hf_xosc(); + if(rf_is_on()) { PRINTF("on: We were on. PD=%u, RX=0x%04x \n", rf_core_is_accessible(), smartrf_settings_cmd_prop_rx_adv.status); @@ -933,7 +933,7 @@ on(void) } } - rf_core_setup_interrupts(); + rf_core_setup_interrupts(false); /* * Trigger a switch to the XOSC, so that we can subsequently use the RF FS diff --git a/cpu/cc26xx-cc13xx/rf-core/rf-ble.c b/cpu/cc26xx-cc13xx/rf-core/rf-ble.c index b8af55ff8..48daba69f 100644 --- a/cpu/cc26xx-cc13xx/rf-core/rf-ble.c +++ b/cpu/cc26xx-cc13xx/rf-core/rf-ble.c @@ -256,7 +256,7 @@ PROCESS_THREAD(rf_ble_beacon_process, ev, data) while(1) { etimer_set(&ble_adv_et, beacond_config.interval); - PROCESS_WAIT_EVENT(); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&ble_adv_et) || ev == PROCESS_EVENT_EXIT); if(ev == PROCESS_EVENT_EXIT) { PROCESS_EXIT(); @@ -374,7 +374,7 @@ PROCESS_THREAD(rf_ble_beacon_process, ev, data) /* Wait unless this is the last burst */ if(i < BLE_ADV_MESSAGES - 1) { - PROCESS_WAIT_EVENT(); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&ble_adv_et)); } } diff --git a/cpu/cc26xx-cc13xx/rf-core/rf-core.c b/cpu/cc26xx-cc13xx/rf-core/rf-core.c index 8efe41dac..15fc8e3bc 100644 --- a/cpu/cc26xx-cc13xx/rf-core/rf-core.c +++ b/cpu/cc26xx-cc13xx/rf-core/rf-core.c @@ -92,6 +92,8 @@ #define ENABLED_IRQS (RX_FRAME_IRQ | ERROR_IRQ) #endif +#define ENABLED_IRQS_POLL_MODE (ENABLED_IRQS & ~(RX_FRAME_IRQ | ERROR_IRQ)) + #define cc26xx_rf_cpe0_isr RFCCPE0IntHandler #define cc26xx_rf_cpe1_isr RFCCPE1IntHandler /*---------------------------------------------------------------------------*/ @@ -101,6 +103,10 @@ static rfc_radioOp_t *last_radio_op = NULL; /* A struct holding pointers to the primary mode's abort() and restore() */ static const rf_core_primary_mode_t *primary_mode = NULL; /*---------------------------------------------------------------------------*/ +/* Radio timer (RAT) offset as compared to the rtimer counter (RTC) */ +int32_t rat_offset = 0; +static bool rat_offset_known = false; +/*---------------------------------------------------------------------------*/ PROCESS(rf_core_process, "CC13xx / CC26xx RF driver"); /*---------------------------------------------------------------------------*/ #define RF_CORE_CLOCKS_MASK (RFC_PWR_PWMCLKEN_RFC_M | RFC_PWR_PWMCLKEN_CPE_M \ @@ -265,6 +271,66 @@ rf_core_power_up() return RF_CORE_CMD_OK; } /*---------------------------------------------------------------------------*/ +uint8_t +rf_core_start_rat(void) +{ + uint32_t cmd_status; + rfc_CMD_SYNC_START_RAT_t cmd_start; + + /* Start radio timer (RAT) */ + rf_core_init_radio_op((rfc_radioOp_t *)&cmd_start, sizeof(cmd_start), CMD_SYNC_START_RAT); + + /* copy the value and send back */ + cmd_start.rat0 = rat_offset; + + if(rf_core_send_cmd((uint32_t)&cmd_start, &cmd_status) != RF_CORE_CMD_OK) { + PRINTF("rf_core_get_rat_rtc_offset: SYNC_START_RAT fail, CMDSTA=0x%08lx\n", + cmd_status); + return RF_CORE_CMD_ERROR; + } + + /* Wait until done (?) */ + if(rf_core_wait_cmd_done(&cmd_start) != RF_CORE_CMD_OK) { + PRINTF("rf_core_cmd_ok: SYNC_START_RAT wait, CMDSTA=0x%08lx, status=0x%04x\n", + cmd_status, cmd_start.status); + return RF_CORE_CMD_ERROR; + } + + return RF_CORE_CMD_OK; +} +/*---------------------------------------------------------------------------*/ +uint8_t +rf_core_stop_rat(void) +{ + rfc_CMD_SYNC_STOP_RAT_t cmd_stop; + uint32_t cmd_status; + + rf_core_init_radio_op((rfc_radioOp_t *)&cmd_stop, sizeof(cmd_stop), CMD_SYNC_STOP_RAT); + + int ret = rf_core_send_cmd((uint32_t)&cmd_stop, &cmd_status); + if(ret != RF_CORE_CMD_OK) { + PRINTF("rf_core_get_rat_rtc_offset: SYNC_STOP_RAT fail, ret %d CMDSTA=0x%08lx\n", + ret, cmd_status); + return ret; + } + + /* Wait until done */ + ret = rf_core_wait_cmd_done(&cmd_stop); + if(ret != RF_CORE_CMD_OK) { + PRINTF("rf_core_cmd_ok: SYNC_STOP_RAT wait, CMDSTA=0x%08lx, status=0x%04x\n", + cmd_status, cmd_stop.status); + return ret; + } + + if(!rat_offset_known) { + /* save the offset, but only if this is the first time */ + rat_offset_known = true; + rat_offset = cmd_stop.rat0; + } + + return RF_CORE_CMD_OK; +} +/*---------------------------------------------------------------------------*/ void rf_core_power_down() { @@ -280,6 +346,8 @@ rf_core_power_down() fs_powerdown(); } + rf_core_stop_rat(); + /* Shut down the RFCORE clock domain in the MCU VD */ ti_lib_prcm_domain_disable(PRCM_DOMAIN_RFCORE); ti_lib_prcm_load_set(); @@ -329,22 +397,6 @@ rf_core_set_modesel() } /*---------------------------------------------------------------------------*/ uint8_t -rf_core_start_rat() -{ - uint32_t cmd_status; - - /* Start radio timer (RAT) */ - if(rf_core_send_cmd(CMDR_DIR_CMD(CMD_START_RAT), &cmd_status) - != RF_CORE_CMD_OK) { - PRINTF("rf_core_apply_patches: START_RAT fail, CMDSTA=0x%08lx\n", - cmd_status); - return RF_CORE_CMD_ERROR; - } - - return RF_CORE_CMD_OK; -} -/*---------------------------------------------------------------------------*/ -uint8_t rf_core_boot() { if(rf_core_power_up() != RF_CORE_CMD_OK) { @@ -366,10 +418,31 @@ rf_core_boot() return RF_CORE_CMD_OK; } /*---------------------------------------------------------------------------*/ +uint8_t +rf_core_restart_rat(void) +{ + if(rf_core_stop_rat() != RF_CORE_CMD_OK) { + PRINTF("rf_core_restart_rat: rf_core_stop_rat() failed\n"); + + return RF_CORE_CMD_ERROR; + } + + if(rf_core_start_rat() != RF_CORE_CMD_OK) { + PRINTF("rf_core_restart_rat: rf_core_start_rat() failed\n"); + + rf_core_power_down(); + + return RF_CORE_CMD_ERROR; + } + + return RF_CORE_CMD_OK; +} +/*---------------------------------------------------------------------------*/ void -rf_core_setup_interrupts() +rf_core_setup_interrupts(bool poll_mode) { bool interrupts_disabled; + const uint32_t enabled_irqs = poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS; /* We are already turned on by the caller, so this should not happen */ if(!rf_core_is_accessible()) { @@ -384,7 +457,7 @@ rf_core_setup_interrupts() HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEISL) = ERROR_IRQ; /* Acknowledge configured interrupts */ - HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS; + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs; /* Clear interrupt flags, active low clear(?) */ HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0; @@ -400,18 +473,20 @@ rf_core_setup_interrupts() } /*---------------------------------------------------------------------------*/ void -rf_core_cmd_done_en(bool fg) +rf_core_cmd_done_en(bool fg, bool poll_mode) { uint32_t irq = fg ? IRQ_LAST_FG_COMMAND_DONE : IRQ_LAST_COMMAND_DONE; + const uint32_t enabled_irqs = poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS; - HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = ENABLED_IRQS; - HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS | irq; + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = enabled_irqs; + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs | irq; } /*---------------------------------------------------------------------------*/ void -rf_core_cmd_done_dis() +rf_core_cmd_done_dis(bool poll_mode) { - HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS; + const uint32_t enabled_irqs = poll_mode ? ENABLED_IRQS_POLL_MODE : ENABLED_IRQS; + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = enabled_irqs; } /*---------------------------------------------------------------------------*/ rfc_radioOp_t * diff --git a/cpu/cc26xx-cc13xx/rf-core/rf-core.h b/cpu/cc26xx-cc13xx/rf-core/rf-core.h index 42c6edb90..474de4a87 100644 --- a/cpu/cc26xx-cc13xx/rf-core/rf-core.h +++ b/cpu/cc26xx-cc13xx/rf-core/rf-core.h @@ -228,6 +228,9 @@ typedef struct rf_core_primary_mode_s { #define RF_CORE_COMMAND_PROTOCOL_IEEE 0x2000 #define RF_CORE_COMMAND_PROTOCOL_PROP 0x3000 /*---------------------------------------------------------------------------*/ +/* Radio timer register */ +#define RATCNT 0x00000004 +/*---------------------------------------------------------------------------*/ /* Make the main driver process visible to mode drivers */ PROCESS_NAME(rf_core_process); /*---------------------------------------------------------------------------*/ @@ -310,6 +313,24 @@ uint8_t rf_core_set_modesel(void); */ uint8_t rf_core_start_rat(void); +/** + * \brief Stop the CM0 RAT synchronously + * \return RF_CORE_CMD_OK or RF_CORE_CMD_ERROR + * + * This function is not strictly necessary, but through calling it it's possibly + * to learn the RAT / RTC offset, which useful to get accurate radio timestamps. + */ +uint8_t rf_core_stop_rat(void); + +/** + * \brief Restart the CM0 RAT + * \return RF_CORE_CMD_OK or RF_CORE_CMD_ERROR + * + * This function restarts the CM0 RAT and therefore resynchornizes it with RTC. + * To achieve good timing accuracy, it should be called periodically. + */ +uint8_t rf_core_restart_rat(void); + /** * \brief Boot the RF Core * \return RF_CORE_CMD_OK or RF_CORE_CMD_ERROR @@ -327,19 +348,20 @@ uint8_t rf_core_boot(void); /** * \brief Setup RF core interrupts */ -void rf_core_setup_interrupts(void); +void rf_core_setup_interrupts(bool poll_mode); /** * \brief Enable interrupt on command done. * \param fg set true to enable irq on foreground command done and false for * background commands or if not in ieee mode. + * \param poll_mode true if the driver is in poll mode * * This is used within TX routines in order to be able to sleep the CM3 and * wake up after TX has finished * * \sa rf_core_cmd_done_dis() */ -void rf_core_cmd_done_en(bool fg); +void rf_core_cmd_done_en(bool fg, bool poll_mode); /** * \brief Disable the LAST_CMD_DONE and LAST_FG_CMD_DONE interrupts. @@ -348,7 +370,7 @@ void rf_core_cmd_done_en(bool fg); * * \sa rf_core_cmd_done_en() */ -void rf_core_cmd_done_dis(void); +void rf_core_cmd_done_dis(bool poll_mode); /** * \brief Returns a pointer to the most recent proto-dependent Radio Op diff --git a/cpu/cc26xx-cc13xx/rtimer-arch.h b/cpu/cc26xx-cc13xx/rtimer-arch.h index 0d54d227c..128461c8d 100644 --- a/cpu/cc26xx-cc13xx/rtimer-arch.h +++ b/cpu/cc26xx-cc13xx/rtimer-arch.h @@ -50,6 +50,21 @@ #define RTIMER_ARCH_SECOND 65536 /*---------------------------------------------------------------------------*/ rtimer_clock_t rtimer_arch_now(void); + +/* HW oscillator frequency is 32 kHz, not 64 kHz and RTIMER_NOW() never returns + * an odd value; so US_TO_RTIMERTICKS always rounds to the nearest even number. + */ +#define US_TO_RTIMERTICKS(US) (2 * ((US) >= 0 ? \ + (((int32_t)(US) * (RTIMER_ARCH_SECOND / 2) + 500000) / 1000000L) : \ + ((int32_t)(US) * (RTIMER_ARCH_SECOND / 2) - 500000) / 1000000L)) + +#define RTIMERTICKS_TO_US(T) ((T) >= 0 ? \ + (((int32_t)(T) * 1000000L + ((RTIMER_ARCH_SECOND) / 2)) / (RTIMER_ARCH_SECOND)) : \ + ((int32_t)(T) * 1000000L - ((RTIMER_ARCH_SECOND) / 2)) / (RTIMER_ARCH_SECOND)) + +/* A 64-bit version because the 32-bit one cannot handle T >= 4295 ticks. + Intended only for positive values of T. */ +#define RTIMERTICKS_TO_US_64(T) ((uint32_t)(((uint64_t)(T) * 1000000 + ((RTIMER_ARCH_SECOND) / 2)) / (RTIMER_ARCH_SECOND))) /*---------------------------------------------------------------------------*/ #endif /* RTIMER_ARCH_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/cpu/cc26xx-cc13xx/ti-lib.h b/cpu/cc26xx-cc13xx/ti-lib.h index cbf9a8e61..c08d05ce3 100644 --- a/cpu/cc26xx-cc13xx/ti-lib.h +++ b/cpu/cc26xx-cc13xx/ti-lib.h @@ -139,6 +139,26 @@ #define ti_lib_aon_wuc_osc_config(...) AONWUCOscConfig(__VA_ARGS__) #define ti_lib_aon_wuc_jtag_power_off(...) AONWUCJtagPowerOff(__VA_ARGS__) /*---------------------------------------------------------------------------*/ +/* aux_adc.h */ +#include "driverlib/aux_adc.h" + +#define ti_lib_aux_adc_disable(...) AUXADCDisable(__VA_ARGS__) +#define ti_lib_aux_adc_enable_async(...) AUXADCEnableAsync(__VA_ARGS__) +#define ti_lib_aux_adc_enable_sync(...) AUXADCEnableSync(__VA_ARGS__) +#define ti_lib_aux_adc_disable_input_scaling(...) AUXADCDisableInputScaling(__VA_ARGS__) +#define ti_lib_aux_adc_flush_fifo(...) AUXADCFlushFifo(__VA_ARGS__) +#define ti_lib_aux_adc_gen_manual_trigger(...) AUXADCGenManualTrigger(__VA_ARGS__) +#define ti_lib_aux_adc_get_fifo_status(...) AUXADCGetFifoStatus(__VA_ARGS__) +#define ti_lib_aux_adc_read_fifo(...) AUXADCReadFifo(__VA_ARGS__) +#define ti_lib_aux_adc_pop_fifo(...) AUXADCPopFifo(__VA_ARGS__) +#define ti_lib_aux_adc_select_input(...) AUXADCSelectInput(__VA_ARGS__) +#define ti_lib_aux_adc_get_adjustment_gain(...) AUXADCGetAdjustmentGain(__VA_ARGS__) +#define ti_lib_aux_adc_get_adjustment_offset(...) AUXADCGetAdjustmentOffset(__VA_ARGS__) +#define ti_lib_aux_adc_value_to_microvolts(...) AUXADCValueToMicrovolts(__VA_ARGS__) +#define ti_lib_aux_adc_microvolts_to_value(...) AUXADCMicrovoltsToValue(__VA_ARGS__) +#define ti_lib_aux_adc_adjust_value_for_gain_and_offset(...) AUXADCAdjustValueForGainAndOffset(__VA_ARGS__) +#define ti_lib_aux_adc_unadjust_value_for_gain_and_offset(...) AUXADCUnadjustValueForGainAndOffset(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ /* aux_wuc.h */ #include "driverlib/aux_wuc.h" diff --git a/cpu/mc1322x/contiki-mc1322x-conf.h b/cpu/mc1322x/contiki-mc1322x-conf.h index e6c65df56..2dfb7e0f1 100644 --- a/cpu/mc1322x/contiki-mc1322x-conf.h +++ b/cpu/mc1322x/contiki-mc1322x-conf.h @@ -55,8 +55,8 @@ typedef unsigned short uip_stats_t; typedef uint32_t clock_time_t; -/* Core rtimer.h defaults to 16 bit timer unless RTIMER_CLOCK_LT is defined */ +/* Core rtimer.h defaults to 16 bit timer unless RTIMER_CLOCK_DIFF is defined */ typedef unsigned long rtimer_clock_t; -#define RTIMER_CLOCK_LT(a,b) ((signed long)((a)-(b)) < 0) +#define RTIMER_CLOCK_DIFF(a,b) ((signed long)((a)-(b))) #endif diff --git a/cpu/msp430/dev/uart0-putchar.c b/cpu/msp430/dev/uart0-putchar.c index 819f627d2..96f24abf0 100644 --- a/cpu/msp430/dev/uart0-putchar.c +++ b/cpu/msp430/dev/uart0-putchar.c @@ -1,9 +1,11 @@ #include "dev/uart0.h" -#include +#if !NETSTACK_CONF_WITH_IPV4 +/* In case of IPv4: putchar() is defined by the SLIP driver */ int putchar(int c) { uart0_writeb((char)c); return c; } +#endif /* ! NETSTACK_CONF_WITH_IPV4 */ diff --git a/cpu/msp430/dev/uart1-putchar.c b/cpu/msp430/dev/uart1-putchar.c index 3d7f65c7b..5cb631190 100644 --- a/cpu/msp430/dev/uart1-putchar.c +++ b/cpu/msp430/dev/uart1-putchar.c @@ -1,9 +1,11 @@ -#include #include "dev/uart1.h" +#if !NETSTACK_CONF_WITH_IPV4 +/* In case of IPv4: putchar() is defined by the SLIP driver */ int putchar(int c) { uart1_writeb((char)c); return c; } +#endif /* ! NETSTACK_CONF_WITH_IPV4 */ diff --git a/cpu/native/net/wpcap.c b/cpu/native/net/wpcap.c index f32ba980f..301b07d91 100644 --- a/cpu/native/net/wpcap.c +++ b/cpu/native/net/wpcap.c @@ -525,7 +525,7 @@ wpcap_init(void) // } #else addr.s_addr = inet_addr("10.10.10.10"); //prefer ipv4 default for legacy compatibility -// uiplib_ipaddrconv("aaaa::1",(uip_ipaddr_t*) &addr6.s6_addr); +// uiplib_ipaddrconv("fd00::1",(uip_ipaddr_t*) &addr6.s6_addr); #endif #ifdef UIP_FALLBACK_INTERFACE diff --git a/cpu/nrf52832/Makefile.nrf52832 b/cpu/nrf52832/Makefile.nrf52832 new file mode 100644 index 000000000..f93f063f3 --- /dev/null +++ b/cpu/nrf52832/Makefile.nrf52832 @@ -0,0 +1,262 @@ +ifndef NRF52_SDK_ROOT + $(error NRF52_SDK_ROOT not defined! You must specify where nRF52 SDK resides!) +endif + +ifneq ($(filter %.flash erase,$(MAKECMDGOALS)),) +ifeq ($(NRF52_JLINK_PATH),) +NRF52_JLINK_PATH=$(shell location=$$(which JLinkExe) && dirname $$location) +endif +ifeq ($(NRF52_JLINK_PATH),) + $(error JLink not found in PATH and NRF52_JLINK_PATH path is not defined) +endif +endif + +ifeq ($(CONTIKI_WITH_RIME),1) + $(error Rime stack is not supported!) +endif + +ifneq ($(CONTIKI_WITH_IPV6),1) + $(error Only IPv6 stack is supported!) +endif + +$(info SDK: $(NRF52_SDK_ROOT)) + +ifeq ($(NRF52_DK_REVISION),) +NRF52_DK_REVISION=pca10040 +endif + +ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1) + ifeq ($(NRF52_SOFTDEVICE),) + NRF52_SOFTDEVICE := $(shell find $(NRF52_SDK_ROOT) -name *iot*_softdevice.hex | head -n 1) + endif + $(info SoftDevice: $(NRF52_SOFTDEVICE)) + LINKER_SCRIPT := $(CONTIKI_CPU)/ld/nrf52-$(NRF52_DK_REVISION)-sd.ld +else + LINKER_SCRIPT := $(CONTIKI_CPU)/ld/nrf52.ld +endif + +OUTPUT_FILENAME := $(CONTIKI_PROJECT) +MAKEFILE_NAME := $(MAKEFILE_LIST) +MAKEFILE_DIR := $(dir $(MAKEFILE_NAME) ) + +TEMPLATE_PATH = $(NRF52_SDK_ROOT)/components/toolchain/gcc + +OBJECT_DIRECTORY = $(OBJECTDIR) +LISTING_DIRECTORY := $(OBJECTDIR) +OUTPUT_BINARY_DIRECTORY := bin_$(TARGET) + +MK := mkdir +RM := rm -rf + +# Toolchain commands +CC := arm-none-eabi-gcc +AS := arm-none-eabi-as +AR := arm-none-eabi-ar +LD := arm-none-eabi-ld +NM := arm-none-eabi-nm +OBJDUMP := arm-none-eabi-objdump +OBJCOPY := arm-none-eabi-objcopy +SIZE := arm-none-eabi-size + +# JLink +JLINK := $(NRF52_JLINK_PATH)/JLinkExe +JLINK_OPTS = -Device NRF52 -if swd -speed 1000 +ifneq ($(NRF52_JLINK_SN),) +JLINK_OPTS += -SelectEmuBySN $(NRF52_JLINK_SN) +endif + +#function for removing duplicates in a list +remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-out $(firstword $1),$1)))) + +### CPU-dependent directories +CONTIKI_CPU_DIRS += . dev ble #compat + +### CPU-dependent source files +CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c uart0.c putchar.c watchdog.c + +ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1) +CONTIKI_CPU_SOURCEFILES += ble-core.c ble-mac.c +endif + +CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) + +#source common to all targets +C_SOURCE_FILES += $(NRF52_SDK_ROOT)/components/drivers_nrf/common/nrf_drv_common.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/gpiote/nrf_drv_gpiote.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/rtc/nrf_drv_rtc.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/clock/nrf_drv_clock.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/timer/nrf_drv_timer.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/wdt/nrf_drv_wdt.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/rng/nrf_drv_rng.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/delay/nrf_delay.c \ + $(NRF52_SDK_ROOT)/components/drivers_nrf/uart/nrf_drv_uart.c \ + $(NRF52_SDK_ROOT)/components/libraries/util/app_error.c \ + $(NRF52_SDK_ROOT)/components/toolchain/system_nrf52.c + +ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1) +C_SOURCE_FILES += $(NRF52_SDK_ROOT)/components/softdevice/common/softdevice_handler/softdevice_handler.c \ + $(NRF52_SDK_ROOT)/components/ble/common/ble_advdata.c +else +C_SOURCE_FILES += $(NRF52_SDK_ROOT)/components/libraries/fifo/app_fifo.c \ + $(NRF52_SDK_ROOT)/components/libraries/util/app_util_platform.c +endif + +#assembly files common to all targets +ASM_SOURCE_FILES = $(NRF52_SDK_ROOT)/components/toolchain/gcc/gcc_startup_nrf52.s + +#includes common to all targets +INC_PATHS += components/drivers_nrf/gpiote +INC_PATHS += components/drivers_nrf/hal +INC_PATHS += components/drivers_nrf/config +INC_PATHS += components/drivers_nrf/delay +INC_PATHS += components/drivers_nrf/uart +INC_PATHS += components/drivers_nrf/common +INC_PATHS += components/drivers_nrf/rtc +INC_PATHS += components/drivers_nrf/wdt +INC_PATHS += components/drivers_nrf/rng +INC_PATHS += components/drivers_nrf/clock +INC_PATHS += components/drivers_nrf/timer +INC_PATHS += components/libraries/util +INC_PATHS += components/libraries/timer +INC_PATHS += components/device +INC_PATHS += components/toolchain/gcc +INC_PATHS += components/toolchain +INC_PATHS += examples/bsp + +ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1) +INC_PATHS += components/softdevice/s1xx_iot/headers +INC_PATHS += components/softdevice/s1xx_iot/headers/nrf52 +INC_PATHS += components/softdevice/common/softdevice_handler +INC_PATHS += components/ble/common +INC_PATHS += components/iot/common +INC_PATHS += components/iot/ble_ipsp +else +INC_PATHS += components/drivers_nrf/nrf_soc_nosd +INC_PATHS += components/libraries/fifo +endif + +EXTERNALDIRS += $(addprefix $(NRF52_SDK_ROOT)/, $(INC_PATHS)) + +# Sorting removes duplicates +BUILD_DIRECTORIES := $(sort $(OUTPUT_BINARY_DIRECTORY) $(LISTING_DIRECTORY)) + +# Clean files and directories +CLEAN += bin_$(TARGET) lst_$(TARGET) nrf52832.a *.elf *.hex + +#flags common to all targets +ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1) +CFLAGS += -DSOFTDEVICE_PRESENT +CFLAGS += -DS132 +endif + +ifeq ($(SMALL),1) +CFLAGS += -Os +else +CFLAGS += -O2 +endif + +CFLAGS += -DNRF52 +CFLAGS += -DBOARD_$(shell echo $(NRF52_DK_REVISION) | tr a-z A-Z) +CFLAGS += -D__HEAP_SIZE=512 +CFLAGS += -DSWI_DISABLE0 +CFLAGS += -DCONFIG_GPIO_AS_PINRESET +CFLAGS += -DBLE_STACK_SUPPORT_REQD +CFLAGS += -mcpu=cortex-m4 +CFLAGS += -mthumb -mabi=aapcs --std=gnu99 +CFLAGS += -Wall -Werror +CFLAGS += -ggdb +CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 +# keep every function in separate section. This will allow linker to dump unused functions +CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing +CFLAGS += -fno-builtin --short-enums + +# keep every function in separate section. This will allow linker to dump unused functions +LDFLAGS += -Xlinker -Map=$(LISTING_DIRECTORY)/$(OUTPUT_FILENAME).map +LDFLAGS += -mthumb -mabi=aapcs -L $(TEMPLATE_PATH) -T$(LINKER_SCRIPT) +LDFLAGS += -mcpu=cortex-m4 +LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16 +# let linker to dump unused sections +LDFLAGS += -Wl,--gc-sections +# use newlib in nano version +LDFLAGS += --specs=nano.specs -lc -lnosys + +# Assembler flags +ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1) +ASMFLAGS += -DSOFTDEVICE_PRESENT +ASMFLAGS += -DS132 +endif +ASMFLAGS += -x assembler-with-cpp +ASMFLAGS += -DSWI_DISABLE0 +ASMFLAGS += -DNRF52 +ASMFLAGS += -DBOARD_$(shell echo $(NRF52_DK_REVISION) | tr a-z A-Z) +ASMFLAGS += -DCONFIG_GPIO_AS_PINRESET +ASMFLAGS += -DBLE_STACK_SUPPORT_REQD + +C_SOURCE_FILE_NAMES = $(notdir $(C_SOURCE_FILES)) +C_PATHS = $(call remduplicates, $(dir $(C_SOURCE_FILES) ) ) +C_OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(C_SOURCE_FILE_NAMES:.c=.o) ) + +ASM_SOURCE_FILE_NAMES = $(notdir $(ASM_SOURCE_FILES)) +ASM_PATHS = $(call remduplicates, $(dir $(ASM_SOURCE_FILES) )) +ASM_OBJECTS = $(addprefix $(OBJECT_DIRECTORY)/, $(ASM_SOURCE_FILE_NAMES:.s=.o) ) + +vpath %.c $(C_PATHS) +vpath %.s $(ASM_PATHS) + +OBJECTS = $(C_OBJECTS) $(ASM_OBJECTS) + +TARGET_LIBS= nrf52832.a $(NRF52_SDK_ROOT)/components/iot/ble_6lowpan/lib/ble_6lowpan.a + +### Don't treat the .elf as intermediate +.PRECIOUS: %.hex %.bin + +nrf52832.a: $(OBJECTS) + $(TRACE_AR) + $(Q)$(AR) $(AROPTS) $@ $^ + +### Compilation rules +CUSTOM_RULE_LINK=1 + +%.elf: $(TARGET_STARTFILES) %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(TARGET_LIBS) + $(TRACE_LD) + $(Q)$(CC) $(LDFLAGS) ${filter %o %.co %.a,$^} -o $@ + +# Assemble files +$(OBJECT_DIRECTORY)/%.o: %.s + @echo Compiling file: $(notdir $<) + $(Q)$(CC) $(ASMFLAGS) $(addprefix -I$(NRF52_SDK_ROOT)/, $(INC_PATHS)) -c -o $@ $< + +# Create binary file from the .out file +%.bin: %.elf + @echo Preparing: $@ + $(Q)$(OBJCOPY) -O binary $^ $@ + +# Create binary .hex file from the .out file +%.hex: %.elf + @echo Preparing: $@ + $(Q)$(OBJCOPY) -O ihex $^ $@ + +### We don't really need the .hex and .bin for the .$(TARGET) but let's make +### sure they get built +%.$(TARGET): %.elf %.hex %.bin + cp $*.elf $@ + $(Q)$(SIZE) $@ + +%.jlink: + sed -e 's/#OUTPUT_FILENAME#/$*.hex/' $(CONTIKI_CPU)/flash.jlink > $@ + +%.flash: %.hex %.jlink + @echo Flashing: $^ + $(JLINK) $(JLINK_OPTS) -CommanderScript $*.jlink + +softdevice.jlink: + sed -e 's,#OUTPUT_FILENAME#,$(NRF52_SOFTDEVICE),' $(CONTIKI_CPU)/flash.jlink > $@ + +softdevice.flash: softdevice.jlink + @echo Flashing: $(notdir $(NRF52_SOFTDEVICE)) + $(JLINK) $(JLINK_OPTS) -CommanderScript $^ + +erase: + $(JLINK) $(JLINK_OPTS) -CommanderScript $(CONTIKI_CPU)/erase.jlink + +.PHONY: softdevice.jlink diff --git a/cpu/nrf52832/ble/ble-core.c b/cpu/nrf52832/ble/ble-core.c new file mode 100644 index 000000000..cb3d4ce66 --- /dev/null +++ b/cpu/nrf52832/ble/ble-core.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup cpu + * @{ + * + * \addtogroup nrf52832 + * @{ + * + * \addtogroup nrf52832-ble Bluetooth Low Energy drivers + * @{ + * + * \file + * Basic BLE functions. + * \author + * Wojciech Bober + * + */ +#include +#include +#include "boards.h" +#include "nordic_common.h" +#include "nrf_delay.h" +#include "nrf_sdm.h" +#include "ble_advdata.h" +#include "ble_srv_common.h" +#include "ble_ipsp.h" +#include "softdevice_handler.h" +#include "app_error.h" +#include "iot_defines.h" +#include "ble-core.h" + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#define IS_SRVC_CHANGED_CHARACT_PRESENT 1 +#define APP_ADV_TIMEOUT 0 /**< Time for which the device must be advertising in non-connectable mode (in seconds). 0 disables timeout. */ +#define APP_ADV_ADV_INTERVAL MSEC_TO_UNITS(333, UNIT_0_625_MS) /**< The advertising interval. This value can vary between 100ms to 10.24s). */ + +static ble_gap_adv_params_t m_adv_params; /**< Parameters to be passed to the stack when starting advertising. */ + +static void +ble_evt_dispatch(ble_evt_t * p_ble_evt); +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize and enable the BLE stack. + */ +void +ble_stack_init(void) +{ + uint32_t err_code; + + // Enable BLE stack. + ble_enable_params_t ble_enable_params; + memset(&ble_enable_params, 0, sizeof(ble_enable_params)); + ble_enable_params.gatts_enable_params.attr_tab_size = + BLE_GATTS_ATTR_TAB_SIZE_DEFAULT; + ble_enable_params.gatts_enable_params.service_changed = + IS_SRVC_CHANGED_CHARACT_PRESENT; + err_code = sd_ble_enable(&ble_enable_params); + APP_ERROR_CHECK(err_code); + + // Register with the SoftDevice handler module for BLE events. + err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch); + APP_ERROR_CHECK(err_code); + + // Setup address + ble_gap_addr_t ble_addr; + err_code = sd_ble_gap_address_get(&ble_addr); + APP_ERROR_CHECK(err_code); + + ble_addr.addr[5] = 0x00; + ble_addr.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC; + + err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &ble_addr); + APP_ERROR_CHECK(err_code); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return device EUI64 MAC address + * \param addr pointer to a buffer to store the address + */ +void +ble_get_mac(uint8_t addr[8]) +{ + uint32_t err_code; + ble_gap_addr_t ble_addr; + + err_code = sd_ble_gap_address_get(&ble_addr); + APP_ERROR_CHECK(err_code); + + IPV6_EUI64_CREATE_FROM_EUI48(addr, ble_addr.addr, ble_addr.addr_type); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize BLE advertising data. + * \param name Human readable device name that will be advertised + */ +void +ble_advertising_init(const char *name) +{ + uint32_t err_code; + ble_advdata_t advdata; + uint8_t flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED; + ble_gap_conn_sec_mode_t sec_mode; + + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); + + err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *)name, + strlen(name)); + APP_ERROR_CHECK(err_code); + + ble_uuid_t adv_uuids[] = {{BLE_UUID_IPSP_SERVICE, BLE_UUID_TYPE_BLE}}; + + // Build and set advertising data. + memset(&advdata, 0, sizeof(advdata)); + + advdata.name_type = BLE_ADVDATA_FULL_NAME; + advdata.flags = flags; + advdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]); + advdata.uuids_complete.p_uuids = adv_uuids; + + err_code = ble_advdata_set(&advdata, NULL); + APP_ERROR_CHECK(err_code); + + // Initialize advertising parameters (used when starting advertising). + memset(&m_adv_params, 0, sizeof(m_adv_params)); + + m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND; + m_adv_params.p_peer_addr = NULL; // Undirected advertisement. + m_adv_params.fp = BLE_GAP_ADV_FP_ANY; + m_adv_params.interval = APP_ADV_ADV_INTERVAL; + m_adv_params.timeout = APP_ADV_TIMEOUT; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Start BLE advertising. + */ +void +ble_advertising_start(void) +{ + uint32_t err_code; + + err_code = sd_ble_gap_adv_start(&m_adv_params); + APP_ERROR_CHECK(err_code); + + PRINTF("ble-core: advertising started\n"); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Print GAP address. + * \param addr a pointer to address + */ +void +ble_gap_addr_print(const ble_gap_addr_t *addr) +{ + unsigned int i; + for(i = 0; i < sizeof(addr->addr); i++) { + if(i > 0) { + PRINTF(":"); + }PRINTF("%02x", addr->addr[i]); + }PRINTF(" (%d)", addr->addr_type); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Function for handling the Application's BLE Stack events. + * \param[in] p_ble_evt Bluetooth stack event. + */ +static void +on_ble_evt(ble_evt_t *p_ble_evt) +{ + switch(p_ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + PRINTF("ble-core: connected [handle:%d, peer: ", p_ble_evt->evt.gap_evt.conn_handle); + ble_gap_addr_print(&(p_ble_evt->evt.gap_evt.params.connected.peer_addr)); + PRINTF("]\n"); + sd_ble_gap_rssi_start(p_ble_evt->evt.gap_evt.conn_handle, + BLE_GAP_RSSI_THRESHOLD_INVALID, + 0); + break; + + case BLE_GAP_EVT_DISCONNECTED: + PRINTF("ble-core: disconnected [handle:%d]\n", p_ble_evt->evt.gap_evt.conn_handle); + ble_advertising_start(); + break; + default: + break; + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief SoftDevice BLE event callback. + * \param[in] p_ble_evt Bluetooth stack event. + */ +static void +ble_evt_dispatch(ble_evt_t *p_ble_evt) +{ + ble_ipsp_evt_handler(p_ble_evt); + on_ble_evt(p_ble_evt); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + */ diff --git a/cpu/nrf52832/ble/ble-core.h b/cpu/nrf52832/ble/ble-core.h new file mode 100644 index 000000000..84c181d2e --- /dev/null +++ b/cpu/nrf52832/ble/ble-core.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup cpu + * @{ + * + * \addtogroup nrf52832 + * @{ + * + * \addtogroup nrf52832-ble Bluetooth Low Energy drivers + * @{ + * + * \file + * Basic BLE functions. + * \author + * Wojciech Bober + */ +#ifndef DEV_BLE_H_ +#define DEV_BLE_H_ + +#include + +void ble_stack_init(void); +void ble_advertising_init(const char *name); +void ble_advertising_start(void); +void ble_get_mac(uint8_t addr[8]); + +#endif /* DEV_BLE_H_ */ + +/** + * @} + * @} + * @} + */ diff --git a/cpu/nrf52832/ble/ble-mac.c b/cpu/nrf52832/ble/ble-mac.c new file mode 100644 index 000000000..6ffd87a82 --- /dev/null +++ b/cpu/nrf52832/ble/ble-mac.c @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832-ble + * @{ + * + * \file + * A MAC protocol implementation that uses nRF52 IPSP implementation + * as a link layer. + * \author + * Wojciech Bober + */ +#include +#include +#include "app_error.h" +#include "ble_ipsp.h" +#include "nrf_soc.h" +#include "iot_defines.h" + +#include "net/mac/nullmac.h" +#include "net/netstack.h" +#include "net/ip/uip.h" +#include "net/ip/tcpip.h" +#include "net/packetbuf.h" +#include "net/netstack.h" +#include "net/linkaddr.h" + +#include "dev/watchdog.h" + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#ifndef BLE_MAC_MAX_INTERFACE_NUM +#define BLE_MAC_MAX_INTERFACE_NUM 1 /**< Maximum number of interfaces, i.e., connection to master devices */ +#endif + +/*---------------------------------------------------------------------------*/ +process_event_t ble_event_interface_added; /**< This event is broadcast when BLE connection is established */ +process_event_t ble_event_interface_deleted; /**< This event is broadcast when BLE connection is destroyed */ + +/*---------------------------------------------------------------------------*/ +PROCESS(ble_ipsp_process, "BLE IPSP process"); + +/*---------------------------------------------------------------------------*/ +/** + * \brief A structure that binds IPSP connection with a peer address. + */ +typedef struct { + eui64_t peer_addr; + ble_ipsp_handle_t handle; +} ble_mac_interface_t; + +static ble_mac_interface_t interfaces[BLE_MAC_MAX_INTERFACE_NUM]; + +static volatile int busy_tx; /**< Flag is set to 1 when the driver is busy transmitting a packet. */ +static volatile int busy_rx; /**< Flag is set to 1 when there is a received packet pending. */ + +struct { + eui64_t src; + uint8_t payload[PACKETBUF_SIZE]; + uint16_t len; + int8_t rssi; +} input_packet; + +static mac_callback_t mac_sent_cb; +static void *mac_sent_ptr; + +/*---------------------------------------------------------------------------*/ +/** + * \brief Lookup interface by IPSP connection. + * + * \param handle a pointer to IPSP handle. + * \retval a pointer to interface structure + * \retval NULL if no interface has been found for a given handle + */ +static ble_mac_interface_t * +ble_mac_interface_lookup(ble_ipsp_handle_t *handle) +{ + int i; + for(i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) { + if(interfaces[i].handle.conn_handle == handle->conn_handle && + interfaces[i].handle.cid == handle->cid) { + return &interfaces[i]; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Add IPSP connection to the interface table. + * + * This function binds IPSP connection with peer address. + * + * \param peer a pointer to eui64 address + * \param handle a pointer to IPSP handle + * + * \retval a pointer to an interface structure on success + * \retval NULL if interface table is full + */ +static ble_mac_interface_t * +ble_mac_interface_add(eui64_t *peer, ble_ipsp_handle_t *handle) +{ + int i; + for(i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) { + if(interfaces[i].handle.conn_handle == 0 && interfaces[i].handle.cid == 0) { + memcpy(&interfaces[i].handle, handle, sizeof(ble_ipsp_handle_t)); + memcpy(&interfaces[i].peer_addr, peer, sizeof(eui64_t)); + process_post(PROCESS_BROADCAST, ble_event_interface_added, NULL); + return &interfaces[i]; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Remove interface from the interface table. + * \param interface a pointer to interface + */ +static void +ble_mac_interface_delete(ble_mac_interface_t *interface) +{ + memset(interface, 0, sizeof(ble_mac_interface_t)); + process_post(PROCESS_BROADCAST, ble_event_interface_deleted, NULL); +} + +/*---------------------------------------------------------------------------*/ +/** + * \brief Callback registered with IPSP to receive asynchronous events from the module. + * \note This function is called from SoftDevice interrupt context. + * + * \param[in] p_handle Pointer to IPSP handle. + * \param[in] p_evt Pointer to specific event, generated by IPSP module. + * + * \return NRF_SUCCESS on success, otherwise NRF_ERROR_NO_MEM error. + */ +static uint32_t +ble_mac_ipsp_evt_handler_irq(ble_ipsp_handle_t *p_handle, ble_ipsp_evt_t *p_evt) +{ + uint32_t retval = NRF_SUCCESS; + + ble_mac_interface_t *p_instance = NULL; + p_instance = ble_mac_interface_lookup(p_handle); + + if(p_handle) { + PRINTF("ble-mac: IPSP event [handle:%d CID 0x%04X]\n", p_handle->conn_handle, p_handle->cid); + } + + switch(p_evt->evt_id) { + case BLE_IPSP_EVT_CHANNEL_CONNECTED: { + eui64_t peer_addr; + + PRINTF("ble-mac: channel connected\n"); + + IPV6_EUI64_CREATE_FROM_EUI48( + peer_addr.identifier, + p_evt->evt_param->params.ch_conn_request.peer_addr.addr, + p_evt->evt_param->params.ch_conn_request.peer_addr.addr_type); + + p_instance = ble_mac_interface_add(&peer_addr, p_handle); + + if(p_instance != NULL) { + PRINTF("ble-mac: added new IPSP interface\n"); + } else { + PRINTF("ble-mac: cannot add new interface. Table is full\n"); + ble_ipsp_disconnect(p_handle); + } + break; + } + + case BLE_IPSP_EVT_CHANNEL_DISCONNECTED: { + PRINTF("ble-mac: channel disconnected\n"); + if(p_instance != NULL) { + PRINTF("ble-mac: removed IPSP interface\n"); + ble_mac_interface_delete(p_instance); + } + break; + } + + case BLE_IPSP_EVT_CHANNEL_DATA_RX: { + PRINTF("ble-mac: data received\n"); + if(p_instance != NULL) { + if(busy_rx) { + PRINTF("ble-mac: packet dropped as input buffer is busy\n"); + break; + } + + if(p_evt->evt_param->params.ch_rx.len > PACKETBUF_SIZE) { + PRINTF("ble-mac: packet buffer is too small!\n"); + break; + } + + busy_rx = 1; + + input_packet.len = p_evt->evt_param->params.ch_rx.len; + memcpy(input_packet.payload, p_evt->evt_param->params.ch_rx.p_data, input_packet.len); + memcpy(input_packet.src.identifier, p_instance->peer_addr.identifier, sizeof(eui64_t)); + sd_ble_gap_rssi_get(p_handle->conn_handle, &input_packet.rssi); + + process_poll(&ble_ipsp_process); + } else { + PRINTF("ble-mac: got data to unknown interface!\n"); + } + break; + } + + case BLE_IPSP_EVT_CHANNEL_DATA_TX_COMPLETE: { + PRINTF("ble-mac: data transmitted\n"); + busy_tx = 0; + break; + } + } + + return retval; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(ble_ipsp_process, ev, data) +{ + PROCESS_BEGIN(); + + while(1) { + PROCESS_WAIT_EVENT(); + if(ev == PROCESS_EVENT_POLL) { + packetbuf_copyfrom(input_packet.payload, input_packet.len); + packetbuf_set_attr(PACKETBUF_ATTR_RSSI, input_packet.rssi); + packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (const linkaddr_t *)input_packet.src.identifier); + packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &linkaddr_node_addr); + busy_rx = 0; + NETSTACK_LLSEC.input(); + } + } + + PROCESS_END(); +} + +/*---------------------------------------------------------------------------*/ +/** + * \brief Lookup IPSP handle by peer address. + * + * \param addr a pointer to eui64 address. + * \retval a pointer to IPSP handle on success + * \retval NULL if an IPSP handle for given address haven't been found + */ +static ble_ipsp_handle_t * +find_handle(const linkaddr_t *addr) +{ + int i; + for(i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) { + if(linkaddr_cmp((const linkaddr_t *)&interfaces[i].peer_addr, addr)) { + return &interfaces[i].handle; + } + } + return NULL; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Send packet on a given IPSP handle. + * + * \param handle a pointer to IPSP handle. + * \return 1 on success, 0 otherwise + */ +static int +send_to_peer(ble_ipsp_handle_t *handle) +{ + PRINTF("ble-mac: sending packet[GAP handle:%d CID:0x%04X]\n", handle->conn_handle, handle->cid); + return (ble_ipsp_send(handle, packetbuf_dataptr(), packetbuf_datalen()) == NRF_SUCCESS); +} +/*---------------------------------------------------------------------------*/ +static void +send_packet(mac_callback_t sent, void *ptr) +{ + int i; + const linkaddr_t *dest; + ble_ipsp_handle_t *handle; + int ret = 0; + + mac_sent_cb = sent; + mac_sent_ptr = ptr; + + dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); + + if(linkaddr_cmp(dest, &linkaddr_null)) { + for(i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) { + if(interfaces[i].handle.cid != 0 && interfaces[i].handle.conn_handle != 0) { + ret = send_to_peer(&interfaces[i].handle); + watchdog_periodic(); + } + } + } else if((handle = find_handle(dest)) != NULL) { + ret = send_to_peer(handle); + } else { + PRINTF("ble-mac: no connection found for peer"); + } + + if(ret) { + busy_tx = 1; + while(busy_tx) { + watchdog_periodic(); + sd_app_evt_wait(); + } + mac_call_sent_callback(sent, ptr, MAC_TX_OK, 1); + } else { + mac_call_sent_callback(sent, ptr, MAC_TX_ERR, 1); + } +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +off(int keep_radio_on) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static unsigned short +channel_check_interval(void) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ +// Initialize IPSP service + uint32_t err_code; + ble_ipsp_init_t ipsp_init_params; + + memset(&ipsp_init_params, 0, sizeof(ipsp_init_params)); + ipsp_init_params.evt_handler = ble_mac_ipsp_evt_handler_irq; + err_code = ble_ipsp_init(&ipsp_init_params); + APP_ERROR_CHECK(err_code); + + ble_event_interface_added = process_alloc_event(); + ble_event_interface_deleted = process_alloc_event(); + + process_start(&ble_ipsp_process, NULL); +} +/*---------------------------------------------------------------------------*/ +const struct mac_driver ble_ipsp_mac_driver = { + "nRF52 IPSP driver", + init, + send_packet, + NULL, + on, + off, + channel_check_interval, +}; +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/cpu/nrf52832/ble/ble-mac.h b/cpu/nrf52832/ble/ble-mac.h new file mode 100644 index 000000000..3dd9b82af --- /dev/null +++ b/cpu/nrf52832/ble/ble-mac.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832-ble + * @{ + * + * \file + * A MAC protocol implementation that uses nRF52 IPSP implementation + * as a link layer. + * \author + * Wojciech Bober + */ +#ifndef BLE_MAC_H_ +#define BLE_MAC_H_ + +#include "sys/process.h" +#include "net/mac/mac.h" + +extern const struct mac_driver ble_ipsp_mac_driver; /**< BLE over IPSP MAC driver structure */ +extern process_event_t ble_event_interface_added; /**< This event is broadcast when a new IPSP connection is established */ +extern process_event_t ble_event_interface_deleted; /**< This event is broadcast when a IPSP connection is deleted */ + +#endif /* BLE_MAC_H_ */ +/** + * @} + */ diff --git a/cpu/nrf52832/dev/clock.c b/cpu/nrf52832/dev/clock.c new file mode 100644 index 000000000..4ee09839d --- /dev/null +++ b/cpu/nrf52832/dev/clock.c @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup nrf52832 + * @{ + * + * \addtogroup nrf52832-dev Device drivers + * @{ + * + * \addtogroup nrf52832-clock Clock driver + * @{ + * + * \file + * Software clock implementation for the nRF52. + * \author + * Wojciech Bober + * + */ +/*---------------------------------------------------------------------------*/ +#include +#include +#include "nrf.h" +#include "nrf_drv_config.h" +#include "nrf_drv_rtc.h" +#include "nrf_drv_clock.h" +#include "nrf_delay.h" +#include "app_error.h" +#include "contiki.h" +#include "platform-conf.h" + +/*---------------------------------------------------------------------------*/ +const nrf_drv_rtc_t rtc = NRF_DRV_RTC_INSTANCE(PLATFORM_RTC_INSTANCE_ID); /**< RTC instance used for platform clock */ +/*---------------------------------------------------------------------------*/ +static volatile uint32_t ticks; +void clock_update(void); + +#define TICKS (RTC1_CONFIG_FREQUENCY/CLOCK_CONF_SECOND) + +/** + * \brief Function for handling the RTC0 interrupts + * \param int_type Type of interrupt to be handled + */ +static void +rtc_handler(nrf_drv_rtc_int_type_t int_type) +{ + if (int_type == NRF_DRV_RTC_INT_TICK) { + clock_update(); + } +} + +#ifndef SOFTDEVICE_PRESENT +/** \brief Function starting the internal LFCLK XTAL oscillator. + */ +static void +lfclk_config(void) +{ + ret_code_t err_code = nrf_drv_clock_init(NULL); + APP_ERROR_CHECK(err_code); + + nrf_drv_clock_lfclk_request(); +} +#endif + +/** + * \brief Function initialization and configuration of RTC driver instance. + */ +static void +rtc_config(void) +{ + uint32_t err_code; + + //Initialize RTC instance + err_code = nrf_drv_rtc_init(&rtc, NULL, rtc_handler); + APP_ERROR_CHECK(err_code); + + //Enable tick event & interrupt + nrf_drv_rtc_tick_enable(&rtc, true); + + //Power on RTC instance + nrf_drv_rtc_enable(&rtc); +} +/*---------------------------------------------------------------------------*/ +void +clock_init(void) +{ + ticks = 0; +#ifndef SOFTDEVICE_PRESENT + lfclk_config(); +#endif + rtc_config(); +} +/*---------------------------------------------------------------------------*/ +CCIF clock_time_t +clock_time(void) +{ + return (clock_time_t)(ticks & 0xFFFFFFFF); +} +/*---------------------------------------------------------------------------*/ +void +clock_update(void) +{ + ticks++; + if (etimer_pending()) { + etimer_request_poll(); + } +} +/*---------------------------------------------------------------------------*/ +CCIF unsigned long +clock_seconds(void) +{ + return (unsigned long)ticks/CLOCK_CONF_SECOND; +} +/*---------------------------------------------------------------------------*/ +void +clock_wait(clock_time_t i) +{ + clock_time_t start; + start = clock_time(); + while (clock_time() - start < (clock_time_t)i) { + __WFE(); + } +} +/*---------------------------------------------------------------------------*/ +void +clock_delay_usec(uint16_t dt) +{ + nrf_delay_us(dt); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Obsolete delay function but we implement it here since some code + * still uses it + */ +void +clock_delay(unsigned int i) +{ + clock_delay_usec(i); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + */ diff --git a/cpu/nrf52832/dev/lpm.h b/cpu/nrf52832/dev/lpm.h new file mode 100644 index 000000000..192165a49 --- /dev/null +++ b/cpu/nrf52832/dev/lpm.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832-dev Device drivers + * @{ + * + * \addtogroup nrf52832-lpm Low power mode functions + * @{ + * + * \file + * A header file for low power mode functions. + * \author + * Wojciech Bober + */ +#ifndef LPM_H +#define LPM_H + +#ifdef SOFTDEVICE_PRESENT +#include "nrf_soc.h" +#endif + +/** + * \brief Stop and wait for an event + * + */ +static inline void +lpm_drop(void) +{ +#ifdef SOFTDEVICE_PRESENT + sd_app_evt_wait(); +#else + __WFI(); +#endif +} + +#endif /* DEV_LPM_H_ */ +/** + * @} + * @} + */ diff --git a/cpu/nrf52832/dev/random.c b/cpu/nrf52832/dev/random.c new file mode 100644 index 000000000..d21bf18ff --- /dev/null +++ b/cpu/nrf52832/dev/random.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832 + * @{ + * + * \addtogroup nrf52832-dev Device drivers + * @{ + * + * \addtogroup nrf52832-rng Hardware random number generator + * @{ + * + * \file + * Random number generator routines exploiting the nRF52 hardware + * capabilities. + * + * This file overrides core/lib/random.c. + * + * \author + * Wojciech Bober + */ +#include +#include +#include "app_error.h" +/*---------------------------------------------------------------------------*/ +/** + * \brief Generates a new random number using the nRF52 RNG. + * \return a random number. + */ +unsigned short +random_rand(void) +{ + unsigned short value = 42; + uint8_t available; + ret_code_t err_code; + + do { + nrf_drv_rng_bytes_available(&available); + } while (available < sizeof(value)); + + err_code = nrf_drv_rng_rand((uint8_t *)&value, sizeof(value)); + APP_ERROR_CHECK(err_code); + + return value; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize the nRF52 random number generator. + * \param seed Ignored. It's here because the function prototype is in core. + * + */ +void +random_init(unsigned short seed) +{ + (void)seed; + ret_code_t err_code = nrf_drv_rng_init(NULL); + APP_ERROR_CHECK(err_code); +} +/** + * @} + * @} + * @} + */ diff --git a/cpu/nrf52832/dev/uart0.c b/cpu/nrf52832/dev/uart0.c new file mode 100644 index 000000000..df9c7b9e3 --- /dev/null +++ b/cpu/nrf52832/dev/uart0.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832-dev Device drivers + * @{ + * + * \addtogroup nrf52832-uart UART driver + * @{ + * + * \file + * Contiki compatible UART driver. + * \author + * Wojciech Bober + */ +#include +#include "nrf.h" +#include "nrf_drv_config.h" +#include "nrf_drv_uart.h" +#include "app_util_platform.h" +#include "app_error.h" + +#include "contiki.h" +#include "dev/uart0.h" +#include "dev/watchdog.h" +#include "lib/ringbuf.h" + +#define TXBUFSIZE 128 +static uint8_t rx_buffer[1]; + +static int (*uart0_input_handler)(unsigned char c); + +static struct ringbuf txbuf; +static uint8_t txbuf_data[TXBUFSIZE]; + +/*---------------------------------------------------------------------------*/ +static void +uart_event_handler(nrf_drv_uart_event_t * p_event, void * p_context) +{ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + if (p_event->type == NRF_DRV_UART_EVT_RX_DONE) { + if (uart0_input_handler != NULL) { + uart0_input_handler(p_event->data.rxtx.p_data[0]); + } + (void)nrf_drv_uart_rx(rx_buffer, 1); + } else if (p_event->type == NRF_DRV_UART_EVT_TX_DONE) { + if (ringbuf_elements(&txbuf) > 0) { + uint8_t c = ringbuf_get(&txbuf); + nrf_drv_uart_tx(&c, 1); + } + } + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +/*---------------------------------------------------------------------------*/ +void +uart0_set_input(int (*input)(unsigned char c)) +{ + uart0_input_handler = input; +} +/*---------------------------------------------------------------------------*/ +void +uart0_writeb(unsigned char c) +{ + if (nrf_drv_uart_tx(&c, 1) == NRF_ERROR_BUSY) { + while (ringbuf_put(&txbuf, c) == 0) { + __WFE(); + } + } +} +/*---------------------------------------------------------------------------*/ +/** + * Initialize the RS232 port. + * + */ +void +uart0_init(unsigned long ubr) +{ + nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG; + ret_code_t retcode = nrf_drv_uart_init(&config, uart_event_handler); + APP_ERROR_CHECK(retcode); + + ringbuf_init(&txbuf, txbuf_data, sizeof(txbuf_data)); + + nrf_drv_uart_rx_enable(); + nrf_drv_uart_rx(rx_buffer, 1); +} +/** + * @} + * @} + */ diff --git a/cpu/nrf52832/dev/uart0.h b/cpu/nrf52832/dev/uart0.h new file mode 100644 index 000000000..c6b3938ea --- /dev/null +++ b/cpu/nrf52832/dev/uart0.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832-dev Device drivers + * @{ + * + * \addtogroup nrf52832-uart UART driver + * @{ + * + * \file + * A header file for Contiki compatible UART driver. + * \author + * Wojciech Bober + */ +#ifndef UART_0_H +#define UART_0_H + +#include +#include "contiki-conf.h" + +void uart0_init(); +void uart0_writeb(uint8_t byte); + +void uart0_set_input(int (* input)(unsigned char c)); + +#endif /* UART_0_H */ +/** + * @} + * @} + */ diff --git a/cpu/nrf52832/dev/watchdog.c b/cpu/nrf52832/dev/watchdog.c new file mode 100644 index 000000000..50e26d72b --- /dev/null +++ b/cpu/nrf52832/dev/watchdog.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832-dev Device drivers + * @{ + * + * \addtogroup nrf52832-watchdog Watchdog driver + * @{ + * + * \file + * Contiki compatible watchdog driver implementation. + * \author + * Wojciech Bober + */ +#include +#include "app_error.h" +#include "contiki-conf.h" + +static nrf_drv_wdt_channel_id wdt_channel_id; +static uint8_t wdt_initialized = 0; + +/** + * \brief WDT events handler. + */ +static void wdt_event_handler(void) +{ + LEDS_OFF(LEDS_MASK); +} + +/*---------------------------------------------------------------------------*/ +void +watchdog_init(void) +{ + ret_code_t err_code; + err_code = nrf_drv_wdt_init(NULL, &wdt_event_handler); + APP_ERROR_CHECK(err_code); + err_code = nrf_drv_wdt_channel_alloc(&wdt_channel_id); + APP_ERROR_CHECK(err_code); + wdt_initialized = 1; +} +/*---------------------------------------------------------------------------*/ +void +watchdog_start(void) +{ + if(wdt_initialized) { + nrf_drv_wdt_enable(); + } +} +/*---------------------------------------------------------------------------*/ +void +watchdog_periodic(void) +{ + if(wdt_initialized) { + nrf_drv_wdt_channel_feed(wdt_channel_id); + } +} +/*---------------------------------------------------------------------------*/ +void +watchdog_reboot(void) +{ + NVIC_SystemReset(); +} +/** + * @} + * @} + */ diff --git a/cpu/nrf52832/erase.jlink b/cpu/nrf52832/erase.jlink new file mode 100644 index 000000000..5f08d8d86 --- /dev/null +++ b/cpu/nrf52832/erase.jlink @@ -0,0 +1,2 @@ +erase +q \ No newline at end of file diff --git a/cpu/nrf52832/flash.jlink b/cpu/nrf52832/flash.jlink new file mode 100644 index 000000000..787670d55 --- /dev/null +++ b/cpu/nrf52832/flash.jlink @@ -0,0 +1,4 @@ +loadfile #OUTPUT_FILENAME# +r +g +q \ No newline at end of file diff --git a/cpu/nrf52832/ld/nrf52-pca10036-sd.ld b/cpu/nrf52832/ld/nrf52-pca10036-sd.ld new file mode 100644 index 000000000..455749e29 --- /dev/null +++ b/cpu/nrf52832/ld/nrf52-pca10036-sd.ld @@ -0,0 +1,12 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +GROUP(-lgcc -lc -lnosys) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x1f000, LENGTH = 0x61000 + RAM (rwx) : ORIGIN = 0x08000000, LENGTH = 0x8000 +} + +INCLUDE "nrf5x_common.ld" \ No newline at end of file diff --git a/cpu/nrf52832/ld/nrf52-pca10040-sd.ld b/cpu/nrf52832/ld/nrf52-pca10040-sd.ld new file mode 100644 index 000000000..f30aad455 --- /dev/null +++ b/cpu/nrf52832/ld/nrf52-pca10040-sd.ld @@ -0,0 +1,12 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +GROUP(-lgcc -lc -lnosys) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x1f000, LENGTH = 0x61000 + RAM (rwx) : ORIGIN = 0x20002800, LENGTH = 0xD800 +} + +INCLUDE "nrf5x_common.ld" \ No newline at end of file diff --git a/cpu/nrf52832/ld/nrf52.ld b/cpu/nrf52832/ld/nrf52.ld new file mode 100644 index 000000000..268794d04 --- /dev/null +++ b/cpu/nrf52832/ld/nrf52.ld @@ -0,0 +1,12 @@ +/* Linker script to configure memory regions. */ + +SEARCH_DIR(.) +GROUP(-lgcc -lc -lnosys) + +MEMORY +{ + FLASH (rx) : ORIGIN = 0x0, LENGTH = 0x80000 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x8000 +} + +INCLUDE "nrf5x_common.ld" \ No newline at end of file diff --git a/cpu/nrf52832/mtarch.h b/cpu/nrf52832/mtarch.h new file mode 100644 index 000000000..4f696669d --- /dev/null +++ b/cpu/nrf52832/mtarch.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* + * \file + * Stub header file for multi-threading. It doesn't do anything, it + * just exists so that mt.c can compile cleanly. + * + * This is based on the original mtarch.h for z80 by Takahide Matsutsuka + * + * \author + * George Oikonomou - + */ +#ifndef __MTARCH_H__ +#define __MTARCH_H__ + +struct mtarch_thread { + unsigned char *sp; +}; + +#endif /* __MTARCH_H__ */ diff --git a/cpu/nrf52832/putchar.c b/cpu/nrf52832/putchar.c new file mode 100644 index 000000000..c4163ba3d --- /dev/null +++ b/cpu/nrf52832/putchar.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832 + * @{ + * + * \file + * Hardware specific implementation of putchar() and puts() functions. + * \author + * Wojciech Bober + * + */ +/*---------------------------------------------------------------------------*/ +#include +#include "dev/uart0.h" +/*---------------------------------------------------------------------------*/ +int +putchar(int c) +{ + uart0_writeb(c); + return c; +} +/*---------------------------------------------------------------------------*/ +int +puts(const char *str) +{ + int i; + + if (str == NULL) { + return 0; + } + + for (i = 0; i < strlen(str); i++) { + uart0_writeb(str[i]); + } + + uart0_writeb('\n'); + return i; +} +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/cpu/nrf52832/rtimer-arch.c b/cpu/nrf52832/rtimer-arch.c new file mode 100644 index 000000000..78f4790f2 --- /dev/null +++ b/cpu/nrf52832/rtimer-arch.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * \addtogroup nrf52832 + * @{ + * + * \file + * Implementation of the architecture dependent rtimer functions for the nRF52 + * + * \author + * Wojciech Bober + */ +/*---------------------------------------------------------------------------*/ +#include +#include +#include "nrf.h" +#include "nrf_drv_timer.h" +#include "app_error.h" +#include "contiki.h" +#include "platform-conf.h" + +static const nrf_drv_timer_t timer = NRF_DRV_TIMER_INSTANCE(PLATFORM_TIMER_INSTANCE_ID); /**< Timer instance used for rtimer */ + +/** + * \brief Handler for timer events. + * + * \param event_type type of an event that should be handled + * \param p_context opaque data pointer passed from nrf_drv_timer_init() + */ +static void +timer_event_handler(nrf_timer_event_t event_type, void* p_context) +{ + switch (event_type) { + case NRF_TIMER_EVENT_COMPARE1: + rtimer_run_next(); + break; + + default: + //Do nothing. + break; + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize platform rtimer + */ +void +rtimer_arch_init(void) +{ + ret_code_t err_code = nrf_drv_timer_init(&timer, NULL, timer_event_handler); + APP_ERROR_CHECK(err_code); + nrf_drv_timer_enable(&timer); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Schedules an rtimer task to be triggered at time t + * \param t The time when the task will need executed. + * + * \e t is an absolute time, in other words the task will be executed AT + * time \e t, not IN \e t rtimer ticks. + * + * This function schedules a one-shot event with the nRF RTC. + */ +void +rtimer_arch_schedule(rtimer_clock_t t) +{ + nrf_drv_timer_compare(&timer, NRF_TIMER_CC_CHANNEL1, t, true); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the current real-time clock time + * \return The current rtimer time in ticks + * + */ +rtimer_clock_t +rtimer_arch_now() +{ + return nrf_drv_timer_capture(&timer, NRF_TIMER_CC_CHANNEL0); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/cpu/nrf52832/rtimer-arch.h b/cpu/nrf52832/rtimer-arch.h new file mode 100644 index 000000000..da709dae2 --- /dev/null +++ b/cpu/nrf52832/rtimer-arch.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52832 nRF52832 + * @{ + * + * \file + * Architecture dependent rtimer implementation header file. + * \author + * Wojciech Bober + * + */ +/*---------------------------------------------------------------------------*/ +#ifndef RTIMER_ARCH_H_ +#define RTIMER_ARCH_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +/*---------------------------------------------------------------------------*/ +rtimer_clock_t rtimer_arch_now(void); +/*---------------------------------------------------------------------------*/ +#endif /* RTIMER_ARCH_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/cpu/x86/Makefile.x86_common b/cpu/x86/Makefile.x86_common index d6e692e9a..c27626815 100644 --- a/cpu/x86/Makefile.x86_common +++ b/cpu/x86/Makefile.x86_common @@ -3,8 +3,10 @@ CONTIKI_CPU_DIRS += . init/common CONTIKI_SOURCEFILES += gdt.c helpers.S idt.c cpu.c CC = gcc -LD = gcc -AS = as +LD = $(CC) +# Use gcc to invoke the assembler so that the preprocessor will be run on each +# file first, enabling us to use macros within assembly language files: +AS = $(CC) OBJCOPY = objcopy SIZE = size STRIP = strip diff --git a/cpu/x86/Makefile.x86_quarkX1000 b/cpu/x86/Makefile.x86_quarkX1000 index 00f352102..1a8d3ac8e 100644 --- a/cpu/x86/Makefile.x86_quarkX1000 +++ b/cpu/x86/Makefile.x86_quarkX1000 @@ -1,12 +1,72 @@ +# See mm/README.md for a description of available settings: +X86_CONF_PROT_DOMAINS ?= none + include $(CONTIKI)/cpu/x86/Makefile.x86_common -CONTIKI_CPU_DIRS += drivers/legacy_pc drivers/quarkX1000 init/legacy_pc +CONTIKI_CPU_DIRS += drivers/legacy_pc drivers/quarkX1000 init/legacy_pc net mm -CONTIKI_SOURCEFILES += bootstrap_quarkX1000.S rtc.c pit.c pic.c irq.c nmi.c pci.c uart-16x50.c uart.c gpio.c i2c.c eth.c +CONTIKI_SOURCEFILES += bootstrap_quarkX1000.S rtc.c pit.c pic.c irq.c nmi.c pci.c uart-16x50.c uart.c gpio.c i2c.c eth.c shared-isr.c +CONTIKI_SOURCEFILES += imr.c msg-bus.c +CONTIKI_SOURCEFILES += stacks.c + +ifneq ($(X86_CONF_PROT_DOMAINS),none) +CONTIKI_SOURCEFILES += prot-domains.c $(X86_CONF_PROT_DOMAINS)-prot-domains.c imr-conf.c + +ifeq ($(X86_CONF_PROT_DOMAINS),paging) +LINKERSCRIPT_SFX = _paging +X86_CONF_SYSCALLS_INT = 1 +ifeq ($(X86_CONF_USE_INVLPG),1) +CFLAGS += -DX86_CONF_USE_INVLPG +endif +# This matches the definition of X86_CONF_PROT_DOMAINS__PAGING in prot-domains.h: +CFLAGS += -DX86_CONF_PROT_DOMAINS=1 +else ifeq ($(X86_CONF_PROT_DOMAINS),tss) +# This matches the definition of X86_CONF_PROT_DOMAINS__TSS in prot-domains.h: +CFLAGS += -DX86_CONF_PROT_DOMAINS=2 +X86_CONF_MULTI_SEG = 1 +CONTIKI_SOURCEFILES += tss-prot-domains-asm.S +else ifeq ($(X86_CONF_PROT_DOMAINS),swseg) +# This matches the definition of X86_CONF_PROT_DOMAINS__SWSEG in prot-domains.h: +CFLAGS += -DX86_CONF_PROT_DOMAINS=3 +X86_CONF_SYSCALLS_INT = 1 +X86_CONF_MULTI_SEG = 1 +else +$(error Unrecognized setting for X86_CONF_PROT_DOMAINS: \ + $(X86_CONF_PROT_DOMAINS). See cpu/x86/mm/README.md for \ + descriptions of available settings) +endif + +ifeq ($(X86_CONF_SYSCALLS_INT),1) +CONTIKI_SOURCEFILES += syscalls-int-asm.S tss.c +endif + +ifeq ($(X86_CONF_MULTI_SEG),1) +LINKERSCRIPT_SFX = _multi_seg +CONTIKI_SOURCEFILES += multi-segment.c +# Due to the way the multi-segment implementation of protection domains define +# tightly-bounded stack segments, the base pointer register cannot be used as +# a general-purpose register in all circumstances. The stack segment is used +# by default for a data access that uses the base pointer as the base register +# to compute the address. If the data referenced by the base pointer is not +# on the stack, then the access will fail. Thus, it is necessary to disable +# the omit-frame-pointer optimization. See mm/README.md for more details of +# how multi-segment protection domains are implemented. +CFLAGS += -fno-omit-frame-pointer +endif + +endif CFLAGS += -m32 -march=i586 -mtune=i586 -LDFLAGS += -m32 -Xlinker -T -Xlinker $(CONTIKI)/cpu/x86/quarkX1000.ld -ASFLAGS += --32 -march=i586 -mtune=i586 +LDFLAGS += -m32 -Xlinker -T -Xlinker $(CONTIKI)/cpu/x86/quarkX1000$(LINKERSCRIPT_SFX).ld +# The C compiler is used to invoke the assembler, so the CFLAGS should be +# passed to it on the command line: +ASFLAGS = -c $(CFLAGS) + +ifeq ($(X86_CONF_RESTRICT_DMA),1) +CONTIKI_SOURCEFILES += imr-conf.c +CFLAGS += -DX86_CONF_RESTRICT_DMA +LDFLAGS += -Xlinker -T -Xlinker $(CONTIKI)/cpu/x86/quarkX1000_dma.ld +endif ### UEFI support diff --git a/cpu/x86/bootstrap_quarkX1000.S b/cpu/x86/bootstrap_quarkX1000.S index 8def35843..622c9dab8 100644 --- a/cpu/x86/bootstrap_quarkX1000.S +++ b/cpu/x86/bootstrap_quarkX1000.S @@ -28,8 +28,7 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -# Kernel -.set STACK_SIZE, 8192 +#include "stacks.h" # Multiboot .set MAGIC_NUMBER, 0x1BADB002 @@ -42,15 +41,21 @@ .long FLAGS .long CHECKSUM -# Reserve space for the C stack. -.lcomm c_stack, STACK_SIZE - -.section .text +.section .boot_text .global start start: cli - movl $(c_stack + STACK_SIZE), %esp - call main - - /* We're not expected to return from main(). But if we do we halt */ - call halt +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS + /* TSS-based protection domains use a multi-segment model that defines + * tight bounds around stacks. That means that the bottom of the stack + * has an offset of 0, which is the address of the stacks_main symbol. + * The following code computes the physical load address of the top of + * the stack, which is what should be initially used as the stack + * pointer while the flat memory model is in use. + */ + lea _sdata_addr, %eax + lea (stacks_main + STACKS_SIZE_MAIN)(%eax), %esp +#else + mov $(stacks_main + STACKS_SIZE_MAIN), %esp +#endif + call cpu_boot_stage0 diff --git a/cpu/x86/dma.h b/cpu/x86/dma.h new file mode 100644 index 000000000..7a8d991b1 --- /dev/null +++ b/cpu/x86/dma.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_DMA_H_ +#define CPU_X86_DMA_H_ + +#include "prot-domains.h" + +#ifdef X86_CONF_RESTRICT_DMA +#define ATTR_BSS_DMA __attribute__((section(".dma_bss"))) +#else +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE +#define ATTR_BSS_DMA +#else +#define ATTR_BSS_DMA ATTR_BSS_META +#endif +#endif + +extern int _ebss_pre_dma_addr, _sbss_dma_addr, _ebss_dma_addr; + +#endif /* CPU_X86_DMA_H_ */ diff --git a/cpu/x86/drivers/legacy_pc/pci.c b/cpu/x86/drivers/legacy_pc/pci.c index 0507ad231..4584d454c 100644 --- a/cpu/x86/drivers/legacy_pc/pci.c +++ b/cpu/x86/drivers/legacy_pc/pci.c @@ -32,12 +32,15 @@ #include "pci.h" #include "helpers.h" +#include "syscalls.h" /* I/O port for PCI configuration address */ #define PCI_CONFIG_ADDR_PORT 0xCF8 /* I/O port for PCI configuration data */ #define PCI_CONFIG_DATA_PORT 0xCFC +PROT_DOMAINS_ALLOC(dom_client_data_t, root_complex_drv); + /*---------------------------------------------------------------------------*/ /* Initialize PCI configuration register address in preparation for accessing * the specified register. @@ -101,47 +104,43 @@ pci_command_enable(pci_config_addr_t addr, uint32_t flags) * \param agent Interrupt Queue Agent to be used, IRQAGENT[0:3]. * \param pin Interrupt Pin Route to be used, INT[A:D]. * \param pirq PIRQ to be used, PIRQ[A:H]. - * \return Returns 0 on success and a negative number otherwise. */ -int -pci_irq_agent_set_pirq(IRQAGENT agent, INTR_PIN pin, PIRQ pirq) +SYSCALLS_DEFINE_SINGLETON(pci_irq_agent_set_pirq, + root_complex_drv, + IRQAGENT agent, INTR_PIN pin, PIRQ pirq) { - pci_config_addr_t pci; uint16_t value; uint32_t rcba_addr, offset = 0; + rcba_addr = PROT_DOMAINS_MMIO(root_complex_drv); + assert(agent >= IRQAGENT0 && agent <= IRQAGENT3); assert(pin >= INTA && pin <= INTD); assert(pirq >= PIRQA && pirq <= PIRQH); - pci.raw = 0; - pci.bus = 0; - pci.dev = 31; - pci.func = 0; - pci.reg_off = 0xF0; /* Root Complex Base Address Register */ - - /* masked to clear non-address bits. */ - rcba_addr = pci_config_read(pci) & ~0x3FFF; - switch(agent) { case IRQAGENT0: - if (pin != INTA) - return -1; + if(pin != INTA) { + halt(); + } offset = 0x3140; break; case IRQAGENT1: offset = 0x3142; break; case IRQAGENT2: - if (pin != INTA) - return -1; + if(pin != INTA) { + halt(); + } offset = 0x3144; break; case IRQAGENT3: offset = 0x3146; } - value = *(uint16_t*)(rcba_addr + offset); + prot_domains_enable_mmio(); + + MMIO_READW(value, *(uint16_t ATTR_MMIO_ADDR_SPACE *)(rcba_addr + offset)); /* clear interrupt pin route and set corresponding pirq. */ switch(pin) { @@ -162,9 +161,9 @@ pci_irq_agent_set_pirq(IRQAGENT agent, INTR_PIN pin, PIRQ pirq) value |= (pirq << 12); } - *(uint16_t*)(rcba_addr + offset) = value; + MMIO_WRITEW(*(uint16_t ATTR_MMIO_ADDR_SPACE *)(rcba_addr + offset), value); - return 0; + prot_domains_disable_mmio(); } /*---------------------------------------------------------------------------*/ /** @@ -231,13 +230,51 @@ pci_pirq_set_irq(PIRQ pirq, uint8_t irq, uint8_t route_to_legacy) * firmware. * \param c_this Structure that will be initialized to represent the driver. * \param pci_addr PCI base address of device. + * \param mmio_sz Size of MMIO region. * \param meta Base address of optional driver-defined metadata. + * \param meta_sz Size of optional driver-defined metadata. */ void -pci_init(pci_driver_t *c_this, pci_config_addr_t pci_addr, uintptr_t meta) +pci_init(pci_driver_t ATTR_KERN_ADDR_SPACE *c_this, + pci_config_addr_t pci_addr, + size_t mmio_sz, + uintptr_t meta, + size_t meta_sz) { + uintptr_t mmio; + /* The BAR value is masked to clear non-address bits. */ - c_this->mmio = pci_config_read(pci_addr) & ~0xFFF; - c_this->meta = meta; + mmio = pci_config_read(pci_addr) & ~0xFFF; + + prot_domains_reg(c_this, mmio, mmio_sz, meta, meta_sz, false); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize the PCI root complex driver. + */ +void +pci_root_complex_init(void) +{ + uint32_t rcba_addr; + pci_config_addr_t pci = { .raw = 0 }; + pci.dev = 31; + pci.reg_off = 0xF0; /* Root Complex Base Address Register */ + + /* masked to clear non-address bits. */ + rcba_addr = pci_config_read(pci) & ~0x3FFF; + + PROT_DOMAINS_INIT_ID(root_complex_drv); + prot_domains_reg(&root_complex_drv, rcba_addr, 0x4000, 0, 0, false); + SYSCALLS_INIT(pci_irq_agent_set_pirq); + SYSCALLS_AUTHZ(pci_irq_agent_set_pirq, root_complex_drv); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Prevent further invocations of pci_irq_agent_set_pirq. + */ +void +pci_root_complex_lock(void) +{ + SYSCALLS_DEAUTHZ(pci_irq_agent_set_pirq, root_complex_drv); } /*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/drivers/legacy_pc/pci.h b/cpu/x86/drivers/legacy_pc/pci.h index c938f9c6c..666b3c29e 100644 --- a/cpu/x86/drivers/legacy_pc/pci.h +++ b/cpu/x86/drivers/legacy_pc/pci.h @@ -33,6 +33,8 @@ #include #include "helpers.h" +#include +#include "prot-domains.h" /** PCI configuration register identifier for Base Address Registers */ #define PCI_CONFIG_REG_BAR0 0x10 @@ -98,22 +100,25 @@ uint32_t pci_config_read(pci_config_addr_t addr); void pci_config_write(pci_config_addr_t addr, uint32_t data); void pci_command_enable(pci_config_addr_t addr, uint32_t flags); -/** - * PCI device driver instance with an optional single MMIO range and optional - * metadata. - */ -typedef struct pci_driver { - uintptr_t mmio; /**< MMIO range base address */ - uintptr_t meta; /**< Driver-defined metadata base address */ -} pci_driver_t; +typedef dom_client_data_t pci_driver_t; -void pci_init(pci_driver_t *c_this, pci_config_addr_t pci_addr, uintptr_t meta); -int pci_irq_agent_set_pirq(IRQAGENT agent, INTR_PIN pin, PIRQ pirq); +void pci_init(pci_driver_t ATTR_KERN_ADDR_SPACE *c_this, + pci_config_addr_t pci_addr, + size_t mmio_sz, + uintptr_t meta, + size_t meta_sz); +void pci_irq_agent_set_pirq(IRQAGENT agent, INTR_PIN pin, PIRQ pirq); void pci_pirq_set_irq(PIRQ pirq, uint8_t irq, uint8_t route_to_legacy); +void pci_root_complex_init(void); +void pci_root_complex_lock(void); #define PCI_MMIO_READL(c_this, dest, reg_addr) \ - dest = *((volatile uint32_t *)((c_this).mmio + (reg_addr))) + MMIO_READL(dest, \ + *((volatile uint32_t ATTR_MMIO_ADDR_SPACE *) \ + (((uintptr_t)PROT_DOMAINS_MMIO(c_this)) + (reg_addr)))) #define PCI_MMIO_WRITEL(c_this, reg_addr, src) \ - *((volatile uint32_t *)((c_this).mmio + (reg_addr))) = (src) + MMIO_WRITEL(*((volatile uint32_t ATTR_MMIO_ADDR_SPACE *) \ + (((uintptr_t)PROT_DOMAINS_MMIO(c_this)) + (reg_addr))), \ + src) #endif /* CPU_X86_DRIVERS_LEGACY_PC_PCI_H_ */ diff --git a/cpu/x86/drivers/legacy_pc/shared-isr.c b/cpu/x86/drivers/legacy_pc/shared-isr.c new file mode 100644 index 000000000..f04f6aba8 --- /dev/null +++ b/cpu/x86/drivers/legacy_pc/shared-isr.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "idt.h" +#include "interrupt.h" +#include "pic.h" +#include "shared-isr.h" + +/* Defined in linker script */ +extern shared_isr_client_t _sdata_shared_isr, _edata_shared_isr; + +static void __attribute__((used)) +shared_handler(void) +{ + shared_isr_client_t *client; + for(client = &_sdata_shared_isr; client < &_edata_shared_isr; client++) { + if(client->handler()) { + pic_eoi(client->irq); + return; + } + } +} + +/** + * \brief Initialize shared ISR by iterating through all of its clients and + * configuring their interrupts to route to the shared ISR. + */ +void +shared_isr_init(void) +{ + shared_isr_client_t *client = &_sdata_shared_isr; + shared_isr_client_t *consistency_check_client; + bool prev_conf; + + void shared_isr_stub(void); + __asm__ __volatile__ ( + ISR_STUB("shared_isr_stub", 0, "shared_handler", 0) + : + ); + + while(client < &_edata_shared_isr) { + consistency_check_client = &_sdata_shared_isr; + + prev_conf = false; + + while(consistency_check_client < client) { + if((client->irq == consistency_check_client->irq) || + (client->pin == consistency_check_client->pin) || + (client->pirq == consistency_check_client->pirq)) { + + prev_conf = true; + + /* This interrupt was previously configured. */ + break; + } + + consistency_check_client++; + } + + if(prev_conf) { + /* The requested configurations for each IRQ must be consistent. */ + assert((client->irq == consistency_check_client->irq) && + (client->agent == consistency_check_client->agent) && + (client->pin == consistency_check_client->pin) && + (client->pirq == consistency_check_client->pirq)); + } else { + idt_set_intr_gate_desc(PIC_INT(client->irq), (uint32_t)shared_isr_stub, + GDT_SEL_CODE_INT, PRIV_LVL_INT); + + pci_irq_agent_set_pirq(client->agent, client->pin, client->pirq); + + pci_pirq_set_irq(client->pirq, client->irq, 1); + + pic_unmask_irq(client->irq); + } + + client++; + } +} diff --git a/cpu/x86/drivers/legacy_pc/shared-isr.h b/cpu/x86/drivers/legacy_pc/shared-isr.h new file mode 100644 index 000000000..e8a92e442 --- /dev/null +++ b/cpu/x86/drivers/legacy_pc/shared-isr.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_DRIVERS_LEGACY_PC_SHARED_ISR_H_ +#define CPU_X86_DRIVERS_LEGACY_PC_SHARED_ISR_H_ + +#include +#include "pci.h" + +/** + * The handler function should return true if and only if it handled the + * interrupt. + */ +typedef bool (*shared_isr_handler_t)(void); + +typedef struct shared_isr_client { + uint8_t irq; + IRQAGENT agent; + INTR_PIN pin; + PIRQ pirq; + shared_isr_handler_t handler; +} shared_isr_client_t; + +/* Unlike a non-shared interrupt handler function, an individual interrupt + * handler for a shared interrupt must not issue an EOI. The EOI is issued by + * the shared-isr subsystem. + */ +#define DEFINE_SHARED_IRQ(irq_, agent_, pin_, pirq_, handler_) \ +static struct shared_isr_client \ + __attribute__((used, section(".shared_isr_data"))) _shared_irq_##irq_ = { \ + .irq = irq_, \ + .agent = agent_, \ + .pin = pin_, \ + .pirq = pirq_, \ + .handler = handler_ \ +} + +void shared_isr_init(void); + +#endif /* CPU_X86_DRIVERS_LEGACY_PC_SHARED_ISR_H_ */ diff --git a/cpu/x86/drivers/legacy_pc/uart-16x50.c b/cpu/x86/drivers/legacy_pc/uart-16x50.c index 296719faa..d17e61498 100644 --- a/cpu/x86/drivers/legacy_pc/uart-16x50.c +++ b/cpu/x86/drivers/legacy_pc/uart-16x50.c @@ -28,9 +28,12 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "uart-16x50.h" #include #include "helpers.h" +#include "paging.h" +#include "prot-domains.h" +#include "syscalls.h" +#include "uart-16x50.h" /* Refer to Intel Quark SoC X1000 Datasheet, Chapter 18 for more details on * UART operation. @@ -64,41 +67,50 @@ typedef struct uart_16x50_regs { volatile uint32_t mcr, lsr, msr, scr, usr, htx, dmasa; } uart_16x50_regs_t; -/*---------------------------------------------------------------------------*/ -/** - * \brief Initialize an MMIO-programmable 16X50 UART. - * \param c_this Structure that will be initialized to represent the device. - * \param pci_addr PCI address of device. - * \param dl Divisor setting to configure the baud rate. +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING +/* When paging-based protection domains are in use, at least one page of memory + * must be reserved to facilitate access to the MMIO region, since that is the + * smallest unit of memory that can be managed with paging: */ -void -uart_16x50_init(uart_16x50_driver_t *c_this, - pci_config_addr_t pci_addr, - uint16_t dl) -{ - /* This assumes that the UART had an MMIO range assigned to it by the - * firmware during boot. - */ - pci_init(c_this, pci_addr, 0); +#define UART_MMIO_SZ MIN_PAGE_SIZE +#else +/* Multi-segment protection domain implementations can control memory with + * byte granularity. Thus, only the registers defined in the uart_16x50_regs + * structure are included in the MMIO region allocated for this protection + * domain: + */ +#define UART_MMIO_SZ sizeof(uart_16x50_regs_t) +#endif - uart_16x50_regs_t *regs = (uart_16x50_regs_t *)c_this->mmio; +void uart_16x50_setup(uart_16x50_driver_t c_this, uint16_t dl); + +/*---------------------------------------------------------------------------*/ +SYSCALLS_DEFINE(uart_16x50_setup, uart_16x50_driver_t c_this, uint16_t dl) +{ + uart_16x50_regs_t ATTR_MMIO_ADDR_SPACE *regs = + (uart_16x50_regs_t ATTR_MMIO_ADDR_SPACE *)PROT_DOMAINS_MMIO(c_this); + + prot_domains_enable_mmio(); /* Set the DLAB bit to enable access to divisor settings. */ - regs->lcr = UART_LCR_7_DLAB; + MMIO_WRITEL(regs->lcr, UART_LCR_7_DLAB); /* The divisor settings configure the baud rate, and may need to be defined * on a per-device basis. */ - regs->rbr_thr_dll = dl & UINT8_MAX; - regs->ier_dlh = dl >> 8; + MMIO_WRITEL(regs->rbr_thr_dll, dl & UINT8_MAX); + MMIO_WRITEL(regs->ier_dlh, dl >> 8); /* Clear the DLAB bit to enable access to other settings and configure other * UART parameters. */ - regs->lcr = UART_LCR_8BITS; + MMIO_WRITEL(regs->lcr, UART_LCR_8BITS); /* Enable the FIFOs. */ - regs->iir_fcr = UART_FCR_0_FIFOE | UART_FCR_1_RFIFOR | UART_FCR_2_XFIFOR; + MMIO_WRITEL(regs->iir_fcr, + UART_FCR_0_FIFOE | UART_FCR_1_RFIFOR | UART_FCR_2_XFIFOR); + + prot_domains_disable_mmio(); } /*---------------------------------------------------------------------------*/ /** @@ -109,15 +121,49 @@ uart_16x50_init(uart_16x50_driver_t *c_this, * This procedure will block indefinitely until the UART is ready * to accept the character to be transmitted. */ -void -uart_16x50_tx(uart_16x50_driver_t c_this, uint8_t c) +SYSCALLS_DEFINE(uart_16x50_tx, uart_16x50_driver_t c_this, uint8_t c) { - struct uart_16x50_regs *regs = (uart_16x50_regs_t *)c_this.mmio; + uint32_t ready; + uart_16x50_regs_t ATTR_MMIO_ADDR_SPACE *regs = + (uart_16x50_regs_t ATTR_MMIO_ADDR_SPACE *)PROT_DOMAINS_MMIO(c_this); + + prot_domains_enable_mmio(); /* Wait for space in TX FIFO. */ - while((regs->lsr & UART_LSR_5_THRE) == 0); + do { + MMIO_READL(ready, regs->lsr); + } while((ready & UART_LSR_5_THRE) == 0); /* Add character to TX FIFO. */ - regs->rbr_thr_dll = c; + MMIO_WRITEL(regs->rbr_thr_dll, c); + + prot_domains_disable_mmio(); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize an MMIO-programmable 16X50 UART. + * \param c_this Structure that will be initialized to represent the device. + * \param pci_addr PCI address of device. + * \param dl Divisor setting to configure the baud rate. + */ +void +uart_16x50_init(uart_16x50_driver_t ATTR_KERN_ADDR_SPACE *c_this, + pci_config_addr_t pci_addr, + uint16_t dl) +{ + uart_16x50_driver_t loc_c_this; + + /* This assumes that the UART had an MMIO range assigned to it by the + * firmware during boot. + */ + pci_init(c_this, pci_addr, UART_MMIO_SZ, 0, 0); + SYSCALLS_INIT(uart_16x50_setup); + SYSCALLS_AUTHZ(uart_16x50_setup, *c_this); + SYSCALLS_INIT(uart_16x50_tx); + SYSCALLS_AUTHZ(uart_16x50_tx, *c_this); + + prot_domains_copy_dcd(&loc_c_this, c_this); + + uart_16x50_setup(loc_c_this, dl); } /*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/drivers/legacy_pc/uart-16x50.h b/cpu/x86/drivers/legacy_pc/uart-16x50.h index 615806518..4a038b948 100644 --- a/cpu/x86/drivers/legacy_pc/uart-16x50.h +++ b/cpu/x86/drivers/legacy_pc/uart-16x50.h @@ -35,7 +35,7 @@ typedef pci_driver_t uart_16x50_driver_t; -void uart_16x50_init(uart_16x50_driver_t *c_this, +void uart_16x50_init(uart_16x50_driver_t ATTR_KERN_ADDR_SPACE *c_this, pci_config_addr_t pci_addr, uint16_t dl); diff --git a/cpu/x86/drivers/quarkX1000/eth.c b/cpu/x86/drivers/quarkX1000/eth.c index 2f02213ea..88782ebc2 100644 --- a/cpu/x86/drivers/quarkX1000/eth.c +++ b/cpu/x86/drivers/quarkX1000/eth.c @@ -32,8 +32,10 @@ #include #include #include "contiki-net.h" +#include "dma.h" #include "eth.h" #include "helpers.h" +#include "syscalls.h" #include "net/ip/uip.h" #include "pci.h" @@ -157,12 +159,29 @@ typedef struct quarkX1000_eth_meta { /* Transmit descriptor */ volatile quarkX1000_eth_tx_desc_t tx_desc; /* Transmit DMA packet buffer */ - volatile uint8_t tx_buf[UIP_BUFSIZE]; + volatile uint8_t tx_buf[ALIGN(UIP_BUFSIZE, 4)]; /* Receive descriptor */ volatile quarkX1000_eth_rx_desc_t rx_desc; /* Receive DMA packet buffer */ - volatile uint8_t rx_buf[UIP_BUFSIZE]; -} quarkX1000_eth_meta_t; + volatile uint8_t rx_buf[ALIGN(UIP_BUFSIZE, 4)]; + +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING + /* Domain-defined metadata must fill an even number of pages, since that is + * the minimum granularity of access control supported by paging. However, + * using the "aligned(4096)" attribute causes the alignment of the kernel + * data section to increase, which causes problems when generating UEFI + * binaries, as is described in the linker script. Thus, it is necessary + * to manually pad the structure to fill a page. This only works if the + * sizes of the actual fields of the structure are collectively less than a + * page. + */ + uint8_t pad[MIN_PAGE_SIZE - + (sizeof(quarkX1000_eth_tx_desc_t) + + ALIGN(UIP_BUFSIZE, 4) + + sizeof(quarkX1000_eth_rx_desc_t) + + ALIGN(UIP_BUFSIZE, 4))]; +#endif +} __attribute__((packed)) quarkX1000_eth_meta_t; #define LOG_PFX "quarkX1000_eth: " @@ -187,42 +206,29 @@ typedef struct quarkX1000_eth_meta { #define REG_ADDR_TX_DESC_LIST 0x1010 #define REG_ADDR_DMA_OPERATION 0x1018 -static quarkX1000_eth_driver_t drv; -static quarkX1000_eth_meta_t meta; +PROT_DOMAINS_ALLOC(quarkX1000_eth_driver_t, drv); +static quarkX1000_eth_meta_t ATTR_BSS_DMA meta; + +void quarkX1000_eth_setup(uintptr_t meta_phys_base); /*---------------------------------------------------------------------------*/ -/** - * \brief Initialize the first Quark X1000 Ethernet MAC. - * - * This procedure assumes that an MMIO range for the device was - * previously assigned, e.g. by firmware. - */ -void -quarkX1000_eth_init(void) +SYSCALLS_DEFINE_SINGLETON(quarkX1000_eth_setup, drv, uintptr_t meta_phys_base) { - pci_config_addr_t pci_addr = { .raw = 0 }; uip_eth_addr mac_addr; uint32_t mac_tmp1, mac_tmp2; + quarkX1000_eth_rx_desc_t rx_desc; + quarkX1000_eth_tx_desc_t tx_desc; + quarkX1000_eth_meta_t ATTR_META_ADDR_SPACE *loc_meta = + (quarkX1000_eth_meta_t ATTR_META_ADDR_SPACE *)PROT_DOMAINS_META(drv); - /* PCI address from section 15.4 of Intel Quark SoC X1000 Datasheet. */ - - pci_addr.dev = 20; - pci_addr.func = 6; - - /* Activate MMIO and DMA access. */ - pci_command_enable(pci_addr, PCI_CMD_2_BUS_MST_EN | PCI_CMD_1_MEM_SPACE_EN); - - printf(LOG_PFX "Activated MMIO and DMA access.\n"); - - pci_addr.reg_off = PCI_CONFIG_REG_BAR0; - - /* Configure the device MMIO range and initialize the driver structure. */ - pci_init(&drv, pci_addr, (uintptr_t)&meta); + prot_domains_enable_mmio(); /* Read the MAC address from the device. */ PCI_MMIO_READL(drv, mac_tmp1, REG_ADDR_MACADDR_HI); PCI_MMIO_READL(drv, mac_tmp2, REG_ADDR_MACADDR_LO); + prot_domains_disable_mmio(); + /* Convert the data read from the device into the format expected by * Contiki. */ @@ -245,29 +251,47 @@ quarkX1000_eth_init(void) uip_setethaddr(mac_addr); /* Initialize transmit descriptor. */ - meta.tx_desc.tdes0 = 0; - meta.tx_desc.tdes1 = 0; + tx_desc.tdes0 = 0; + tx_desc.tdes1 = 0; - meta.tx_desc.buf1_ptr = (uint8_t *)meta.tx_buf; - meta.tx_desc.tx_end_of_ring = 1; - meta.tx_desc.first_seg_in_frm = 1; - meta.tx_desc.last_seg_in_frm = 1; - meta.tx_desc.tx_end_of_ring = 1; + tx_desc.tx_end_of_ring = 1; + tx_desc.first_seg_in_frm = 1; + tx_desc.last_seg_in_frm = 1; + tx_desc.tx_end_of_ring = 1; + + META_WRITEL(loc_meta->tx_desc.tdes0, tx_desc.tdes0); + META_WRITEL(loc_meta->tx_desc.tdes1, tx_desc.tdes1); + META_WRITEL(loc_meta->tx_desc.buf1_ptr, + (uint8_t *)PROT_DOMAINS_META_OFF_TO_PHYS( + (uintptr_t)&loc_meta->tx_buf, meta_phys_base)); + META_WRITEL(loc_meta->tx_desc.buf2_ptr, 0); /* Initialize receive descriptor. */ - meta.rx_desc.rdes0 = 0; - meta.rx_desc.rdes1 = 0; + rx_desc.rdes0 = 0; + rx_desc.rdes1 = 0; - meta.rx_desc.buf1_ptr = (uint8_t *)meta.rx_buf; - meta.rx_desc.own = 1; - meta.rx_desc.first_desc = 1; - meta.rx_desc.last_desc = 1; - meta.rx_desc.rx_buf1_sz = UIP_BUFSIZE; - meta.rx_desc.rx_end_of_ring = 1; + rx_desc.own = 1; + rx_desc.first_desc = 1; + rx_desc.last_desc = 1; + rx_desc.rx_buf1_sz = UIP_BUFSIZE; + rx_desc.rx_end_of_ring = 1; + + META_WRITEL(loc_meta->rx_desc.rdes0, rx_desc.rdes0); + META_WRITEL(loc_meta->rx_desc.rdes1, rx_desc.rdes1); + META_WRITEL(loc_meta->rx_desc.buf1_ptr, + (uint8_t *)PROT_DOMAINS_META_OFF_TO_PHYS( + (uintptr_t)&loc_meta->rx_buf, meta_phys_base)); + META_WRITEL(loc_meta->rx_desc.buf2_ptr, 0); + + prot_domains_enable_mmio(); /* Install transmit and receive descriptors. */ - PCI_MMIO_WRITEL(drv, REG_ADDR_RX_DESC_LIST, (uint32_t)&meta.rx_desc); - PCI_MMIO_WRITEL(drv, REG_ADDR_TX_DESC_LIST, (uint32_t)&meta.tx_desc); + PCI_MMIO_WRITEL(drv, REG_ADDR_RX_DESC_LIST, + PROT_DOMAINS_META_OFF_TO_PHYS( + (uintptr_t)&loc_meta->rx_desc, meta_phys_base)); + PCI_MMIO_WRITEL(drv, REG_ADDR_TX_DESC_LIST, + PROT_DOMAINS_META_OFF_TO_PHYS( + (uintptr_t)&loc_meta->tx_desc, meta_phys_base)); PCI_MMIO_WRITEL(drv, REG_ADDR_MAC_CONF, /* Set the RMII speed to 100Mbps */ @@ -290,8 +314,11 @@ quarkX1000_eth_init(void) /* Place the receiver state machine in the Running state. */ OP_MODE_1_START_RX); + prot_domains_disable_mmio(); + printf(LOG_PFX "Enabled 100M full-duplex mode.\n"); } + /*---------------------------------------------------------------------------*/ /** * \brief Poll for a received Ethernet frame. @@ -301,36 +328,50 @@ quarkX1000_eth_init(void) * If a frame is received, this procedure copies it into the * global uip_buf buffer. */ -void -quarkX1000_eth_poll(uint16_t *frame_len) +SYSCALLS_DEFINE_SINGLETON(quarkX1000_eth_poll, drv, uint16_t * frame_len) { + uint16_t *loc_frame_len; uint16_t frm_len = 0; + quarkX1000_eth_rx_desc_t tmp_desc; + quarkX1000_eth_meta_t ATTR_META_ADDR_SPACE *loc_meta = + (quarkX1000_eth_meta_t ATTR_META_ADDR_SPACE *)PROT_DOMAINS_META(drv); + + PROT_DOMAINS_VALIDATE_PTR(loc_frame_len, frame_len, sizeof(*frame_len)); + + META_READL(tmp_desc.rdes0, loc_meta->rx_desc.rdes0); /* Check whether the RX descriptor is still owned by the device. If not, * process the received frame or an error that may have occurred. */ - if(meta.rx_desc.own == 0) { - if(meta.rx_desc.err_summary) { + if(tmp_desc.own == 0) { + META_READL(tmp_desc.rdes1, loc_meta->rx_desc.rdes1); + if(tmp_desc.err_summary) { fprintf(stderr, LOG_PFX "Error receiving frame: RDES0 = %08x, RDES1 = %08x.\n", - meta.rx_desc.rdes0, meta.rx_desc.rdes1); + tmp_desc.rdes0, tmp_desc.rdes1); assert(0); } - frm_len = meta.rx_desc.frm_len; + frm_len = tmp_desc.frm_len; assert(frm_len <= UIP_BUFSIZE); - memcpy(uip_buf, (void *)meta.rx_buf, frm_len); + MEMCPY_FROM_META(uip_buf, loc_meta->rx_buf, frm_len); /* Return ownership of the RX descriptor to the device. */ - meta.rx_desc.own = 1; + tmp_desc.own = 1; + + META_WRITEL(loc_meta->rx_desc.rdes0, tmp_desc.rdes0); + + prot_domains_enable_mmio(); /* Request that the device check for an available RX descriptor, since * ownership of the descriptor was just transferred to the device. */ PCI_MMIO_WRITEL(drv, REG_ADDR_RX_POLL_DEMAND, 1); + + prot_domains_disable_mmio(); } - *frame_len = frm_len; + *loc_frame_len = frm_len; } /*---------------------------------------------------------------------------*/ /** @@ -342,31 +383,83 @@ quarkX1000_eth_poll(uint16_t *frame_len) * buffer and signals to the device that a new frame is available to be * transmitted. */ -void -quarkX1000_eth_send(void) +SYSCALLS_DEFINE_SINGLETON(quarkX1000_eth_send, drv) { + quarkX1000_eth_tx_desc_t tmp_desc; + quarkX1000_eth_meta_t ATTR_META_ADDR_SPACE *loc_meta = + (quarkX1000_eth_meta_t ATTR_META_ADDR_SPACE *)PROT_DOMAINS_META(drv); + /* Wait until the TX descriptor is no longer owned by the device. */ - while(meta.tx_desc.own == 1); + do { + META_READL(tmp_desc.tdes0, loc_meta->tx_desc.tdes0); + } while(tmp_desc.own == 1); + + META_READL(tmp_desc.tdes1, loc_meta->tx_desc.tdes1); /* Check whether an error occurred transmitting the previous frame. */ - if(meta.tx_desc.err_summary) { + if(tmp_desc.err_summary) { fprintf(stderr, LOG_PFX "Error transmitting frame: TDES0 = %08x, TDES1 = %08x.\n", - meta.tx_desc.tdes0, meta.tx_desc.tdes1); + tmp_desc.tdes0, tmp_desc.tdes1); assert(0); } /* Transmit the next frame. */ assert(uip_len <= UIP_BUFSIZE); - memcpy((void *)meta.tx_buf, uip_buf, uip_len); + MEMCPY_TO_META(loc_meta->tx_buf, uip_buf, uip_len); - meta.tx_desc.tx_buf1_sz = uip_len; + tmp_desc.tx_buf1_sz = uip_len; - meta.tx_desc.own = 1; + META_WRITEL(loc_meta->tx_desc.tdes1, tmp_desc.tdes1); + + tmp_desc.own = 1; + + META_WRITEL(loc_meta->tx_desc.tdes0, tmp_desc.tdes0); + + prot_domains_enable_mmio(); /* Request that the device check for an available TX descriptor, since * ownership of the descriptor was just transferred to the device. */ PCI_MMIO_WRITEL(drv, REG_ADDR_TX_POLL_DEMAND, 1); + + prot_domains_disable_mmio(); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize the first Quark X1000 Ethernet MAC. + * + * This procedure assumes that an MMIO range for the device was + * previously assigned, e.g. by firmware. + */ +void +quarkX1000_eth_init(void) +{ + pci_config_addr_t pci_addr = { .raw = 0 }; + + /* PCI address from section 15.4 of Intel Quark SoC X1000 Datasheet. */ + + pci_addr.dev = 20; + pci_addr.func = 6; + + /* Activate MMIO and DMA access. */ + pci_command_enable(pci_addr, PCI_CMD_2_BUS_MST_EN | PCI_CMD_1_MEM_SPACE_EN); + + printf(LOG_PFX "Activated MMIO and DMA access.\n"); + + pci_addr.reg_off = PCI_CONFIG_REG_BAR0; + + PROT_DOMAINS_INIT_ID(drv); + /* Configure the device MMIO range and initialize the driver structure. */ + pci_init(&drv, pci_addr, MMIO_SZ, + (uintptr_t)&meta, sizeof(quarkX1000_eth_meta_t)); + SYSCALLS_INIT(quarkX1000_eth_setup); + SYSCALLS_AUTHZ(quarkX1000_eth_setup, drv); + SYSCALLS_INIT(quarkX1000_eth_poll); + SYSCALLS_AUTHZ(quarkX1000_eth_poll, drv); + SYSCALLS_INIT(quarkX1000_eth_send); + SYSCALLS_AUTHZ(quarkX1000_eth_send, drv); + + quarkX1000_eth_setup(prot_domains_lookup_meta_phys_base(&drv)); } /*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/drivers/quarkX1000/gpio.c b/cpu/x86/drivers/quarkX1000/gpio.c index 92438b456..ba825c090 100644 --- a/cpu/x86/drivers/quarkX1000/gpio.c +++ b/cpu/x86/drivers/quarkX1000/gpio.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,9 +29,12 @@ */ #include "gpio.h" + +#include #include "helpers.h" -#include "interrupt.h" -#include "pic.h" +#include "paging.h" +#include "shared-isr.h" +#include "syscalls.h" /* GPIO Controler Registers */ #define SWPORTA_DR 0x00 @@ -49,28 +52,65 @@ #define PINS 8 -#define GPIO_IRQ 10 -#define GPIO_INT PIC_INT(GPIO_IRQ) +#define GPIO_IRQ 9 + +#define HIGHEST_REG LS_SYNC + +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING +#define MMIO_SZ MIN_PAGE_SIZE +#else +#define MMIO_SZ (HIGHEST_REG + 4) +#endif + +PROT_DOMAINS_ALLOC(pci_driver_t, drv); struct gpio_internal_data { - pci_driver_t pci; quarkX1000_gpio_callback callback; }; static struct gpio_internal_data data; +void quarkX1000_gpio_mmin(uint32_t offset, uint32_t *res); +SYSCALLS_DEFINE_SINGLETON(quarkX1000_gpio_mmin, drv, + uint32_t offset, uint32_t *res) +{ + uint32_t *loc_res; + + PROT_DOMAINS_VALIDATE_PTR(loc_res, res, sizeof(*res)); + if(HIGHEST_REG < offset) { + halt(); + } + + prot_domains_enable_mmio(); + PCI_MMIO_READL(drv, *loc_res, offset); + prot_domains_disable_mmio(); +} + static inline uint32_t read(uint32_t offset) { uint32_t res; - PCI_MMIO_READL(data.pci, res, offset); + quarkX1000_gpio_mmin(offset, &res); return res; } +void quarkX1000_gpio_mmout(uint32_t offset, uint32_t val); +SYSCALLS_DEFINE_SINGLETON(quarkX1000_gpio_mmout, drv, + uint32_t offset, uint32_t val) +{ + if(HIGHEST_REG < offset) { + halt(); + } + + prot_domains_enable_mmio(); + PCI_MMIO_WRITEL(drv, offset, val); + prot_domains_disable_mmio(); +} + static inline void write(uint32_t offset, uint32_t val) { - PCI_MMIO_WRITEL(data.pci, offset, val); + quarkX1000_gpio_mmout(offset, val); } /* value must be 0x0 or 0x1 */ @@ -87,17 +127,23 @@ set_bit(uint32_t offset, uint32_t bit, uint32_t value) write(offset, reg); } -static void +static bool gpio_isr(void) { uint32_t int_status; int_status = read(INTSTATUS); + if(int_status == 0) { + return false; + } + if (data.callback) data.callback(int_status); write(PORTA_EOI, -1); + + return true; } static void @@ -211,13 +257,7 @@ quarkX1000_gpio_clock_disable(void) set_bit(LS_SYNC, 0, 0); } -static void -gpio_handler(void) -{ - gpio_isr(); - - pic_eoi(GPIO_IRQ); -} +DEFINE_SHARED_IRQ(GPIO_IRQ, IRQAGENT3, INTC, PIRQC, gpio_isr); int quarkX1000_gpio_init(void) @@ -232,14 +272,12 @@ quarkX1000_gpio_init(void) pci_command_enable(pci_addr, PCI_CMD_1_MEM_SPACE_EN); - SET_INTERRUPT_HANDLER(GPIO_INT, 0, gpio_handler); - - if (pci_irq_agent_set_pirq(IRQAGENT3, INTA, PIRQC) < 0) - return -1; - - pci_pirq_set_irq(PIRQC, GPIO_IRQ, 1); - - pci_init(&data.pci, pci_addr, 0); + PROT_DOMAINS_INIT_ID(drv); + pci_init(&drv, pci_addr, MMIO_SZ, 0, 0); + SYSCALLS_INIT(quarkX1000_gpio_mmin); + SYSCALLS_AUTHZ(quarkX1000_gpio_mmin, drv); + SYSCALLS_INIT(quarkX1000_gpio_mmout); + SYSCALLS_AUTHZ(quarkX1000_gpio_mmout, drv); data.callback = 0; @@ -250,7 +288,5 @@ quarkX1000_gpio_init(void) write(INTMASK, 0); write(PORTA_EOI, 0); - pic_unmask_irq(GPIO_IRQ); - return 0; } diff --git a/cpu/x86/drivers/quarkX1000/i2c-registers.h b/cpu/x86/drivers/quarkX1000/i2c-registers.h index 7b9e4cec0..3ff7746ec 100644 --- a/cpu/x86/drivers/quarkX1000/i2c-registers.h +++ b/cpu/x86/drivers/quarkX1000/i2c-registers.h @@ -61,6 +61,8 @@ #define QUARKX1000_IC_ENABLE_STATUS 0x9C #define QUARKX1000_IC_FS_SPKLEN 0xA0 +#define QUARKX1000_IC_HIGHEST QUARKX1000_IC_FS_SPKLEN + /* IC_CON */ #define QUARKX1000_IC_CON_MASTER_MODE_SHIFT 0 #define QUARKX1000_IC_CON_MASTER_MODE_MASK 0x01 diff --git a/cpu/x86/drivers/quarkX1000/i2c.c b/cpu/x86/drivers/quarkX1000/i2c.c index b781bcc35..9e233e89c 100644 --- a/cpu/x86/drivers/quarkX1000/i2c.c +++ b/cpu/x86/drivers/quarkX1000/i2c.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -30,9 +30,11 @@ #include "contiki.h" #include "i2c.h" + #include "i2c-registers.h" -#include "interrupt.h" -#include "pic.h" +#include "paging.h" +#include "shared-isr.h" +#include "syscalls.h" #define I2C_CLOCK_SPEED 25 /* kHz */ #define I2C_FIFO_DEPTH 16 @@ -48,18 +50,32 @@ #define I2C_POLLING_TIMEOUT (CLOCK_SECOND / 10) #define I2C_IRQ 9 -#define I2C_INT PIC_INT(I2C_IRQ) + +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING +#define MMIO_SZ MIN_PAGE_SIZE +#else +#define MMIO_SZ (QUARKX1000_IC_HIGHEST + 4) +#endif typedef enum { I2C_DIRECTION_READ, I2C_DIRECTION_WRITE } I2C_DIRECTION; +PROT_DOMAINS_ALLOC(pci_driver_t, drv); + +struct quarkX1000_i2c_config { + QUARKX1000_I2C_SPEED speed; + QUARKX1000_I2C_ADDR_MODE addressing_mode; + + quarkX1000_i2c_callback cb_rx; + quarkX1000_i2c_callback cb_tx; + quarkX1000_i2c_callback cb_err; +}; + struct i2c_internal_data { struct quarkX1000_i2c_config config; - pci_driver_t pci; - I2C_DIRECTION direction; uint8_t rx_len; @@ -74,18 +90,50 @@ struct i2c_internal_data { static struct i2c_internal_data device; -static uint32_t +static int inited = 0; + +void quarkX1000_i2c_mmin(uint32_t offset, uint32_t *res); +SYSCALLS_DEFINE_SINGLETON(quarkX1000_i2c_mmin, drv, + uint32_t offset, uint32_t *res) +{ + uint32_t *loc_res; + + PROT_DOMAINS_VALIDATE_PTR(loc_res, res, sizeof(*res)); + if(QUARKX1000_IC_HIGHEST < offset) { + halt(); + } + + prot_domains_enable_mmio(); + PCI_MMIO_READL(drv, *loc_res, offset); + prot_domains_disable_mmio(); +} + +static inline uint32_t read(uint32_t offset) { uint32_t res; - PCI_MMIO_READL(device.pci, res, offset); + quarkX1000_i2c_mmin(offset, &res); + return res; } -static void +void quarkX1000_i2c_mmout(uint32_t offset, uint32_t val); +SYSCALLS_DEFINE_SINGLETON(quarkX1000_i2c_mmout, drv, + uint32_t offset, uint32_t val) +{ + if(QUARKX1000_IC_HIGHEST < offset) { + halt(); + } + + prot_domains_enable_mmio(); + PCI_MMIO_WRITEL(drv, offset, val); + prot_domains_disable_mmio(); +} + +static inline void write(uint32_t offset, uint32_t val) { - PCI_MMIO_WRITEL(device.pci, offset, val); + quarkX1000_i2c_mmout(offset, val); } static uint32_t @@ -169,9 +217,11 @@ i2c_data_send(void) device.tx_buffer += i; } -static void +static bool i2c_isr(void) { + bool handled = false; + if (read(QUARKX1000_IC_INTR_STAT) & QUARKX1000_IC_INTR_STAT_STOP_DET_MASK) { i2c_data_read(); @@ -185,6 +235,8 @@ i2c_isr(void) if (device.config.cb_rx) device.config.cb_rx(); } + + handled = true; } if (read(QUARKX1000_IC_INTR_STAT) & QUARKX1000_IC_INTR_STAT_TX_EMPTY_MASK) { @@ -195,11 +247,16 @@ i2c_isr(void) set_value(QUARKX1000_IC_INTR_MASK, QUARKX1000_IC_INTR_STAT_STOP_DET_MASK, QUARKX1000_IC_INTR_STAT_STOP_DET_SHIFT, 1); } + + handled = true; } - if (read(QUARKX1000_IC_INTR_STAT) & QUARKX1000_IC_INTR_STAT_RX_FULL_MASK) + if(read(QUARKX1000_IC_INTR_STAT) & QUARKX1000_IC_INTR_STAT_RX_FULL_MASK) { i2c_data_read(); + handled = true; + } + if (read(QUARKX1000_IC_INTR_STAT) & (QUARKX1000_IC_INTR_STAT_TX_ABRT_MASK | QUARKX1000_IC_INTR_STAT_TX_OVER_MASK | QUARKX1000_IC_INTR_STAT_RX_OVER_MASK | QUARKX1000_IC_INTR_STAT_RX_UNDER_MASK)) { @@ -208,20 +265,22 @@ i2c_isr(void) if (device.config.cb_err) device.config.cb_err(); + + handled = true; } + + return handled; } -int -quarkX1000_i2c_configure(struct quarkX1000_i2c_config *config) +void +quarkX1000_i2c_configure(QUARKX1000_I2C_SPEED speed, + QUARKX1000_I2C_ADDR_MODE addressing_mode) { uint32_t hcnt, lcnt; uint8_t ic_fs_spklen; - device.config.speed = config->speed; - device.config.addressing_mode = config->addressing_mode; - device.config.cb_rx = config->cb_rx; - device.config.cb_tx = config->cb_tx; - device.config.cb_err = config->cb_err; + device.config.speed = speed; + device.config.addressing_mode = addressing_mode; if (device.config.speed == QUARKX1000_I2C_SPEED_STANDARD) { lcnt = I2C_STD_LCNT; @@ -240,8 +299,16 @@ quarkX1000_i2c_configure(struct quarkX1000_i2c_config *config) /* Clear interrupts. */ read(QUARKX1000_IC_CLR_INTR); +} - return 0; +void +quarkX1000_i2c_set_callbacks(quarkX1000_i2c_callback rx, + quarkX1000_i2c_callback tx, + quarkX1000_i2c_callback err) +{ + device.config.cb_rx = rx; + device.config.cb_tx = tx; + device.config.cb_err = err; } static int @@ -477,16 +544,10 @@ quarkX1000_i2c_polling_read(uint8_t *buf, uint8_t len, uint16_t addr) int quarkX1000_i2c_is_available(void) { - return device.pci.mmio ? 1 : 0; + return inited; } -static void -i2c_handler() -{ - i2c_isr(); - - pic_eoi(I2C_IRQ); -} +DEFINE_SHARED_IRQ(I2C_IRQ, IRQAGENT3, INTC, PIRQC, i2c_isr); int quarkX1000_i2c_init(void) @@ -501,16 +562,14 @@ quarkX1000_i2c_init(void) pci_command_enable(pci_addr, PCI_CMD_1_MEM_SPACE_EN); - SET_INTERRUPT_HANDLER(I2C_INT, 0, i2c_handler); + PROT_DOMAINS_INIT_ID(drv); + pci_init(&drv, pci_addr, MMIO_SZ, 0, 0); + SYSCALLS_INIT(quarkX1000_i2c_mmin); + SYSCALLS_AUTHZ(quarkX1000_i2c_mmin, drv); + SYSCALLS_INIT(quarkX1000_i2c_mmout); + SYSCALLS_AUTHZ(quarkX1000_i2c_mmout, drv); - if (pci_irq_agent_set_pirq(IRQAGENT3, INTC, PIRQC) < 0) - return -1; - - pci_pirq_set_irq(PIRQC, I2C_IRQ, 1); - - pci_init(&device.pci, pci_addr, 0); - - pic_unmask_irq(I2C_IRQ); + inited = 1; return 0; } diff --git a/cpu/x86/drivers/quarkX1000/i2c.h b/cpu/x86/drivers/quarkX1000/i2c.h index b5292524f..ed2db18fb 100644 --- a/cpu/x86/drivers/quarkX1000/i2c.h +++ b/cpu/x86/drivers/quarkX1000/i2c.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -45,17 +45,12 @@ typedef enum { typedef void (*quarkX1000_i2c_callback)(void); -struct quarkX1000_i2c_config { - QUARKX1000_I2C_SPEED speed; - QUARKX1000_I2C_ADDR_MODE addressing_mode; - - quarkX1000_i2c_callback cb_rx; - quarkX1000_i2c_callback cb_tx; - quarkX1000_i2c_callback cb_err; -}; - int quarkX1000_i2c_init(void); -int quarkX1000_i2c_configure(struct quarkX1000_i2c_config *config); +void quarkX1000_i2c_configure(QUARKX1000_I2C_SPEED speed, + QUARKX1000_I2C_ADDR_MODE addressing_mode); +void quarkX1000_i2c_set_callbacks(quarkX1000_i2c_callback rx, + quarkX1000_i2c_callback tx, + quarkX1000_i2c_callback err); int quarkX1000_i2c_is_available(void); int quarkX1000_i2c_read(uint8_t *buf, uint8_t len, uint16_t addr); diff --git a/cpu/x86/drivers/quarkX1000/imr-conf.c b/cpu/x86/drivers/quarkX1000/imr-conf.c new file mode 100644 index 000000000..8c5b6703a --- /dev/null +++ b/cpu/x86/drivers/quarkX1000/imr-conf.c @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "dma.h" +#include "imr.h" +#include "msg-bus.h" + +/*---------------------------------------------------------------------------*/ +void +quarkX1000_imr_conf(void) +{ + quarkX1000_imr_t imr; + int imr_idx = 0; + + imr.lo.raw = 0; + imr.hi.raw = 0; + imr.rdmsk.raw = 0; + imr.wrmsk.raw = 0; + + imr.lo.lock = 1; + + imr.rdmsk.cpu0 = imr.rdmsk.cpu_0 = 1; + imr.wrmsk.cpu0 = imr.wrmsk.cpu_0 = 1; + + quarkX1000_msg_bus_init(); + + imr.lo.addr = 0; + imr.hi.addr = (((uint32_t)&_sbss_dma_addr) - 1) >> QUARKX1000_IMR_SHAMT; + quarkX1000_imr_write(imr_idx, imr); + imr_idx++; + + imr.lo.addr = ((uint32_t)&_ebss_dma_addr) >> QUARKX1000_IMR_SHAMT; + imr.hi.addr = ~0; + quarkX1000_imr_write(imr_idx, imr); + imr_idx++; + + imr.lo.addr = 0; + imr.hi.addr = 0; + imr.rdmsk.raw = ~0; + imr.wrmsk.raw = ~0; + + /* Lock the other IMRs open */ + while(imr_idx < QUARKX1000_IMR_CNT) { + quarkX1000_imr_write(imr_idx, imr); + imr_idx++; + } + +#ifndef DBG_IMRS + /* The IMRs are locked by the hardware, but the message bus could still + * provide access to other potentially-sensitive functionality. + */ + quarkX1000_msg_bus_lock(); +#endif +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/drivers/quarkX1000/imr-conf.h b/cpu/x86/drivers/quarkX1000/imr-conf.h new file mode 100644 index 000000000..a81888c29 --- /dev/null +++ b/cpu/x86/drivers/quarkX1000/imr-conf.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_DRIVERS_QUARKX1000_IMR_CONF_H_ +#define CPU_X86_DRIVERS_QUARKX1000_IMR_CONF_H_ + +void quarkX1000_imr_conf(void); + +#endif /* CPU_X86_DRIVERS_QUARKX1000_IMR_CONF_H_ */ diff --git a/cpu/x86/drivers/quarkX1000/imr.c b/cpu/x86/drivers/quarkX1000/imr.c new file mode 100644 index 000000000..03c43a0c0 --- /dev/null +++ b/cpu/x86/drivers/quarkX1000/imr.c @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "imr.h" +#include "msg-bus.h" + +#define MEM_MANAGER_PORT 5 + +#define IMR_BASE_OFFSET 0x40 +#define IMR_REG_COUNT 4 + +#define IMR_LO_OFFSET 0 +#define IMR_HI_OFFSET 1 +#define IMR_RDMSK_OFFSET 2 +#define IMR_WRMSK_OFFSET 3 + +/*---------------------------------------------------------------------------*/ +/** + * \brief Read the contents of the specified IMR. + */ +quarkX1000_imr_t +quarkX1000_imr_read(uint32_t imr_idx) +{ + quarkX1000_imr_t imr; + uint32_t reg_base = IMR_BASE_OFFSET + (IMR_REG_COUNT * imr_idx); + + assert(imr_idx < QUARKX1000_IMR_CNT); + + quarkX1000_msg_bus_read(MEM_MANAGER_PORT, + reg_base + IMR_LO_OFFSET, &imr.lo.raw); + quarkX1000_msg_bus_read(MEM_MANAGER_PORT, + reg_base + IMR_HI_OFFSET, &imr.hi.raw); + quarkX1000_msg_bus_read(MEM_MANAGER_PORT, + reg_base + IMR_RDMSK_OFFSET, &imr.rdmsk.raw); + quarkX1000_msg_bus_read(MEM_MANAGER_PORT, + reg_base + IMR_WRMSK_OFFSET, &imr.wrmsk.raw); + + return imr; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Overwrite the contents of the specified IMR. + */ +void +quarkX1000_imr_write(uint32_t imr_idx, quarkX1000_imr_t imr) +{ + uint32_t reg_base = IMR_BASE_OFFSET + (IMR_REG_COUNT * imr_idx); + + assert(imr_idx < QUARKX1000_IMR_CNT); + + quarkX1000_msg_bus_write(MEM_MANAGER_PORT, + reg_base + IMR_HI_OFFSET, imr.hi.raw); + quarkX1000_msg_bus_write(MEM_MANAGER_PORT, + reg_base + IMR_RDMSK_OFFSET, imr.rdmsk.raw); + quarkX1000_msg_bus_write(MEM_MANAGER_PORT, + reg_base + IMR_WRMSK_OFFSET, imr.wrmsk.raw); + /* This register must be programmed last, in case it sets the lock bit. */ + quarkX1000_msg_bus_write(MEM_MANAGER_PORT, + reg_base + IMR_LO_OFFSET, imr.lo.raw); +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/drivers/quarkX1000/imr.h b/cpu/x86/drivers/quarkX1000/imr.h new file mode 100644 index 000000000..f5ddef3e2 --- /dev/null +++ b/cpu/x86/drivers/quarkX1000/imr.h @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_DRIVERS_QUARKX1000_IMR_H_ +#define CPU_X86_DRIVERS_QUARKX1000_IMR_H_ + +#include + +typedef union quarkX1000_imr_lo { + struct { + uint32_t : 2; + uint32_t addr : 22; + uint32_t : 7; + uint32_t lock : 1; + }; + uint32_t raw; +} quarkX1000_imr_lo_t; + +typedef union quarkX1000_imr_hi { + struct { + uint32_t : 2; + uint32_t addr : 22; + uint32_t : 8; + }; + uint32_t raw; +} quarkX1000_imr_hi_t; + +/* Amount to shift imr_lo/hi.addr left to obtain the bound address */ +#define QUARKX1000_IMR_SHAMT 10 + +typedef union quarkX1000_imr_rdmsk { + struct { + uint32_t cpu0 : 1; + uint32_t cpu_0 : 1; + uint32_t : 6; + uint32_t vc0_sai_id0 : 1; + uint32_t vc0_sai_id1 : 1; + uint32_t vc0_sai_id2 : 1; + uint32_t vc0_sai_id3 : 1; + uint32_t vc1_sai_id0 : 1; + uint32_t vc1_sai_id1 : 1; + uint32_t vc1_sai_id2 : 1; + uint32_t vc1_sai_id3 : 1; + uint32_t : 13; + uint32_t punit : 1; + uint32_t : 1; + uint32_t esram_flush_init : 1; + }; + uint32_t raw; +} quarkX1000_imr_rdmsk_t; + +typedef union quarkX1000_imr_wrmsk { + struct { + uint32_t cpu0 : 1; + uint32_t cpu_0 : 1; + uint32_t : 6; + uint32_t vc0_sai_id0 : 1; + uint32_t vc0_sai_id1 : 1; + uint32_t vc0_sai_id2 : 1; + uint32_t vc0_sai_id3 : 1; + uint32_t vc1_sai_id0 : 1; + uint32_t vc1_sai_id1 : 1; + uint32_t vc1_sai_id2 : 1; + uint32_t vc1_sai_id3 : 1; + uint32_t : 13; + uint32_t punit : 1; + uint32_t cpu_snoop : 1; + uint32_t esram_flush_init : 1; + }; + uint32_t raw; +} quarkX1000_imr_wrmsk_t; + +/* Refer to Intel Quark SoC X1000 Datasheet, Section 12.7.4 for more details on + * the IMR registers. + */ +typedef struct quarkX1000_imr { + quarkX1000_imr_lo_t lo; + quarkX1000_imr_hi_t hi; + quarkX1000_imr_rdmsk_t rdmsk; + quarkX1000_imr_wrmsk_t wrmsk; +} quarkX1000_imr_t; + +/* The Intel Quark SoC X1000 defines eight general IMRs. */ +#define QUARKX1000_IMR_CNT 8 + +/* Routines for accessing the Isolated Memory Region (IMR) feature. + * + * The Intel Quark X1000 SoC includes support for Isolated Memory Regions + * (IMRs), which are specified using range registers and associated + * control registers that are accessible via the message bus. + * + * Refer to Intel Quark SoC X1000 Datasheet, Section 12.2 for more information. + */ + +quarkX1000_imr_t quarkX1000_imr_read(uint32_t imr_idx); +void quarkX1000_imr_write(uint32_t imr_idx, quarkX1000_imr_t imr); + +#endif /* CPU_X86_DRIVERS_QUARKX1000_IMR_H_ */ diff --git a/cpu/x86/drivers/quarkX1000/msg-bus.c b/cpu/x86/drivers/quarkX1000/msg-bus.c new file mode 100644 index 000000000..fc64a6f8c --- /dev/null +++ b/cpu/x86/drivers/quarkX1000/msg-bus.c @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "msg-bus.h" +#include "pci.h" +#include "syscalls.h" + +PROT_DOMAINS_ALLOC(dom_client_data_t, quarkX1000_msg_bus); + +/** Message bus control register */ +#define MCR_PCI_REG_ADDR 0xD0 +/** Message data register */ +#define MDR_PCI_REG_ADDR 0xD4 +/** Message control register extension */ +#define MCRX_PCI_REG_ADDR 0xD8 + +typedef union mcr { + struct { + uint32_t : 4; + uint32_t byte_en : 4; + uint32_t reg_off : 8; + uint32_t port : 8; + uint32_t opcode : 8; + }; + uint32_t raw; +} mcr_t; + +typedef union mcrx { + struct { + uint32_t : 8; + uint32_t reg_off : 24; + }; + uint32_t raw; +} mcrx_t; + +/*---------------------------------------------------------------------------*/ +static void +request_op(uint8_t port, uint32_t reg_off, uint8_t opcode) +{ + pci_config_addr_t pci_addr = { .raw = 0 }; + mcr_t mcr = { .raw = 0 }; + mcrx_t mcrx = { .raw = 0 }; + + pci_addr.reg_off = MCR_PCI_REG_ADDR; + mcr.opcode = opcode; + mcr.byte_en = 0xF; + mcr.port = port; + mcr.reg_off = reg_off & 0xFF; + pci_config_write(pci_addr, mcr.raw); + + pci_addr.reg_off = MCRX_PCI_REG_ADDR; + mcrx.reg_off = reg_off >> 8; + pci_config_write(pci_addr, mcrx.raw); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Read from a message bus register. + * \param port Port of message bus register to be read. + * \param reg_off Register/offset identifier of message bus register to read. + * \param val Storage location for value that has been read. + */ +SYSCALLS_DEFINE_SINGLETON(quarkX1000_msg_bus_read, + quarkX1000_msg_bus, + uint8_t port, + uint32_t reg_off, + uint32_t *val) +{ + uint32_t *loc_val; + pci_config_addr_t pci_addr = { .raw = 0 }; + + PROT_DOMAINS_VALIDATE_PTR(loc_val, val, sizeof(*val)); + + request_op(port, reg_off, 0x10); + + pci_addr.reg_off = MDR_PCI_REG_ADDR; + *loc_val = pci_config_read(pci_addr); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Write to a message bus register. + * \param port Port of message bus register to be written. + * \param reg_off Register/offset identifier of message bus register to write. + * \param val Value to write. + */ +SYSCALLS_DEFINE_SINGLETON(quarkX1000_msg_bus_write, + quarkX1000_msg_bus, + uint8_t port, + uint32_t reg_off, + uint32_t val) +{ + pci_config_addr_t pci_addr = { .raw = 0 }; + + pci_addr.reg_off = MDR_PCI_REG_ADDR; + pci_config_write(pci_addr, val); + + request_op(port, reg_off, 0x11); +} +/*---------------------------------------------------------------------------*/ +void +quarkX1000_msg_bus_init(void) +{ + PROT_DOMAINS_INIT_ID(quarkX1000_msg_bus); + prot_domains_reg(&quarkX1000_msg_bus, 0, 0, 0, 0, true); + SYSCALLS_INIT(quarkX1000_msg_bus_read); + SYSCALLS_AUTHZ(quarkX1000_msg_bus_read, quarkX1000_msg_bus); + SYSCALLS_INIT(quarkX1000_msg_bus_write); + SYSCALLS_AUTHZ(quarkX1000_msg_bus_write, quarkX1000_msg_bus); +} +/*---------------------------------------------------------------------------*/ +void +quarkX1000_msg_bus_lock(void) +{ + SYSCALLS_DEAUTHZ(quarkX1000_msg_bus_read, quarkX1000_msg_bus); + SYSCALLS_DEAUTHZ(quarkX1000_msg_bus_write, quarkX1000_msg_bus); +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/drivers/quarkX1000/msg-bus.h b/cpu/x86/drivers/quarkX1000/msg-bus.h new file mode 100644 index 000000000..11bab0849 --- /dev/null +++ b/cpu/x86/drivers/quarkX1000/msg-bus.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_DRIVERS_QUARKX1000_MSG_BUS_H_ +#define CPU_X86_DRIVERS_QUARKX1000_MSG_BUS_H_ + +#include + +/* Routines for accessing the message bus. + * + * The Intel Quark X1000 SoC includes a message bus that is accessible + * via PCI configuration registers. It communicates to various SoC + * components such as the Isolated Memory Region (IMR) registers and the + * Remote Management Unit. + * + * Refer to Intel Quark SoC X1000 Datasheet, Section 12.5 for more details on + * the message bus. + */ + +void quarkX1000_msg_bus_init(void); +void quarkX1000_msg_bus_lock(void); +void quarkX1000_msg_bus_read(uint8_t port, uint32_t reg_off, uint32_t *val); +void quarkX1000_msg_bus_write(uint8_t port, uint32_t reg_off, uint32_t val); + +#endif /* CPU_X86_DRIVERS_QUARKX1000_MSG_BUS_H_ */ diff --git a/cpu/x86/drivers/quarkX1000/uart.c b/cpu/x86/drivers/quarkX1000/uart.c index 23731ba93..341e31cf7 100644 --- a/cpu/x86/drivers/quarkX1000/uart.c +++ b/cpu/x86/drivers/quarkX1000/uart.c @@ -32,8 +32,8 @@ #include "uart-16x50.h" #include -static uart_16x50_driver_t quarkX1000_uart0; -static uart_16x50_driver_t quarkX1000_uart1; +PROT_DOMAINS_ALLOC(uart_16x50_driver_t, quarkX1000_uart0); +PROT_DOMAINS_ALLOC(uart_16x50_driver_t, quarkX1000_uart1); /* Divisor setting for 115200 baud from section 18.2.2 of Intel Quark SoC * X1000 Datasheet. @@ -49,6 +49,7 @@ void quarkX1000_uart_init(quarkX1000_uart_dev_t dev) { pci_config_addr_t pci_addr; + uart_16x50_driver_t ATTR_KERN_ADDR_SPACE *drv; assert((dev == QUARK_X1000_UART_0) || (dev == QUARK_X1000_UART_1)); @@ -59,7 +60,14 @@ quarkX1000_uart_init(quarkX1000_uart_dev_t dev) pci_addr.func = (dev == QUARK_X1000_UART_0) ? 1 : 5; pci_addr.reg_off = PCI_CONFIG_REG_BAR0; - uart_16x50_init((dev == QUARK_X1000_UART_0) ? &quarkX1000_uart0 : &quarkX1000_uart1, pci_addr, QUARK_X1000_UART_DL_115200); + if(dev == QUARK_X1000_UART_0) { + drv = &quarkX1000_uart0; + PROT_DOMAINS_INIT_ID(quarkX1000_uart0); + } else { + drv = &quarkX1000_uart1; + PROT_DOMAINS_INIT_ID(quarkX1000_uart1); + } + uart_16x50_init(drv, pci_addr, QUARK_X1000_UART_DL_115200); } /*---------------------------------------------------------------------------*/ /** @@ -70,7 +78,11 @@ quarkX1000_uart_init(quarkX1000_uart_dev_t dev) void quarkX1000_uart_tx(quarkX1000_uart_dev_t dev, uint8_t c) { + uart_16x50_driver_t drv; assert((dev == QUARK_X1000_UART_0) || (dev == QUARK_X1000_UART_1)); - uart_16x50_tx((dev == QUARK_X1000_UART_0) ? quarkX1000_uart0 : quarkX1000_uart1, c); + prot_domains_copy_dcd(&drv, + (dev == QUARK_X1000_UART_0) ? + &quarkX1000_uart0 : &quarkX1000_uart1); + uart_16x50_tx(drv, c); } /*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/helpers.h b/cpu/x86/helpers.h index 91b120a9e..1ef312e14 100644 --- a/cpu/x86/helpers.h +++ b/cpu/x86/helpers.h @@ -37,6 +37,17 @@ void halt(void) __attribute__((__noreturn__)); +#define STRINGIFY(x) #x +/* The C preprocessor will not expand macro arguments that are converted to + * strings in the macro body using the '#' operator. The EXP_STRINGIFY macro + * introduces an additional level of argument expansion for instances where + * the developer wishes to convert the expanded argument to a string. + */ +#define EXP_STRINGIFY(x) STRINGIFY(x) + +#define ALIGN(x, amt) \ + (((x) & ~((amt) - 1)) + ((((x) & ((amt) - 1)) == 0) ? 0 : (amt))) + /** Wrappers for the assembly 'out' instruction. */ void outb(uint16_t port, uint8_t val); void outl(uint16_t port, uint32_t val); diff --git a/cpu/x86/init/common/cpu.c b/cpu/x86/init/common/cpu.c index a174853cc..dd58b96d5 100644 --- a/cpu/x86/init/common/cpu.c +++ b/cpu/x86/init/common/cpu.c @@ -28,11 +28,13 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "cpu.h" #include "gdt.h" #include "helpers.h" #include "idt.h" #include "interrupt.h" #include "irq.h" +#include "stacks.h" static void double_fault_handler(struct interrupt_context context) @@ -40,16 +42,83 @@ double_fault_handler(struct interrupt_context context) halt(); } /*---------------------------------------------------------------------------*/ -void -cpu_init(void) +/* The OS has switched to its own segment descriptors. When multi-segment + * protection domain support is enabled, this routine runs with the + * necessary address translations configured to invoke other routines that + * require those translations to be in place. However, the protection domain + * support, if enabled, has not yet been fully activated. + */ +static void +boot_stage1(void) { - gdt_init(); idt_init(); /* Set an interrupt handler for Double Fault exception. This way, we avoid * the system to triple fault, leaving no trace about what happened. */ - SET_INTERRUPT_HANDLER(8, 1, double_fault_handler); + SET_EXCEPTION_HANDLER(8, 1, double_fault_handler); - irq_init(); + /* Initialize protection domain support, if enabled */ + prot_domains_init(); + + prot_domains_leave_boot_stage1(); +} +/*---------------------------------------------------------------------------*/ +int main(void); +/* This routine runs with the initial, flat address space, even if protection + * domain support is enabled. The goal behind the design of this routine is to + * keep it as short as possible, since it is unable to directly reference data + * and invoke functions that are intended to be accessible later after the + * system has booted when a multi-segment protection domain model is in use. + */ +void +cpu_boot_stage0(void) +{ + /* Reserve three stack slots for return addresses */ + uintptr_t top_of_stack = STACKS_INIT_TOP; + +#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__NONE + uintptr_t *top_of_stack_ptr = + (uintptr_t *)DATA_OFF_TO_PHYS_ADDR(top_of_stack); + + top_of_stack_ptr[0] = (uintptr_t)prot_domains_launch_kernel; + top_of_stack_ptr[1] = (uintptr_t)prot_domains_launch_app; +#endif + + /* Perform common GDT initialization */ + gdt_init(); + + /* Switch all data segment registers to the newly-initialized flat data + * descriptor. + */ + __asm__( + "mov %0, %%ds\n\t" + "mov %0, %%es\n\t" + "mov %0, %%fs\n\t" + "mov %0, %%gs\n\t" + : + : "r" (GDT_SEL_DATA_FLAT) + ); + + /** + * Perform specific GDT initialization tasks for the protection domain + * implementation that is enabled, if any. + */ + prot_domains_gdt_init(); + + /* Do not pass memory operands to the asm block below, since it is + * switching from the flat address space to a multi-segment address space + * model if such a model is used by the enabled protection domain + * implementation, if any. + */ + __asm__( + "mov %[_ss_], %%ss\n\t" + "mov %[_esp_], %%esp\n\t" + "ljmp %[_cs_], %[_stage1_]\n\t" + : + : [_ss_] "r" (GDT_SEL_STK_EXC), + [_esp_] "r" (top_of_stack), + [_cs_] "i" ((uint16_t)GDT_SEL_CODE_EXC), + [_stage1_] "i" (boot_stage1) + ); } diff --git a/cpu/x86/init/common/cpu.h b/cpu/x86/init/common/cpu.h index a56d0db5a..4fd9b835b 100644 --- a/cpu/x86/init/common/cpu.h +++ b/cpu/x86/init/common/cpu.h @@ -31,6 +31,8 @@ #ifndef CPU_H #define CPU_H -void cpu_init(void); +#include "prot-domains.h" + +void cpu_boot_stage0(void) ATTR_CODE_BOOT; #endif /* CPU_H */ diff --git a/cpu/x86/init/common/gdt.c b/cpu/x86/init/common/gdt.c index 39a8a7ce4..f63767850 100644 --- a/cpu/x86/init/common/gdt.c +++ b/cpu/x86/init/common/gdt.c @@ -29,45 +29,15 @@ */ #include +#include "gdt.h" +#include "gdt-layout.h" +#include "helpers.h" +#include "prot-domains.h" +#include "segmentation.h" -#define NUM_DESC 3 - -#define GDT_IDX_NULL 0 -#define GDT_IDX_CODE 1 -#define GDT_IDX_DATA 2 - -/* All code in the x86 port of Contiki runs at ring (privilege) level 0 */ -#define PRIV_LVL 0 - -/* Compute GDT selector from descriptor index and requested privilege level */ -#define GDT_SEL(IDX, RPL) (((IDX) << 3) | (RPL)) - -#define GDT_SEL_NULL GDT_SEL(GDT_IDX_NULL, 0) -#define GDT_SEL_CODE GDT_SEL(GDT_IDX_CODE, PRIV_LVL) -#define GDT_SEL_DATA GDT_SEL(GDT_IDX_DATA, PRIV_LVL) - -/* Each define here is for a specific flag in the descriptor. Refer to Intel - * Combined Manual (Intel 64 and IA-32 Architectures Software Developer's - * Manual), Vol. 3, Section 3.4.5 for a description of each flag. - */ -#define SEG_DESCTYPE(x) ((x) << 0x04) /* Descriptor type (0 for system, 1 for code/data) */ -#define SEG_PRES(x) ((x) << 0x07) /* Present */ -#define SEG_SAVL(x) ((x) << 0x0C) /* Available for system use */ -#define SEG_LONG(x) ((x) << 0x0D) /* Long mode */ -#define SEG_SIZE(x) ((x) << 0x0E) /* Size (0 for 16-bit, 1 for 32) */ -#define SEG_GRAN(x) ((x) << 0x0F) /* Granularity (0 for 1B - 1MB, 1 for 4KB - 4GB) */ -#define SEG_PRIV(x) (((x) & 0x03) << 0x05) /* Set privilege level (0 - 3) */ - -#define SEG_DATA_RDWR 0x02 /* Read/Write */ -#define SEG_CODE_EXRD 0x0A /* Execute/Read */ - -#define GDT_CODE_PL0 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \ - SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \ - SEG_PRIV(0) | SEG_CODE_EXRD - -#define GDT_DATA_PL0 SEG_DESCTYPE(1) | SEG_PRES(1) | SEG_SAVL(0) | \ - SEG_LONG(0) | SEG_SIZE(1) | SEG_GRAN(1) | \ - SEG_PRIV(0) | SEG_DATA_RDWR +#define GDT_MEM_PL0 (SEG_DESCTYPE_NSYS | SEG_GRAN_PAGE) +#define GDT_CODE_PL0 (GDT_MEM_PL0 | SEG_TYPE_CODE_EXRD) +#define GDT_DATA_PL0 (GDT_MEM_PL0 | SEG_TYPE_DATA_RDWR) typedef struct gdtr { @@ -75,44 +45,58 @@ typedef struct gdtr uint32_t base; } __attribute__((packed)) gdtr_t; -typedef uint64_t segment_desc_t; - /* From Intel Combined Manual, Vol. 3 , Section 3.5.1: The base addresses of * the GDT should be aligned on an eight-byte boundary to yield the best * processor performance. */ -static segment_desc_t gdt[NUM_DESC] __attribute__ ((aligned (8))); +segment_desc_t __attribute__ ((aligned(8))) ATTR_BSS_GDT_START + gdt[GDT_NUM_FIXED_DESC]; -static void -set_descriptor(unsigned int index, uint32_t base, uint32_t limit, uint16_t flag) +#define GDT_LEN \ + ((((uintptr_t)&_ebss_gdt_addr) - \ + (uintptr_t)gdt)/sizeof(segment_desc_t)) + +/*---------------------------------------------------------------------------*/ +static void ATTR_CODE_BOOT +set_descriptor(unsigned int index, + uint32_t base, + uint32_t len, + uint16_t flag) { segment_desc_t descriptor; - if (index >= NUM_DESC) - return; + if(GDT_LEN <= index) { + halt(); + } - /* Create the high 32 bit segment */ - descriptor = limit & 0x000F0000; /* set limit bits 19:16 */ - descriptor |= (flag << 8) & 0x00F0FF00; /* set type, p, dpl, s, g, d/b, l and avl fields */ - descriptor |= (base >> 16) & 0x000000FF; /* set base bits 23:16 */ - descriptor |= base & 0xFF000000; /* set base bits 31:24 */ - - /* Shift by 32 to allow for low part of segment */ - descriptor <<= 32; - - /* Create the low 32 bit segment */ - descriptor |= base << 16; /* set base bits 15:0 */ - descriptor |= limit & 0x0000FFFF; /* set limit bits 15:0 */ + segment_desc_init(&descriptor, base, len, flag); /* Save descriptor into gdt */ - gdt[index] = descriptor; + gdt_insert_boot(index, descriptor); } +/*---------------------------------------------------------------------------*/ +void +gdt_copy_desc_change_dpl(unsigned int dest_idx, + unsigned int src_idx, + unsigned dpl) +{ + segment_desc_t desc; + if((GDT_LEN <= dest_idx) || (GDT_LEN <= src_idx)) { + halt(); + } -/* This function initializes the Global Offset Table. For simplicity, the - * memory is organized following the flat model. Thus, memory appears to - * Contiki as a single continuous address space. Code, data, and stack + gdt_lookup(src_idx, &desc); + SEG_SET_FLAG(desc, DPL, dpl); + gdt_insert(dest_idx, desc); +} +/*---------------------------------------------------------------------------*/ +/* This function initializes the Global Descriptor Table. For simplicity, the + * memory is initially organized following the flat model. Thus, memory appears + * to Contiki as a single continuous address space. Code, data, and stack * are all contained in this address space (so called linear address space). + * Certain protection domain implementations switch to a multi-segment memory + * model later during boot. */ void gdt_init(void) @@ -120,29 +104,43 @@ gdt_init(void) gdtr_t gdtr; /* Initialize gdtr structure */ - gdtr.limit = sizeof(segment_desc_t) * NUM_DESC - 1; - gdtr.base = (uint32_t) &gdt; + gdtr.limit = sizeof(segment_desc_t) * GDT_LEN - 1; + gdtr.base = KERN_DATA_OFF_TO_PHYS_ADDR(gdt); /* Initialize descriptors */ set_descriptor(GDT_IDX_NULL, 0, 0, 0); - set_descriptor(GDT_IDX_CODE, 0, 0x0FFFFF, GDT_CODE_PL0); - set_descriptor(GDT_IDX_DATA, 0, 0x0FFFFF, GDT_DATA_PL0); + set_descriptor(GDT_IDX_CODE_FLAT, 0, 0x100000, GDT_CODE_PL0); + set_descriptor(GDT_IDX_DATA_FLAT, 0, 0x100000, GDT_DATA_PL0); - /* Load GDTR register and update segment registers. - * - * CS register cannot be changed directly. For that reason, we do a far jump. - */ - __asm__ ("lgdt %[_gdtr_]\n\t" - "jmp %[_cs_], $1f\n\t" - "1:\n\t" - "mov %[_ds_], %%ds\n\t" - "mov %[_ds_], %%ss\n\t" - "mov %[_ds_], %%es\n\t" - "mov %[_ds_], %%fs\n\t" - "mov %[_ds_], %%gs\n\t" - : - : [_gdtr_] "m" (gdtr), - [_cs_] "i" (GDT_SEL_CODE), - [_ds_] "r" (GDT_SEL_DATA) - ); + /* Load GDTR */ + __asm__ __volatile__ ("lgdt %0" :: "m" (gdtr)); } +/*---------------------------------------------------------------------------*/ +void +gdt_insert_boot(unsigned int idx, segment_desc_t desc) +{ + ((segment_desc_t *)KERN_DATA_OFF_TO_PHYS_ADDR(gdt))[idx] = desc; +} +/*---------------------------------------------------------------------------*/ +void +gdt_insert(unsigned int idx, segment_desc_t desc) +{ + if(GDT_LEN <= idx) { + halt(); + } + + KERN_WRITEL(gdt[idx].raw_lo, desc.raw_lo); + KERN_WRITEL(gdt[idx].raw_hi, desc.raw_hi); +} +/*---------------------------------------------------------------------------*/ +void +gdt_lookup(unsigned int idx, segment_desc_t *desc) +{ + if((GDT_LEN <= idx) || (desc == NULL)) { + halt(); + } + + KERN_READL(desc->raw_lo, gdt[idx].raw_lo); + KERN_READL(desc->raw_hi, gdt[idx].raw_hi); +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/init/common/gdt.h b/cpu/x86/init/common/gdt.h index 3db17f08c..305e32716 100644 --- a/cpu/x86/init/common/gdt.h +++ b/cpu/x86/init/common/gdt.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,6 +31,48 @@ #ifndef GDT_H #define GDT_H -void gdt_init(void); +#include "gdt-layout.h" +#include "prot-domains.h" +#include "segmentation.h" + +extern segment_desc_t ATTR_KERN_ADDR_SPACE gdt[]; +extern int ATTR_KERN_ADDR_SPACE _ebss_gdt_addr; + +#define GDT_IDX_OF_DESC(ptr) \ + ((((uintptr_t)(ptr)) - ((uintptr_t)&gdt))/ \ + sizeof(segment_desc_t)) + +typedef struct far_pointer { + /** Far pointer offset. */ + uint32_t offset; + /** Far pointer segment/gate selector. */ + uint16_t sel; + uint16_t pad; +} __attribute__((packed)) far_pointer_t; + +/** + * \brief Compute the selector for a GDT entry allocated somewhere besides gdt.c. + * \param ptr Pointer to GDT descriptor. + * \param rpl Requested Privilege Level. + */ +#define GDT_SEL_OF_DESC(ptr, rpl) GDT_SEL(GDT_IDX_OF_DESC(ptr), rpl) + +/* Section for fixed GDT entries */ +#define ATTR_BSS_GDT \ + __attribute__((section(".gdt_bss"))) ATTR_KERN_ADDR_SPACE +/* Section for TSS and LDT descriptors for protection domains */ +#define ATTR_BSS_GDT_MID \ + __attribute__((used, section(".gdt_bss_mid"))) ATTR_KERN_ADDR_SPACE +/* Section for other GDT entries */ +#define ATTR_BSS_GDT_START \ + __attribute__((section(".gdt_bss_start"))) ATTR_KERN_ADDR_SPACE + +void gdt_copy_desc_change_dpl(unsigned int dest_idx, + unsigned int src_idx, + unsigned dpl); +void gdt_init(void) ATTR_CODE_BOOT; +void gdt_insert(unsigned int idx, segment_desc_t desc); +void gdt_insert_boot(unsigned int idx, segment_desc_t desc) ATTR_CODE_BOOT; +void gdt_lookup(unsigned int idx, segment_desc_t *desc); #endif /* GDT_H */ diff --git a/cpu/x86/init/common/idt.c b/cpu/x86/init/common/idt.c index d561f49f7..c5de5ed25 100644 --- a/cpu/x86/init/common/idt.c +++ b/cpu/x86/init/common/idt.c @@ -28,9 +28,13 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "gdt-layout.h" +#include "prot-domains.h" #include #include "helpers.h" +#include "segmentation.h" +#include "idt.h" #define NUM_DESC 256 @@ -39,40 +43,55 @@ typedef struct idtr { uint32_t base; } __attribute__((packed)) idtr_t; -typedef struct intr_gate_desc { - uint16_t offset_low; - uint16_t selector; /* Segment Selector for destination code segment */ - uint16_t fixed:11; - uint16_t d:1; /* Size of gate: 1 = 32 bits; 0 = 16 bits */ - uint16_t pad:1; - uint16_t dpl:2; /* Descriptor Privilege Level */ - uint16_t p:1; /* Segment Present flag */ - uint16_t offset_high; - -} __attribute__((packed)) intr_gate_desc_t; +typedef union intr_gate_desc { + struct __attribute__((packed)) { + uint16_t offset_low; + uint16_t selector; /* Segment Selector for destination code segment */ + uint16_t fixed:11; + uint16_t d:1; /* Size of gate: 1 = 32 bits; 0 = 16 bits */ + uint16_t pad:1; + uint16_t dpl:2; /* Descriptor Privilege Level */ + uint16_t p:1; /* Segment Present flag */ + uint16_t offset_high; + }; + uint64_t raw; + struct { + uint32_t raw_lo; + uint32_t raw_hi; + }; +} intr_gate_desc_t; /* According to Intel Combined Manual, Vol. 3, Section 6.10, the base addresses * of the IDT should be aligned on an 8-byte boundary to maximize performance * of cache line fills. */ -static intr_gate_desc_t idt[NUM_DESC] __attribute__ ((aligned(8))); +static intr_gate_desc_t __attribute__((aligned(8))) ATTR_BSS_KERN + idt[NUM_DESC]; +/*---------------------------------------------------------------------------*/ /* XXX: If you change this function prototype, make sure you fix the assembly - * code in SET_INTERRUPT_HANDLER macro in interrupt.h. Otherwise, you might + * code in SET_INT_EXC_HANDLER macro in interrupt.h. Otherwise, you might * face a very-hard-to-find bug in the interrupt handling system. */ void -idt_set_intr_gate_desc(int intr_num, uint32_t offset) +idt_set_intr_gate_desc(int intr_num, + uint32_t offset, + uint16_t cs, + uint16_t dpl) { - intr_gate_desc_t *desc = &idt[intr_num]; + intr_gate_desc_t desc; - desc->offset_low = offset & 0xFFFF; - desc->selector = 0x08; /* Offset in GDT for code segment */ - desc->fixed = BIT(9) | BIT(10); - desc->d = 1; - desc->dpl = 0; - desc->p = 1; - desc->offset_high = (offset >> 16) & 0xFFFF; + desc.offset_low = offset & 0xFFFF; + desc.selector = cs; + desc.fixed = BIT(9) | BIT(10); + desc.pad = 0; + desc.d = 1; + desc.dpl = dpl; + desc.p = 1; + desc.offset_high = (offset >> 16) & 0xFFFF; + + KERN_WRITEL(idt[intr_num].raw_hi, desc.raw_hi); + KERN_WRITEL(idt[intr_num].raw_lo, desc.raw_lo); } /*---------------------------------------------------------------------------*/ /* Initialize Interrupt Descriptor Table. The IDT is initialized with @@ -86,7 +105,7 @@ idt_init(void) /* Initialize idtr structure */ idtr.limit = (sizeof(intr_gate_desc_t) * NUM_DESC) - 1; - idtr.base = (uint32_t)&idt; + idtr.base = KERN_DATA_OFF_TO_PHYS_ADDR((uint32_t)idt); /* Load IDTR register */ __asm__("lidt %0\n\t" :: "m" (idtr)); diff --git a/cpu/x86/init/common/idt.h b/cpu/x86/init/common/idt.h index d29b97153..059e81705 100644 --- a/cpu/x86/init/common/idt.h +++ b/cpu/x86/init/common/idt.h @@ -32,8 +32,12 @@ #define IDT_H #include +#include "prot-domains.h" void idt_init(void); -void idt_set_intr_gate_desc(int intr_num, uint32_t offset); +void idt_set_intr_gate_desc(int intr_num, + uint32_t offset, + uint16_t cs, + uint16_t dpl); #endif /* IDT_H */ diff --git a/cpu/x86/init/common/interrupt.h b/cpu/x86/init/common/interrupt.h index 2ab228c72..10b906be4 100644 --- a/cpu/x86/init/common/interrupt.h +++ b/cpu/x86/init/common/interrupt.h @@ -32,10 +32,17 @@ #define INTERRUPT_H #include +#include "gdt-layout.h" #include "idt.h" struct interrupt_context { + /* The general-purpose register values are saved by the pushal instruction in + * the interrupt dispatcher. Having access to these saved values may be + * useful in some future interrupt or exception handler, and saving and later + * restoring them also enables the ISR to freely overwrite the EAX, ECX, and + * EDX registers as is permitted by the cdecl calling convention. + */ uint32_t edi; uint32_t esi; uint32_t ebp; @@ -44,10 +51,35 @@ struct interrupt_context { uint32_t edx; uint32_t ecx; uint32_t eax; + /* These two values are pushed on the stack by the CPU when it delivers an + * exception with an associated error code. Currently, only the double fault + * handler accepts this structure as a parameter, and that type of exception + * does have an associated error code. + */ uint32_t error_code; uint32_t eip; + /* The CPU pushes additional values beyond these on the stack, specifically + * the code segment descriptor and flags. If a privilege-level change occurs + * during delivery, the CPU additionally pushes the stack pointer and stack + * segment descriptor. + */ }; +#define ISR_STUB(label_str, has_error_code, handler_str, exc) \ + "jmp 2f\n\t" \ + ".align 4\n\t" \ + label_str ":\n\t" \ + " pushal\n\t" \ + PROT_DOMAINS_ENTER_ISR(exc) \ + " call " handler_str "\n\t" \ + PROT_DOMAINS_LEAVE_ISR(exc) \ + " popal\n\t" \ + " .if " #has_error_code "\n\t" \ + " add $4, %%esp\n\t" \ + " .endif\n\t" \ + " iret\n\t" \ + "2:\n\t" + /* Helper macro to register interrupt handler function. * * num: Interrupt number (0-255) @@ -59,6 +91,14 @@ struct interrupt_context { * void handler(void) * Otherwise, it should be: * void handler(struct interrupt_context context) + * exc: 0 if this is an interrupt, which should be handled + * at the interrupt privilege level. 1 if this is an + * exception, which should be handled at the + * exception privilege level. + * dpl: Privilege level for IDT descriptor, which is the + * numerically-highest privilege level that can + * generate this interrupt with a software interrupt + * instruction. * * Since there is no easy way to write an Interrupt Service Routines * (ISR) in C (for further information on this, see [1]), we provide @@ -68,28 +108,30 @@ struct interrupt_context { * * [1] http://wiki.osdev.org/Interrupt_Service_Routines */ -#define SET_INTERRUPT_HANDLER(num, has_error_code, handler) \ - do { \ - __asm__ __volatile__ ( \ - "push $1f\n\t" \ - "push %0\n\t" \ - "call %P1\n\t" \ - "add $8, %%esp\n\t" \ - "jmp 2f\n\t" \ - ".align 4\n\t" \ - "1:\n\t" \ - " pushal\n\t" \ - " call %P2\n\t" \ - " popal\n\t" \ - " .if " #has_error_code "\n\t" \ - " add $4, %%esp\n\t" \ - " .endif\n\t" \ - " iret\n\t" \ - "2:\n\t" \ - :: "g" (num), "i" (idt_set_intr_gate_desc), "i" (handler) \ - : "eax", "ecx", "edx" \ - ); \ +#define SET_INT_EXC_HANDLER(num, has_error_code, handler, exc, dpl) \ + do { \ + __asm__ __volatile__ ( \ + "pushl %[_dpl_]\n\t" \ + "pushl %[_cs_]\n\t" \ + "pushl $1f\n\t" \ + "pushl %[_isr_num_]\n\t" \ + "call idt_set_intr_gate_desc\n\t" \ + "add $16, %%esp\n\t" \ + ISR_STUB("1", has_error_code, "%P[_handler_]", exc) \ + : \ + : [_isr_num_] "g" (num), \ + [_handler_] "i" (handler), \ + [_cs_] "i" (exc ? GDT_SEL_CODE_EXC : GDT_SEL_CODE_INT), \ + [_dpl_] "i" (dpl) \ + /* the invocation of idt_set_intr_gate_desc may clobber */ \ + /* the caller-saved registers: */ \ + : "eax", "ecx", "edx" \ + ); \ } while (0) +#define SET_INTERRUPT_HANDLER(num, has_error_code, handler) \ + SET_INT_EXC_HANDLER(num, has_error_code, handler, 0, PRIV_LVL_INT) +#define SET_EXCEPTION_HANDLER(num, has_error_code, handler) \ + SET_INT_EXC_HANDLER(num, has_error_code, handler, 1, PRIV_LVL_EXC) /* Disable maskable hardware interrupts */ #define DISABLE_IRQ() \ diff --git a/cpu/x86/mm/README.md b/cpu/x86/mm/README.md new file mode 100644 index 000000000..42c4070a7 --- /dev/null +++ b/cpu/x86/mm/README.md @@ -0,0 +1,997 @@ +X86 Lightweight Protection Domain Support for Contiki +===================================================== + +Introduction +------------ + +The X86 port of Contiki implements a simple, lightweight form of +protection domains using a pluggable framework. Currently, there are +three plugins available: + + - Flat memory model with paging. + - Multi-segment memory model with either hardware- or + software-switched segments. The hardware-switched segments + approach is based on Task-State Segment (TSS) structures. + +For an introduction to paging and TSS and possible ways in which they +can be used, refer to the following resources: + + - Intel Combined Manual (Intel 64 and IA-32 Architectures Software + Developer's Manual), Vol. 3, Chapter 4 + - Programming the 80386, by John H. Crawford and Patrick + P. Gelsinger, Chapter 5 + +The overall goal of a protection domain implementation within this +framework is to define a set of resources that should be accessible to +each protection domain and to prevent that protection domain from +accessing other resources. The details of each implementation of +protection domains may differ substantially, but they should all be +guided by the principle of least privilege [1]. However, that +idealized principle is balanced against the practical objectives of +limiting the number of relatively time-consuming context switches and +minimizing changes to existing code. In fact, no changes were made to +code outside of the CPU- and platform-specific code directories for +the initial plugins. + +Each protection domain can optionally be associated with a metadata +and/or MMIO region. The hardware can support additional regions per +protection domain, but that would increase complexity and is unneeded +for the existing protection domains. + +After boot, all code runs in the context of some protection domain. +Two default protection domains are implemented: + +- kern: Kernel protection domain that is more privileged than any + other protection domain. As little code as possible should be placed + in this protection domain. +- app: Application protection domain used whenever special privileges + are not required. + +Additional protection domains are defined as needed. For example, +each driver may reside in a separate protection domain, although not +all drivers require additional privileges beyond those available in +the relevant scheduling context in the app protection domain. The +Ethernet and UART drivers are assigned separate protection domains. +Non-driver protection domains can also be defined. Other drivers only +require access to programmed IO ports accessible via the IN* and OUT* +instructions, and such drivers do not require separate protection +domains. They run in the Contiki preemptive scheduling context and +the kernel protection domain, both of which are granted access to all +IO ports. + +Each protection domain may have associated system calls. A system +call transfers control from a client protection domain to a defined +entrypoint in a server protection domain. As their name suggests, +system calls adhere to a synchronous call-return model (rather than +some alternative such as an asynchronous message-passing model). To +invoke a system call, the client provides two identifiers to the +system call dispatcher. The first identifies the server domain and +the second identifies the system call to be invoked. The protection +domain implementation should associate allowable system calls with +particular server protection domains and reject any system call +requests that are not within that set of allowable system calls. The +system call implementations do not restrict the clients that are +permitted to invoke each system call. No modifications that the +client can make to the server domain and system call identifiers can +open up new entrypoints into the server domain. The entrypoints are +fixed at boot time. + +However, if the identifiers were stored in shared memory, it may be +possible for a protection domain to influence the system calls issued +by some other protection domain, which may be undesirable. Thus, the +server domain identifiers are stored in memory that can only be +written by the kernel protection domain and the system call +identifiers are embedded in the code. + +The system call dispatcher is responsible for reconfiguring the system +to enforce the appropriate resource access controls for the server +protection domain. It should then transfer control to the approved +entrypoint for the requested system call. + +Contiki defines a process concept that is orthogonal to protection +domains [2]. A single Contiki process may run code in multiple +protection domains at various points in time. Contiki processes run +in a cooperative scheduling context. Contiki also defines a +preemptive scheduling context for interrupt handlers and real-time +timers. When protection domain support is enabled, interrupts are +only enabled when the application protection domain is active and is +running code in the cooperative scheduling context. Code running in +the preemptive context may also invoke multiple protection domains. +Contiki can also support preemptive multithreading, but support for +that has not yet been added to the X86 port so we do not discuss it +further. + +A single stack is shared by all code that runs in the cooperative +scheduling context in all protection domains, and separate stacks are +defined for short interrupt dispatchers in the preemptive scheduling +context and for exception handlers and software system call +dispatchers. Except for the interrupt dispatchers, code in the +preemptive scheduling context also shares the same stack with the +cooperative scheduling context. All protection domains also share a +main data section, so similar considerations are also relevant to +that. + +Introducing multi-core support would complicate things further, since +another core running a protection domain that the first core never +invoked could access data from the protection domain on the first +core. It may be possible to adequately address such concerns by +allocating per-core stacks. + +Note that this stack arrangement means that a given protection domain +may read and write data written to the stack by some other protection +domain. For example, a protection domain B may push data onto the +stack and later pop that data off of the stack, but a protection +domain A that invoked protection domain B may still be able to read +the data that was pushed and popped to and from the stack, since +popping the data off of the stack does not automatically erase that +stack memory location. Another possibility is that protection domain +B may modify a stack entry pushed by protection domain A before it +invoked protection domain B, and protection domain A may later use the +modified value. Permitting legitimate accesses to callers' stacks is +in fact the primary motivation for this stack arrangement, in that it +makes it simple for A to pass data to and from B (on the shared stack) +when requesting services from B. A system call invocation is nearly +transparent to the developer, appearing almost identical to an +ordinary function call. However, B can access any data on the stack. +The third case is that A can read data placed on the stack by B after +B returns, unless B wipes that data from the stack before returning. +A related sub-case is that if an interrupt handler is invoked, it +pushes the current contents of the general-purpose registers onto the +stack, which may then be revealed to other protection domains besides +the one that was interrupted. However, interrupts are only actually +enabled in the application protection domain. + +Similarly, register contents may be accessed and modified across +protection domain boundaries in some protection domain +implementations. The TSS task switching mechanism automatically saves +and restores many registers to and from TSS data structures when +switching tasks, but the other protection domain implementations do +not perform analogous operations. + +For the reasons described above, each protection domain should only +invoke other protection domains that it trusts to properly handle data +on the stack. + +Design +------ + +### Boot Process + +The system boots in the following phases. + +#### UEFI Bootstrap + +Primary implementation sources: + + - cpu/x86/uefi/bootstrap_uefi.c + +When the OS is compiled as a UEFI binary, a short bootstrap phase that +is UEFI-compliant is run initially. It simply performs a minimal set +of functions to exit the UEFI boot services and then transfer control +to the Multiboot bootstrap phase. + +#### Multiboot Bootstrap + +Primary implementation sources: + + - cpu/x86/bootstrap_quarkX1000.S + +This phase disables interrupts, sets the stack pointer to the top of +the main stack, and then invokes boot stage 0. + +#### Boot Stage 0 + +Primary implementation sources: + + - cpu/x86/init/common/cpu.c + - cpu/x86/init/common/gdt.c + +The UEFI firmware or Multiboot-compliant bootloader should have +configured an initial Global Descriptor Table (GDT) with flat segments +and configured the CPU to operate in protected mode with paging +disabled. Flat segments each map the whole 4GiB physical memory +space. This is the state of the system when the OS enters boot stage +0. This stage is responsible for setting up a new GDT and loading the +segment registers with the appropriate descriptors from the new GDT to +enable boot stage 1 to run. Code in stage 1 for multi-segment +protection domain implementations require that the appropriate +segment-based address translations be configured. + +#### Boot Stage 1 + +Primary implementation sources: + + - cpu/x86/init/common/cpu.c + - cpu/x86/init/common/idt.c + - cpu/x86/mm/prot-domains.c + +Boot stage 1 intializes the Interrupt Descriptor Table (IDT) and +installs a handler for double-fault exceptions. Handlers for +additional interrupts and exceptions are installed later in boot +stages 1 and 2. + +This stage also initializes protection domain support and enters the +kernel protection domain. + +#### Boot Stage 2 + +Primary implementation sources: + + - cpu/x86/init/common/cpu.c + - platform/galileo/contiki-main.c + +The entrypoint for the kernel protection domain is 'main'. Boot stage +2 initializes hardware devices and associated interrupts. It then +transfers control to the application protection domain. Note that +this is a transfer of control, not a call that would be matched with +some future return. This is an important distinction, because +protection domains are not reentrant. Thus, if the kernel protection +domain called the application protection domain, it would not be +possible to invoke any kernel system calls until the system is reset, +since the application protection domain never exits/returns while the +system is running. There are not actually any kernel system calls +provided in the initial implementation of protection domains, but they +may be added in the future. + +The core protection domain configuration (e.g. allowable system calls +and entrypoints, registered protection domains, etc.) is frozen by the +conclusion of boot stage 2 to help prevent erroneous changes that +could reduce the robustness of the system. The way that it is frozen +is that there are no kernel system calls that are intended to permit +changes to the core protection domain configuration. Thus, once the +kernel protection domain has exited, the only way the core protection +domain configuration can change would be due to undesirable memory +manipulations (e.g. due to a faulty device driver). + +#### Boot Stage 3 + +Primary implementation sources: + + - platform/galileo/contiki-main.c + +Boot stage 3 performs initialization procedures that are less +tightly-coupled to hardware. For example, it launches Contiki +processes and invokes Contiki configuration routines. + +### Privilege Levels + +When protection domain support is inactive, all code runs at +ring/privilege level 0. When protection domain support is active, +only exception handlers and system call dispatchers (including +dispatchers for system call returns) run at ring level 0. Code in the +preemptive scheduling context runs at ring level 2 and code in the +cooperative scheduling context runs at ring level 3. Ring levels with +higher numbers are less privileged than those with lower numbers. +Ring level 1 is unused. + +### IO and Interrupt Privileges + +The kernel protection domain cooperative scheduling context needs +access to IO ports, for device initialization. Some other protection +domains also require such access. The IO Privilege Level (IOPL) that +is assigned to a protection domain using the relevant bits in the +EFLAGS field could be set according to whether IO port access is +required in that protection domain. This is straightforward for TSS, +which includes separate flags settings for each protection domain. +However, this would introduce additional complexity and overhead in +the critical system call and return dispatchers for other plugins. +Instead, the IOPL is always set to block IO access from the +cooperative scheduling context. Port IO instructions in that context +will then generate general protection faults, and the exception +handler decodes and emulates authorized port IO instructions. + +Interrupts are handled at ring level 2, since they do not use any +privileged instructions. They do cause the interrupt flag to be +cleared as they are delivered. The interrupt flag can only be +modified by instructions executing at a ring level that is numerically +less than or equal to the IOPL. Each interrupt handler needs to set +the interrupt flag using the IRET instruction when it returns. +Protection domains that require access to port IO (currently just the +kernel protection domain) are configured with an IOPL of 3 whereas +others are configured with an IOPL of 2. That is why interrupts are +configured to run at ring level 2. Interrupts are only enabled in the +application protection domain. + +Some interrupt handlers require access to port IO, and all are +permitted such access, since they need it anyway for restoring the +interrupt flag when returning. IO port access is a very powerful +privilege, since it can be used to remap MMIO regions of PCI devices, +reconfigure PCI devices, etc. Thus, further restricting access to IO +ports may improve the robustness of the system, but would increase +complexity and space requirements and possibly necessitate additional +context switches, since IO port access is controlled by the combined +settings of IOPL as well as an optional IO bitmap in the TSS. + +### Interrupt and Exception Dispatching + +Primary implementation sources: + - cpu/x86/init/common/interrupt.h + +Separate stacks are allocated for dispatching interrupts and +exceptions. However, to save space, the main bodies of some interrupt +and exception handlers are run on the main stack. A handler may +expect to have access to data from the interrupt or exception stack, +so the interrupt or exception dispatcher copies that data prior to +pivoting to the main stack and executing the handler. + +### Protection Domain Control Structures (PDCSes) + +Each protection domain is managed by the kernel and privileged +functions using a PDCS. The structure of the PDCS is partially +hardware-imposed in the cases of the two segment-based plugins, since +the PDCS contains the Local Descriptor Table (LDT) and the TSS, if +applicable. In the paging plugin, the PDCS structure is entirely +software-defined. None of the initial protection domain plugins +support re-entrant protection domains due to hardware-imposed +limitations of TSS and to simplify the implementation of the other +plugins by enabling domain-specific information (e.g. system call +return address) to be trivially stored in each PDCS. + +### Paging-Based Protection Domains + +Primary implementation sources: + + - cpu/x86/mm/paging-prot-domains.c + - cpu/x86/mm/syscalls-int.c + - cpu/x86/mm/syscalls-int-asm.S + +#### Introduction + +Only a single page table is used for all protection domains. A flat +memory model is used. Almost all linear-to-physical address mappings +are identity mappings, with the exceptions being the MMIO and metadata +regions. The X86 port of Contiki currently only supports at most one +MMIO and one metadata range per driver, and the paging-based +protection domain implementation always starts at particular linear +addresses when mapping an MMIO or metadata range. This may reduce +overhead, due to the way protection domain switches are implemented. + +#### System Call and Return Dispatching + +The system call dispatcher executes at ring level 0, since it uses the +privileged INVLPG or MOV CR3 instructions to invalidate TLB entries. +The dispatcher modifies page table entries to grant only the +permissions required by the protection domain being activated. It +then optionally uses the INVLPG instruction to invalidate any TLB +entries for any page table entries that were modified. If INVLPG is +not used to invalidate specific TLB entries, then CR3 is reloaded to +invalidate the entire TLB (global entries would be excluded, but they +are not used in this implementation). + +It is more efficient to always start at a particular linear address +when mapping an MMIO or metadata region, since the page table entries +for that region can be updated to unmap any previous region of that +type, map the new region, and then invalidated to cause the new +settings to take effect. The alternative using an identity +linear-to-physical address mapping for regions would be to unmap the +previous region by editing one set of page table entries and to then +map the new region by editing a different set of page table entries +and to finally perform invalidations for both sets of page table +entries. Another drawback of such an identity address mapping is that +additional page tables may need to be allocated to represent the +various MMIO regions, since page tables are indexed by linear address +and MMIO regions are often at high physical addresses. Note that this +is specific to MMIO regions, since metadata regions are not at +particularly high physical addresses. Additionally, if different base +linear addresses are used, it is necessary to communicate those to the +system call handler code so that the regions can be accessed. This +would require care to prevent an adversary from manipulating the +addresses and it may increase complexity. + +The overall process of handling a system call can be illustrated at a +high level as follows. Some minor steps are omitted in the interest +of clarity and brevity. + +``` + == BEGIN Client protection domain ========================================== + -- BEGIN Caller ------------------------------------------------------------ + 1. Call system call stub. + -- + 20. Continue execution... + -- END Caller -------------------------------------------------------------- + -- BEGIN System call stub -------------------------------------------------- + 2. Already in desired (server) protection domain? + - No: Issue software interrupt #100 to request system call. + - Yes: Jump to system call body. + -- END System call stub ---------------------------------------------------- + == END Client protection domain ============================================ + == BEGIN Ring level 0 ====================================================== + -- BEGIN System call dispatcher--------------------------------------------- + 3. Check that the requested system call is allowed. Get entrypoint. + 4. Check that the server protection domain is available (not yet present + in the protection domain call stack) and then mark it as busy. + 5. Save the caller return address from the main stack into the client + PDCS. + 6. Overwrite the caller return address on the main stack to point to + system call return stub. + 7. Push server protection domain onto protection domain call stack. + 8. Update the interrupt return stack EIP to start of system call body. + 9. Update and invalidate page table entries to grant only the permissions + required by the server protection domain. + 10. Update interrupt flag to disable interrupts, since interrupts are only + enabled in app protection domain, which exports no system calls. + 11. Perform interrupt return (IRET). + -- END System call dispatcher ---------------------------------------------- + -- BEGIN System call return dispatcher ------------------------------------- + 15. Mark protection domain on top of protection domain call stack as + available. + 16. Retrieve the caller return address from the kernel data structure for + the client protection domain and use it to overwrite the EIP in the + interrupt return stack. + 17. Update and invalidate page table entries to grant only the permissions + required by the client protection domain. + 18. Update interrupt flag to only enable interrupts if returning to app + protection domain cooperative scheduling context. + 19. Perform interrupt return (IRET). + -- END System call dispatcher ---------------------------------------------- + == END Ring level 0 ======================================================== + == BEGIN Server protection domain ========================================== + -- BEGIN System call body -------------------------------------------------- + 12. Execute the work for the requested system call. + 13. Return (to system call return stub, unless invoked from server + protection domain, in which case return is to caller). + -- END System call body ---------------------------------------------------- + -- BEGIN System call return stub ------------------------------------------- + 14. Issue software interrupt #101 to request system call return. + -- END System call return stub --------------------------------------------- + == END Server protection domain ============================================ +``` + +The first step in performing a system call is to invoke a system call +stub that actually issues the software interrupt to request a system +call dispatch. This approach reduces disruption to existing code, +since macros are used to generate separate stubs and corresponding +system call bodies with a single system call signature definition. + +#### Memory Layout + +The approximate memory layout of the system is depicted below, +starting with the highest physical addresses and proceeding to lower +physical addresses. Optional permissions are denoted with +parentheses. See cpu/x86/quarkX1000_paging.ld for details of how this +memory layout is implemented. + +``` + | Kernel | App | Other | + ... +--------+--------+--------+ + +------------------------------------------+ | | | | + | Domain X MMIO | | | | (RW) | + +------------------------------------------+ | | | | + ... | | | | + +------------------------------------------+ | | | | + | Domain X DMA-accessible metadata | | | | (RW) | + | (section .dma_bss) | | | | | + +------------------------------------------+ | | | | + +------------------------------------------+ | | | | + | Domain X metadata (section .meta_bss) | | | | (RW) | + +------------------------------------------+ | | | | + ... | | | | + +------------------------------------------+ | | | | + | Kernel-private data | | RW | | | + | (sections .prot_dom_bss, .gdt_bss, etc.) | | | | | + +------------------------------------------+ | | | | + +------------------------------------------+ | | | | + | System call data (section .syscall_bss) | | RW | R | R | + +------------------------------------------+ | | | | + +------------------------------------------+ | | | | + | Kernel-owned data (section .kern_bss) | | RW | R | R | + +------------------------------------------+ | | | | + +------------------------------------------+ | | | | + | Page-aligned, Kernel-owned data | | RW | R | R | + | (section .page_aligned_kern_bss) | | | | | + +------------------------------------------+ | | | | + +------------------------------------------+ | | | | + | Common data | | RW | RW | RW | + | (sections .data, .rodata*, .bss, etc.) | | | | | + +------------------------------------------+ | | | | + (not-present guard band page) | | | | + +------------------------------------------+ | | | | + | Exception stack | | RW | RW | RW | + | (section .exc_stack) | | | | | + +------------------------------------------+ | | | | + +------------------------------------------+ | | | | + | Interrupt stack | | RW | RW | RW | + | (section .int_stack) | | | | | + +------------------------------------------+ | | | | + +------------------------------------------+ | | | | + | Main stack (section .main_stack) | | RW | RW | RW | + +------------------------------------------+ | | | | + (not-present guard band page) | | | | + +------------------------------------------+ | | | | + | Main code (.text) | | RX | RX | RX | + +------------------------------------------+ | | | | + +------------------------------------------+ | | | | + | Bootstrap code (section .boot_text) | | | | | + +------------------------------------------+ | | | | + +------------------------------------------+ | | | | + | Multiboot header | | | | | + +------------------------------------------+ | | | | + ... +``` + +The only protection domain that is permitted to access kernel-owned +data is the kernel protection domain. Some devices can also be +instructed to perform DMA to kernel-owned data, although that is an +incorrect configuration. + +Paging only differentiates between memory accesses from ring 3 (user +level) and those from rings 0-2 (supervisor level). To avoid granting +code running in the preemptive scheduling context supervisory write +access to kernel data structures (including the page tables), those +structures are marked read-only (except when the kernel protection +domain is active) and the Write Protect (WP) bit in Control Register 0 +(CR0) is cleared only when it is necessary to update a write-protected +structure. Only ring 0 is allowed to modify CR0. + +Optional metadata for each protection domain is intended to only be +accessible from the associated protection domain and devices. + +Read accesses to executable code have not been observed to be needed +in at least a limited set of tests, but they are permitted, since +paging does not support an execute-only permission setting. On the +other hand, the Execute-Disable feature is used to prevent execution +of non-code memory regions. All non-startup code is mapped in all +protection domains. Limiting the code that is executable within each +protection domain to just the code that is actually needed within that +protection domain could improve the robustness of the system, but it +is challenging to determine all code that may be needed in a given +protection domain (e.g. all needed library routines). + +Stack accesses to non-stack memory are not needed, but they are +permitted. However, one page of unmapped linear address space is +placed above and below the stacks to detect erroneous stack accesses +to those linear address regions, which are the types of accesses most +likely to occur during a stack overflow or underflow condition. The +main stack is placed just below the interrupt stack, which is just +below the exception stack. Stack overflows are more common than stack +underflows, which motivates arranging the stacks such that an overflow +from a less-critical stack will not affect a more-critical stack. +Furthermore, the main stack is the most likely to overflow, since the +code that uses it is typically the most voluminous and difficult to +characterize. That provides additional motivation for positioning it +such that an overflow results in an immediate page fault. An +alternative design placing each stack on a separate group of +contiguous pages may improve the robustness of the system by +permitting the insertion of unmapped guard pages around them to +generate page faults in the event an overflow or underflow occurs on +any stack. However, that would consume additional memory. + +Data in the .rodata sections is marked read/write, even though it may +be possible to improve the robustness of the system by marking that +data as read-only. Doing so would introduce additional complexity +into the system. + +### Hardware-Switched Segment-Based Protection Domains + +Primary implementation sources: + + - cpu/x86/mm/tss-prot-domains.c + - cpu/x86/mm/tss-prot-domains-asm.S + +#### Introduction + +One TSS is allocated for each protection domain. Each one is +associated with its own dedicated LDT. The memory resources assigned +to each protection domain are represented as segment descriptors in +the LDT for the protection domain. Additional shared memory resources +are represented as segment descriptors in the GDT. + +#### System Call and Return Dispatching + +The system call dispatcher runs in the context of the server +protection domain. It is a common piece of code that is shared among +all protection domains. Thus, each TSS, except the application TSS, +has its EIP field initialized to the entrypoint for the system call +dispatcher so that will be the first code to run when the first switch +to that task is performed. + +The overall process of handling a system call can be illustrated at a +high level as follows. Some minor steps are omitted from this +illustration in the interest of clarity and brevity. + +``` + == BEGIN Client protection domain ========================================== + -- BEGIN Caller ------------------------------------------------------------ + 1. Call system call stub. + -- + 13. Continue execution... + -- END Caller -------------------------------------------------------------- + -- BEGIN System call stub -------------------------------------------------- + 2. Already in desired (server) protection domain? + - No: Request task switch to server protection domain. + - Yes: Jump to system call body. + -- + 12. Return to caller. + -- END System call stub ---------------------------------------------------- + == END Client protection domain ============================================ + == BEGIN Server protection domain ========================================== + -- BEGIN System call dispatcher--------------------------------------------- + 3. Check that the requested system call is allowed. Get entrypoint. + 4. Switch to the main stack. + 5. Pop the client return address off the stack to a callee-saved register. + 6. Push the address of the system call return dispatcher onto the stack. + 7. Jump to system call body. + -- + 10. Restore the client return address to the stack. + 11. Request task switch to client protection domain. + -- END System call dispatcher ---------------------------------------------- + -- BEGIN System call body -------------------------------------------------- + 8. Execute the work for the requested system call. + 9. Return (to system call return stub, unless invoked from server + protection domain, in which case return is to caller). + -- END System call body ---------------------------------------------------- + == END Server protection domain ============================================ +``` + +An additional exception handler is needed, for the "Device Not +Available" exception. The handler comprises just a CLTS and an IRET +instruction. The CLTS instruction is privileged, which is why it must +be run at ring level 0. This exception handler is invoked when a +floating point instruction is used following a task switch, and its +sole purpose is to enable the floating point instruction to execute +after the exception handler returns. See the TSS resources listed +above for more details regarding interactions between task switching +and floating point instructions. + +Each segment register may represent a different data region within +each protection domain, although the FS register is used for two +separate purposes at different times. The segments are defined as +follows: + + - CS (code segment) maps all non-startup code with execute-only + permissions in all protection domains. Limiting the code that is + executable within each protection domain to just the code that is + actually needed within that protection domain could improve the + robustness of the system, but it is challenging to determine all + code that may be needed in a given protection domain (e.g. all + needed library routines). Furthermore, that code may not all be + contiguous, and each segment descriptor can only map a contiguous + memory region. Finally, segment-based memory addressing is + relative to an offset of zero from the beginning of each segment, + introducing additional complexity if such fine-grained memory + management were to be used. + - DS (default data segment) typically maps the main stack and all + non-stack data memory that is accessible from all protection + domains. Limiting the data that is accessible via DS within each + protection domain to just the subset of the data that is actually + needed within that protection domain could improve the robustness + of the system, but it is challenging for similar reasons to those + that apply to CS. Access to the main stack via DS is supported so + that code that copies the stack pointer to a register and attempts + to access stack entries via DS works correctly. Disallowing access + to the main stack via DS could improve the robustness of the + system, but that may require modifying code that expects to be able + to access the stack via DS. + - ES is loaded with the same segment descriptor as DS so that string + operations (e.g. the MOVS instruction) work correctly. + - FS usually maps the kernel-owned data region. That region can only + be written via FS in the kernel protection domain. FS contains a + descriptor specifying a read-only mapping in all other protection + domains except the application protection domain, in which FS is + nullified. Requiring that code specifically request access to the + kernel-owned data region by using the FS segment may improve the + robustness of the system by blocking undesired accesses to the + kernel-owned data region via memory access instructions within the + kernel protection domain that implicitly access DS. The reason for + granting read-only access to the kernel-owned data region from most + protection domains is that the system call dispatcher runs in the + context of the server protection domain to minimize overhead, and + it requires access to the kernel-owned data region. It may improve + the robustness of the system to avoid this by running the system + call dispatcher in a more-privileged ring level (e.g. ring 1) + within the protection domain and just granting access to the + kernel-owned data region from that ring. However, that would + necessitate a ring level transition to ring 3 when dispatching the + system call, which would increase overhead. The application + protection domain does not export any system calls, so it does not + require access to the kernel-owned data region. + - FS is temporarily loaded with a segment descriptor that maps just + an MMIO region used by a driver protection domain when such a + driver needs to perform MMIO accesses. + - GS maps an optional region of readable and writable metadata that + can be associated with a protection domain. In protection domains + that are not associated with metadata, GS is nullified. + - SS usually maps just the main stack. This may improve the + robustness of the system by enabling immediate detection of stack + underflows and overflows rather than allowing such a condition to + result in silent data corruption. Interrupt handlers use a stack + segment that covers the main stack and also includes a region above + the main stack that is specifically for use by interrupt handlers. + In like manner, exception handlers use a stack segment that covers + both of the other stacks and includes an additional region. This + is to support the interrupt dispatchers that copy parameters from + the interrupt-specific stack region to the main stack prior to + pivoting to the main stack to execute an interrupt handler body. + +The approximate memory layout of the system is depicted below, +starting with the highest physical addresses and proceeding to lower +physical addresses. The memory ranges that are mapped at various +times by each of the segment registers are also depicted. Read the +descriptions of each segment above for more information about what +memory range may be mapped by each segment register at various times +with various protection domain configurations. Parenthetical notes +indicate the protection domains that can use each mapping. The suffix +[L] indicates that the descriptor is loaded from LDT. Optional +mappings are denoted by a '?' after the protection domain label. The +'other' protection domain label refers to protection domains other +than the application and kernel domains. + +``` + ... + +------------------------------------------+ \ + | Domain X MMIO | +- FS[L] + +------------------------------------------+ / (other?) + ... + +------------------------------------------+ \ + | Domain X DMA-accessible metadata | +- GS[L] (other?) + | (section .dma_bss) | | + +------------------------------------------+ / + +------------------------------------------+ \ + | Domain X metadata (section .meta_bss) | +- GS[L] (other?) + +------------------------------------------+ / + ... + +------------------------------------------+ \ + | Kernel-private data | | + | (sections .prot_dom_bss, .gdt_bss, etc.) | +- FS[L] (kern) + +------------------------------------------+ | + +------------------------------------------+ \ + | System call data (section .syscall_bss) | | + +------------------------------------------+ +- FS[L] (all) + +------------------------------------------+ | + | Kernel-owned data (section .kern_bss) | | + +------------------------------------------+ / + +------------------------------------------+ \ + | Common data | | + | (sections .data, .rodata*, .bss, etc.) | | + +------------------------------------------+ +- DS, ES + +------------------------------------------+ \ | (all) + | Exception stack (section .exc_stack) | | | + |+----------------------------------------+| \ | + || Interrupt stack (section .int_stack) || | | + ||+--------------------------------------+|| \ | + ||| Main stack (section .main_stack) ||| +- SS (all) | + +++--------------------------------------+++ / / + +------------------------------------------+ \ + | Main code (.text) | +- CS (all) + +------------------------------------------+ / + +------------------------------------------+ + | Bootstrap code (section .boot_text) | + +------------------------------------------+ + +------------------------------------------+ + | Multiboot header | + +------------------------------------------+ + ... +``` + +This memory layout is more efficient than the layout that is possible +with paging-based protection domains, since segments have byte +granularity, whereas the minimum unit of control supported by paging +is a 4KiB page. For example, this means that metadata may need to be +padded to be a multiple of the page size. This may also permit +potentially-undesirable accesses to padded areas of code and data +regions that do not entirely fill the pages that they occupy. + +Kernel data structure access, including to the descriptor tables +themselves, is normally restricted to the code running at ring level +0, specifically the exception handlers and the system call and return +dispatchers. It is also accessible from the cooperative scheduling +context in the kernel protection domain. Interrupt delivery is +disabled in the kernel protection domain, so the preemptive scheduling +context is not used. + +SS, DS, and ES all have the same base address, since the compiler may +assume that a flat memory model is in use. Memory accesses that use a +base register of SP/ESP or BP/EBP or that are generated by certain +other instructions (e.g. PUSH, RET, etc.) are directed to SS by +default, whereas other accesses are directed to DS or ES by default. +The compiler may use an instruction that directs an access to DS or ES +even if the data being accessed is on the stack, which is why these +three segments must use the same base address. However, it is +possible to use a lower limit for SS than for DS and ES for the +following reasons. Compilers commonly provide an option for +preventing the frame pointer, EBP, from being omitted and possibly +used to point to non-stack data. In our tests, compilers never used +ESP to point to non-stack data. + +Each task switch ends up saving and restoring more state than is +actually useful to us, but the implementation attempts to minimize +overhead by configuring the register values in each TSS to reduce the +number of register loads that are needed in the system call +dispatcher. Specifically, two callee-saved registers are populated +with base addresses used when computing addresses in the entrypoint +information table as well as a mask corresponding to the ID of the +server protection domain that is used to check whether the requested +system call is exported by the server protection domain. Callee-saved +registers are used, since the task return will update the saved +register values. + +Note that this implies that the intervening code run between the task +call and return can modify critical data used by the system call +dispatcher. However, this is analogous to the considerations +associated with sharing a single stack amongst all protection domains +and should be addressed similarly, by only invoking protection domains +that are trusted by the caller to not modify the saved critical +values. This consideration is specific to the TSS-based dispatcher +and is not shared by the ring 0 dispatcher used in the other +plugins. + +Data in the .rodata sections is marked read/write, even though it may +be possible to improve the robustness of the system by marking that +data as read-only. Doing so would introduce even more complexity into +the system than would be the case with paging-based protection +domains, since it would require allocating different segment +descriptors for the read-only vs. the read/write data. + +#### Supporting Null-Pointer Checks + +A lot of code considers a pointer value of 0 to be invalid. However, +segment offsets always start at 0. To accommodate the common software +behavior, at least the first byte of each segment is marked as +unusable. An exception to this is that the first byte of the stack +segments is usable. + +#### Interrupt and Exception Dispatching + +A distinctive challenge that occurs during interrupt and exception +dispatching is that the state of the segment registers when an +interrupt or exception occurs is somewhat unpredictable. For example, +an exception may occur while MMIO is being performed, meaning that FS +is loaded with the MMIO descriptor instead of the kernel descriptor. +Leaving the segment registers configured in that way could cause +incorrect interrupt or exception handler behavior. Thus, the +interrupt or exception dispatcher must save the current segment +configuration, switch to a configuration that is suitable for the +handler body, and then restore the saved segment configuration after +the handler body returns. Another motivation for this is that the +interrupted code may have corrupted the segment register configuration +in an unexpected manner, since segment register load instructions are +unprivileged. Similar segment register updates must be performed for +similar reasons when dispatching system calls. + +### Software-Switched Segment-Based Protection Domains + +Primary implementation sources: + + - cpu/x86/mm/swseg-prot-domains.c + +The requirement to allocate a TSS for each protection domain in the +hardware-switched segments plugin may consume a substantial amount of +space, since the size of each TSS is fixed by hardware to be at least +104 bytes. The software-switched segments plugin saves space by +defining a more compact PDCS. However, the layout and definitions of +the segments is identical to what was described above for the +hardware-switched segments plugin. + +The system call and return procedure is mostly identical to that for +paging-based protection domains. However, instead of updating and +invalidating page tables, the dispatchers update the LDT and some of +the segment registers. + +### Pointer Validation + +Primary implementation sources: + - cpu/x86/mm/syscalls.h + +At the beginning of each system call routine, it is necessary to check +that any untrusted pointer that could have been influenced by a caller +(i.e. a stack parameter or global variable) refers to a location above +the return address and to halt otherwise. This is to prevent a +protection domain from calling a different protection domain and +passing a pointer that references a location in the callee's stack +other than its parameters to influence the execution of the callee in +an unintended manner. For example, if an incoming pointer referenced +the return address, it could potentially redirect execution with the +privileges of the callee protection domain. + +When the paging-based plugin is in use, it is also necessary to check +that the pointer is either within the stack region or the shared data +region (or a guard band region, since that will generate a fault) to +prevent redirection of data accesses to MMIO or metadata regions. The +other plugins already configure segments to restrict accesses to DS to +just those regions. Pointers provided as inputs to system calls as +defined above should never be dereferenced in any segment other than +DS. + +The pointer is both validated and copied to a new storage location, +which must be within the callee's local stack region (excluding the +parameter region). This is to mitigate scenarios such as two pointers +being validated and an adversary later inducing a write through one of +the pointers to the other pointer to corrupt the latter pointer before +it is used. + +Any pointer whose value is fixed at link or load time does not need to +be validated prior to use, since no adversary within the defined +threat model is able to influence the link or load process. + +### DMA Restrictions + +Primary implementation sources: + - cpu/x86/drivers/quarkX1000/imr.c + - cpu/x86/drivers/quarkX1000/imr-conf.c + +The CPU is not the only agent with the ability to issue requests to +the interconnect within the SoC. For example, SoC peripherals such as +the Ethernet driver use DMA to efficiently access memory buffers. +This could introduce a risk that DMA could be used to bypass the +memory protections enforced on the CPU by segmentation or paging. For +example, a device driver could instruct a device to access a memory +region to which the kernel has not granted the driver's protection +domain permission to access. + +The Isolated Memory Region (IMR) feature is configured to restrict the +memory that can be accessed by system agents other than the CPU [3]. +It only allows those system agents to access portions of the Contiki +memory space that are specifically intended to be used with DMA. The +source code for each protection domain specifies that its optional +metadata region needs to be accessible from other system agents +besides the CPU by using ATTR_BSS_DMA instead of ATTR_BSS_META when +allocating storage for the metadata. + +Extending the Framework +----------------------- + +### Adding a New Protection Domain + +The following steps are required. See the existing device drivers for +examples of various types of protection domains and how they are +initialized. + + - Allocate storage for the PDCS and the corresponding + client-accessible data structure using the PROT_DOMAINS_ALLOC + macro. + - Apply the ATTR_BSS_META attribute to the metadata structure, if + applicable. Apply the ATTR_BSS_DMA attribute instead if the + metadata structure needs to be DMA-accessible. Pad the metadata + structure to completely fill an integer multiple of the minimum + page size, 4096, when paging-based protection domains are in use. + See the definition of quarkX1000_eth_meta_t for an example. + - Perform the following steps during boot stage 2: + - Initialize the protection domain ID in the client-accessible data + structure using the PROT_DOMAINS_INIT_ID macro. + - Register the domain. See prot-domains.c:prot_domains_init for an + example of registering a non-driver protection domain. See + cpu/x86/drivers/quarkX1000/eth.c:quarkX1000_eth_init for an + example of registering a PCI driver protection domain with an + MMIO region and a metadata region. + +### Adding a New System Call + +The following steps are required: + + - Define the system call procedure using the SYSCALLS_DEFINE or + SYSCALLS_DEFINE_SINGLETON macro. See + cpu/x86/drivers/legacy_pc/uart-16x50.c:uart_16x50_tx for an example + of a non-singleton system call. See + cpu/x86/drivers/quarkX1000/eth.c:quarkX1000_eth_send for an example + of a singleton system call. A singleton system call is one for + which at most one server protection domain will be associated with + it. + - During boot phase 2, associate the system call with one or more + server protection domains using the SYSCALLS_AUTHZ macro. + +Usage +----- + +To enable protection domain support, add "X86_CONF_PROT_DOMAINS=" to +the command line and specify one of the following options: + + - paging + - tss + - swseg + +The paging option accepts a sub-option to determine whether the TLB is +fully- or selectively-invalidated during protection domain switches. +By default, full invalidation is selected. Set the +X86_CONF_USE_INVLPG variable to 1 to override the default. + +References +---------- + +[1] J. H. Saltzer, "Protection and the Control of Information Sharing + in Multics," Commun. ACM, vol. 17, no. 7, pp. 388-402, Jul. 1974. + +[2] https://github.com/contiki-os/contiki/wiki/Processes + +[3] "Intel(R) Quark(TM) SoC X1000 Secure Boot Programmer's Reference + Manual," + http://www.intel.com/support/processors/quark/sb/CS-035228.htm diff --git a/cpu/x86/mm/gdt-layout.h b/cpu/x86/mm/gdt-layout.h new file mode 100644 index 000000000..b79c2b9ca --- /dev/null +++ b/cpu/x86/mm/gdt-layout.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_MM_GDT_LAYOUT_H_ +#define CPU_X86_MM_GDT_LAYOUT_H_ + +#include "prot-domains.h" + +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING +/** + * Number of fixed GDT descriptors. Additional descriptors may be defined + * outside of gdt.c. + */ +#define GDT_NUM_FIXED_DESC 7 +#elif X86_CONF_PROT_DOMAINS_MULTI_SEG +#define GDT_NUM_FIXED_DESC 11 +#else +#define GDT_NUM_FIXED_DESC 3 +#endif + +#define GDT_IDX_NULL 0 +/** + * Flat code segment, used at boot and also for the rest of the system's + * runtime when protection domains are disabled + */ +#define GDT_IDX_CODE_FLAT 1 +/** + * Flat data segment, used at boot and also for the rest of the system's + * runtime when protection domains are disabled + */ +#define GDT_IDX_DATA_FLAT 2 + +#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__NONE +/** Default (post-boot) code segment */ +#define GDT_IDX_CODE 3 +/** + * Same bounds and permissions as default code segment, but at the interrupt + * handler privilege level + */ +#define GDT_IDX_CODE_INT 4 +/** Stack segment for interrupt handlers */ +#define GDT_IDX_STK_INT 5 + +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING +#define GDT_IDX_CODE_EXC GDT_IDX_CODE_FLAT +/** Default data segment used by code at all privilege levels */ +#define GDT_IDX_DATA 6 +#define GDT_IDX_STK GDT_IDX_DATA +#define GDT_IDX_STK_EXC GDT_IDX_DATA_FLAT +#else +/** + * Same bounds and permissions as default code segment, but at the exception + * handler privilege level + */ +#define GDT_IDX_CODE_EXC 6 +/** R/W kernel data descriptor used during boot stage 1 */ +#define GDT_IDX_DATA_KERN_EXC 7 +/** Default data segment used by code at all privilege levels */ +#define GDT_IDX_DATA 8 +/** + * Default stack segment, which overlaps with the beginning of the default data + * segment + */ +#define GDT_IDX_STK 9 +/** Stack segment for exception handlers */ +#define GDT_IDX_STK_EXC 10 + +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS +#define GDT_IDX_TSS(dom_id) (GDT_NUM_FIXED_DESC + (2 * (dom_id))) +#define GDT_IDX_LDT(dom_id) (GDT_NUM_FIXED_DESC + (2 * (dom_id)) + 1) +#else +#define GDT_IDX_LDT(dom_id) (GDT_NUM_FIXED_DESC + (dom_id)) +#endif + +#endif +#else +#define GDT_IDX_CODE GDT_IDX_CODE_FLAT +#define GDT_IDX_CODE_INT GDT_IDX_CODE_FLAT +#define GDT_IDX_CODE_EXC GDT_IDX_CODE_FLAT +#define GDT_IDX_DATA GDT_IDX_DATA_FLAT +#define GDT_IDX_STK GDT_IDX_DATA_FLAT +#define GDT_IDX_STK_INT GDT_IDX_DATA_FLAT +#define GDT_IDX_STK_EXC GDT_IDX_DATA_FLAT +#endif + +#define GDT_SEL(idx, rpl) (((idx) << 3) | (rpl)) + +#define DT_SEL_GET_IDX(sel) ((sel) >> 3) + +#define DT_SEL_GET_RPL(sel) ((sel) & 3) + +#define GDT_SEL_NULL GDT_SEL(GDT_IDX_NULL, 0) +#define GDT_SEL_CODE_FLAT GDT_SEL(GDT_IDX_CODE_FLAT, PRIV_LVL_EXC) +#define GDT_SEL_DATA_FLAT GDT_SEL(GDT_IDX_DATA_FLAT, PRIV_LVL_EXC) + +#define GDT_SEL_CODE GDT_SEL(GDT_IDX_CODE, PRIV_LVL_USER) +#define GDT_SEL_CODE_INT GDT_SEL(GDT_IDX_CODE_INT, PRIV_LVL_INT) +#define GDT_SEL_CODE_EXC GDT_SEL(GDT_IDX_CODE_EXC, PRIV_LVL_EXC) + +#define GDT_SEL_DATA GDT_SEL(GDT_IDX_DATA, PRIV_LVL_EXC) +#define GDT_SEL_DATA_KERN_EXC GDT_SEL(GDT_IDX_DATA_KERN_EXC, PRIV_LVL_EXC) + +#define GDT_SEL_STK GDT_SEL(GDT_IDX_STK, PRIV_LVL_USER) +#define GDT_SEL_STK_INT GDT_SEL(GDT_IDX_STK_INT, PRIV_LVL_INT) +#define GDT_SEL_STK_EXC GDT_SEL(GDT_IDX_STK_EXC, PRIV_LVL_EXC) + +#define GDT_SEL_TSS(dom_id) GDT_SEL(GDT_IDX_TSS(dom_id), PRIV_LVL_USER) +#define GDT_SEL_LDT(dom_id) GDT_SEL(GDT_IDX_LDT(dom_id), PRIV_LVL_USER) + +#endif /* CPU_X86_MM_GDT_LAYOUT_H_ */ + diff --git a/cpu/x86/mm/ldt-layout.h b/cpu/x86/mm/ldt-layout.h new file mode 100644 index 000000000..7c61054a5 --- /dev/null +++ b/cpu/x86/mm/ldt-layout.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_MM_LDT_LAYOUT_H_ +#define CPU_X86_MM_LDT_LAYOUT_H_ + +#include "gdt-layout.h" + +/* Each LDT can contain up to this many descriptors, but some protection + * domains may not use all of the slots. + */ +#define LDT_NUM_DESC 3 + +/** + * Provides access to kernel data. Most protection domains are granted at most + * read-only access, but the kernel protection domain is granted read/write + * access. + */ +#define LDT_IDX_KERN 0 +/** Maps a device MMIO range */ +#define LDT_IDX_MMIO 1 +/** Maps domain-defined metadata */ +#define LDT_IDX_META 2 + +#define LDT_SEL(idx, rpl) (GDT_SEL(idx, rpl) | (1 << 2)) + +#define LDT_SEL_KERN LDT_SEL(LDT_IDX_KERN, PRIV_LVL_USER) +#define LDT_SEL_MMIO LDT_SEL(LDT_IDX_MMIO, PRIV_LVL_USER) +#define LDT_SEL_META LDT_SEL(LDT_IDX_META, PRIV_LVL_USER) +#define LDT_SEL_STK LDT_SEL(LDT_IDX_STK, PRIV_LVL_USER) + +#endif /* CPU_X86_MM_LDT_LAYOUT_H_ */ diff --git a/cpu/x86/mm/multi-segment.c b/cpu/x86/mm/multi-segment.c new file mode 100644 index 000000000..6d3fd57f1 --- /dev/null +++ b/cpu/x86/mm/multi-segment.c @@ -0,0 +1,248 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gdt.h" +#include "helpers.h" +#include "prot-domains.h" +#include "segmentation.h" +#include "stacks.h" + +/*---------------------------------------------------------------------------*/ +static uint32_t +segment_desc_compute_base(segment_desc_t desc) +{ + return (desc.base_hi << 24) | (desc.base_mid << 16) | desc.base_lo; +} +/*---------------------------------------------------------------------------*/ +void +prot_domains_reg_multi_seg(volatile struct dom_kern_data ATTR_KERN_ADDR_SPACE *dkd, + uintptr_t mmio, size_t mmio_sz, + uintptr_t meta, size_t meta_sz) +{ + segment_desc_t desc; + dom_id_t dom_id = PROT_DOMAINS_GET_DOM_ID(dkd); + uint32_t kern_data_len; + uint32_t tmp; + + if((dkd < prot_domains_kern_data) || + (prot_domains_kern_data_end <= dkd) || + (((((uintptr_t)dkd) - (uintptr_t)prot_domains_kern_data) % + sizeof(dom_kern_data_t)) != 0)) { + halt(); + } + + KERN_READL(tmp, dkd->ldt[DT_SEL_GET_IDX(LDT_SEL_KERN)].raw_hi); + if(tmp != 0) { + /* This PDCS was previously initialized, which is disallowed. */ + halt(); + } + + /* Initialize descriptors */ + + if(dom_id == DOM_ID_kern) { + kern_data_len = (uint32_t)&_ebss_kern_addr; + } else { + /* Non-kernel protection domains do not need to access the protection + * domain control structures, and they may contain saved register values + * that are private to each domain. + */ + kern_data_len = (uint32_t)&_ebss_syscall_addr; + } + kern_data_len -= (uint32_t)&_sbss_kern_addr; + + segment_desc_init(&desc, (uint32_t)&_sbss_kern_addr, kern_data_len, + /* Every protection domain requires at least read-only access to kernel + data to read dom_client_data structures and to support the system call + dispatcher, if applicable. Only the kernel protection domain is granted + read/write access to the kernel data. */ + ((dom_id == DOM_ID_kern) ? + SEG_TYPE_DATA_RDWR : + SEG_TYPE_DATA_RDONLY) | + SEG_FLAG(DPL, PRIV_LVL_USER) | + SEG_GRAN_BYTE | SEG_DESCTYPE_NSYS); + + KERN_WRITEL(dkd->ldt[LDT_IDX_KERN].raw_lo, desc.raw_lo); + KERN_WRITEL(dkd->ldt[LDT_IDX_KERN].raw_hi, desc.raw_hi); + + if(mmio_sz != 0) { + if(SEG_MAX_BYTE_GRAN_LEN < mmio_sz) { + halt(); + } + + segment_desc_init(&desc, mmio, mmio_sz, + SEG_FLAG(DPL, PRIV_LVL_USER) | SEG_GRAN_BYTE | + SEG_DESCTYPE_NSYS | SEG_TYPE_DATA_RDWR); + } else { + desc.raw = SEG_DESC_NOT_PRESENT; + } + + KERN_WRITEL(dkd->ldt[LDT_IDX_MMIO].raw_lo, desc.raw_lo); + KERN_WRITEL(dkd->ldt[LDT_IDX_MMIO].raw_hi, desc.raw_hi); + + if(meta_sz != 0) { + if(SEG_MAX_BYTE_GRAN_LEN < meta_sz) { + halt(); + } + + segment_desc_init(&desc, meta, meta_sz, + SEG_FLAG(DPL, PRIV_LVL_USER) | SEG_GRAN_BYTE | + SEG_DESCTYPE_NSYS | SEG_TYPE_DATA_RDWR); + } else { + desc.raw = SEG_DESC_NOT_PRESENT; + } + + KERN_WRITEL(dkd->ldt[LDT_IDX_META].raw_lo, desc.raw_lo); + KERN_WRITEL(dkd->ldt[LDT_IDX_META].raw_hi, desc.raw_hi); + + segment_desc_init(&desc, + KERN_DATA_OFF_TO_PHYS_ADDR(dkd->ldt), + sizeof(dkd->ldt), + SEG_FLAG(DPL, PRIV_LVL_USER) | SEG_GRAN_BYTE | + SEG_DESCTYPE_SYS | SEG_TYPE_LDT); + gdt_insert(GDT_IDX_LDT(dom_id), desc); +} +/*---------------------------------------------------------------------------*/ +void +prot_domains_gdt_init() +{ + int i; + segment_desc_t desc; + + segment_desc_init(&desc, + (uint32_t)&_stext_addr, + ((uint32_t)&_etext_addr) - (uint32_t)&_stext_addr, + SEG_FLAG(DPL, PRIV_LVL_EXC) | SEG_GRAN_BYTE | + SEG_DESCTYPE_NSYS | +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG + /* The general protection fault handler requires read access to CS */ + SEG_TYPE_CODE_EXRD +#else + SEG_TYPE_CODE_EX +#endif + ); + gdt_insert_boot(GDT_IDX_CODE_EXC, desc); + + segment_desc_init(&desc, + (uint32_t)&_sdata_addr, + ((uint32_t)&_edata_addr) - (uint32_t)&_sdata_addr, + SEG_FLAG(DPL, PRIV_LVL_USER) | SEG_GRAN_BYTE | + SEG_DESCTYPE_NSYS | SEG_TYPE_DATA_RDWR); + gdt_insert_boot(GDT_IDX_DATA, desc); + + segment_desc_init(&desc, + (uint32_t)&_sbss_kern_addr, + ((uint32_t)&_ebss_kern_addr) - + (uint32_t)&_sbss_kern_addr, + SEG_FLAG(DPL, PRIV_LVL_EXC) | SEG_GRAN_BYTE | + SEG_DESCTYPE_NSYS | SEG_TYPE_DATA_RDWR); + gdt_insert_boot(GDT_IDX_DATA_KERN_EXC, desc); + + segment_desc_init(&desc, + (uint32_t)DATA_OFF_TO_PHYS_ADDR(stacks_main), + STACKS_SIZE_MAIN, + SEG_FLAG(DPL, PRIV_LVL_USER) | SEG_GRAN_BYTE | + SEG_DESCTYPE_NSYS | SEG_TYPE_DATA_RDWR); + gdt_insert_boot(GDT_IDX_STK, desc); + + segment_desc_set_limit(&desc, STACKS_SIZE_MAIN + STACKS_SIZE_INT); + SEG_SET_FLAG(desc, DPL, PRIV_LVL_INT); + gdt_insert_boot(GDT_IDX_STK_INT, desc); + + segment_desc_set_limit(&desc, + STACKS_SIZE_MAIN + + STACKS_SIZE_INT + + STACKS_SIZE_EXC); + SEG_SET_FLAG(desc, DPL, PRIV_LVL_EXC); + gdt_insert_boot(GDT_IDX_STK_EXC, desc); + + /* Not all domains will necessarily be initialized, so this initially marks + * all per-domain descriptors not-present. + */ + desc.raw = SEG_DESC_NOT_PRESENT; + for(i = 0; i < PROT_DOMAINS_ACTUAL_CNT; i++) { +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS + gdt_insert_boot(GDT_IDX_TSS(i), desc); +#endif + gdt_insert_boot(GDT_IDX_LDT(i), desc); + } + + __asm__ __volatile__ ( + "mov %[_default_data_], %%ds\n\t" + "mov %[_default_data_], %%es\n\t" + "mov %[_kern_data_], %%" SEG_KERN "s\n\t" + : + : [_default_data_] "r"(GDT_SEL_DATA), + [_kern_data_] "r"(GDT_SEL_DATA_KERN_EXC)); +} +/*---------------------------------------------------------------------------*/ +void +multi_segment_launch_kernel(void) +{ + /* Update segment registers. */ + __asm__ __volatile__ ( + "mov %[_data_seg_], %%ds\n\t" + "mov %[_data_seg_], %%es\n\t" + "mov %[_kern_seg_], %%" SEG_KERN "s\n\t" + "mov %[_data_seg_], %%" SEG_META "s\n\t" + : + : [_data_seg_] "r" (GDT_SEL_DATA), + [_kern_seg_] "r" (LDT_SEL_KERN) + ); +} +/*---------------------------------------------------------------------------*/ +void +prot_domains_enable_mmio(void) +{ + __asm__ __volatile__ ("mov %0, %%" SEG_MMIO "s" :: "r" (LDT_SEL_MMIO)); +} +/*---------------------------------------------------------------------------*/ +void +prot_domains_disable_mmio(void) +{ + __asm__ __volatile__ ("mov %0, %%" SEG_KERN "s" :: "r" (LDT_SEL_KERN)); +} +/*---------------------------------------------------------------------------*/ +uintptr_t +prot_domains_lookup_meta_phys_base(dom_client_data_t ATTR_KERN_ADDR_SPACE *drv) +{ + dom_id_t dom_id; + segment_desc_t desc; + volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE *dkd; + + KERN_READL(dom_id, drv->dom_id); + + dkd = prot_domains_kern_data + dom_id; + + KERN_READL(desc.raw_lo, dkd->ldt[DT_SEL_GET_IDX(LDT_SEL_META)].raw_lo); + KERN_READL(desc.raw_hi, dkd->ldt[DT_SEL_GET_IDX(LDT_SEL_META)].raw_hi); + + return segment_desc_compute_base(desc); +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/mm/multi-segment.h b/cpu/x86/mm/multi-segment.h new file mode 100644 index 000000000..baa28002b --- /dev/null +++ b/cpu/x86/mm/multi-segment.h @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_MM_MULTI_SEGMENT_H_ +#define CPU_X86_MM_MULTI_SEGMENT_H_ + +#include +#include +#include "helpers.h" +#include "ldt-layout.h" + +#ifdef __clang__ +#define __SEG_FS +#define __seg_fs __attribute__((address_space(257))) +#define __SEG_GS +#define __seg_gs __attribute__((address_space(256))) +#endif + +#ifdef __SEG_FS +#define ATTR_MMIO_ADDR_SPACE __seg_fs +#define ATTR_KERN_ADDR_SPACE __seg_fs +#else +#define ATTR_KERN_ADDR_SPACE +#endif +#ifdef __SEG_GS +#define ATTR_META_ADDR_SPACE __seg_gs +#endif + +void prot_domains_reg_multi_seg(volatile struct dom_kern_data ATTR_KERN_ADDR_SPACE *dkd, + uintptr_t mmio, size_t mmio_sz, + uintptr_t meta, size_t meta_sz); +void multi_segment_launch_kernel(void); + +#define MULTI_SEGMENT_ENTER_ISR(exc) \ + "mov $" EXP_STRINGIFY(GDT_SEL_DATA) ", %%eax\n\t" \ + /* Refresh DS and ES in case the userspace code corrupted them. */ \ + "mov %%eax, %%ds\n\t" \ + "mov %%eax, %%es\n\t" \ + /* Refresh SEG_KERN. */ \ + "mov $" EXP_STRINGIFY(LDT_SEL_KERN) ", %%eax\n\t" \ + "mov %%eax, %%" SEG_KERN "s\n\t" \ + ".if " #exc "\n\t" \ + /* It is possible that a routine performing MMIO is being interrupted. */ \ + /* Thus, it is necessary to save and restore the MMIO segment register */ \ + /* (in a callee-saved register). */ \ + "mov %%" SEG_MMIO "s, %%ebp\n\t" \ + "mov $" EXP_STRINGIFY(GDT_SEL_DATA_KERN_EXC) ", %%eax\n\t" \ + "mov %%eax, %%" SEG_KERN "s\n\t" \ + ".endif\n\t" +#define MULTI_SEGMENT_LEAVE_ISR(exc) \ + ".if " #exc "\n\t" \ + "mov %%ebp, %%" SEG_MMIO "s\n\t" \ + ".endif\n\t" + +/** + * The MMIO region is tightly bounded within a segment, so its base offset is + * always 0. + */ +#define PROT_DOMAINS_MMIO(dcd) 0 +/** + * The metadata region is tightly bounded within a segment, so its base offset + * is always 0. + */ +#define PROT_DOMAINS_META(dcd) 0 + +#define SEG_MMIO "f" /**< For MMIO accesses, when enabled. */ +#define SEG_KERN "f" /**< For kernel data accesses */ +#define SEG_META "g" /**< For metadata accesses */ + +#define _SEG_READL(seg, dst, src) \ + __asm__ __volatile__ ( \ + "movl %%" seg "s:%[src_], %[dst_]" : [dst_]"=r"(dst) : [src_]"m"(src)) + +#define _SEG_READW(seg, dst, src) \ + __asm__ __volatile__ ( \ + "movw %%" seg "s:%[src_], %[dst_]" : [dst_]"=r"(dst) : [src_]"m"(src)) + +#define _SEG_READB(seg, dst, src) \ + __asm__ __volatile__ ( \ + "movb %%" seg "s:%[src_], %[dst_]" : [dst_]"=q"(dst) : [src_]"m"(src)) + +#define _SEG_WRITEL(seg, dst, src) \ + __asm__ __volatile__ ( \ + "movl %[src_], %%" seg "s:%[dst_]" \ + : [dst_]"=m"(dst) : [src_]"r"((uint32_t)(src))) + +#define _SEG_WRITEW(seg, dst, src) \ + __asm__ __volatile__ ( \ + "movw %[src_], %%" seg "s:%[dst_]" \ + : [dst_]"=m"(dst) : [src_]"r"((uint16_t)(src))) + +#define _SEG_WRITEB(seg, dst, src) \ + __asm__ __volatile__ ( \ + "movb %[src_], %%" seg "s:%[dst_]" \ + : [dst_]"=m"(dst) : [src_]"q"((uint8_t)(src))) + +#ifndef __SEG_FS +#define MMIO_READL(dst, src) _SEG_READL(SEG_MMIO, dst, src) +#define MMIO_READW(dst, src) _SEG_READW(SEG_MMIO, dst, src) +#define MMIO_READB(dst, src) _SEG_READB(SEG_MMIO, dst, src) +#define MMIO_WRITEL(dst, src) _SEG_WRITEL(SEG_MMIO, dst, src) +#define MMIO_WRITEW(dst, src) _SEG_WRITEW(SEG_MMIO, dst, src) +#define MMIO_WRITEB(dst, src) _SEG_WRITEB(SEG_MMIO, dst, src) + +#define KERN_READL(dst, src) _SEG_READL(SEG_KERN, dst, src) +#define KERN_READW(dst, src) _SEG_READW(SEG_KERN, dst, src) +#define KERN_READB(dst, src) _SEG_READB(SEG_KERN, dst, src) +#define KERN_WRITEL(dst, src) _SEG_WRITEL(SEG_KERN, dst, src) +#define KERN_WRITEW(dst, src) _SEG_WRITEW(SEG_KERN, dst, src) +#define KERN_WRITEB(dst, src) _SEG_WRITEB(SEG_KERN, dst, src) +#endif + +#ifndef __SEG_GS +#define META_READL(dst, src) _SEG_READL(SEG_META, dst, src) +#define META_READW(dst, src) _SEG_READW(SEG_META, dst, src) +#define META_READB(dst, src) _SEG_READB(SEG_META, dst, src) +#define META_WRITEL(dst, src) _SEG_WRITEL(SEG_META, dst, src) +#define META_WRITEW(dst, src) _SEG_WRITEW(SEG_META, dst, src) +#define META_WRITEB(dst, src) _SEG_WRITEB(SEG_META, dst, src) +#endif + +#define MEMCPY_FROM_META(dst, src, sz) \ + { \ + uintptr_t __dst = (uintptr_t)(dst); \ + uintptr_t __src = (uintptr_t)(src); \ + size_t __sz = (size_t)(sz); \ + __asm__ __volatile__ ( \ + "rep movsb %%" SEG_META "s:(%%esi), %%es:(%%edi)\n\t" \ + : "+D"(__dst), "+S"(__src), "+c"(__sz)); \ + } + +#define MEMCPY_TO_META(dst, src, sz) \ + { \ + uintptr_t __dst = (uintptr_t)(dst); \ + uintptr_t __src = (uintptr_t)(src); \ + size_t __sz = (size_t)(sz); \ + __asm__ __volatile__ ( \ + "push %%es\n\t" \ + "push %%" SEG_META "s\n\t" \ + "pop %%es\n\t" \ + "rep movsb\n\t" \ + "pop %%es\n\t" \ + : "+D"(__dst), "+S"(__src), "+c"(__sz)); \ + } + +/** Compute physical address from offset into kernel data space */ +#define KERN_DATA_OFF_TO_PHYS_ADDR(x) \ + (((uintptr_t)&_sbss_kern_addr) + (uintptr_t)(x)) +/** Compute physical address from offset into default data space */ +#define DATA_OFF_TO_PHYS_ADDR(x) \ + (((uintptr_t)&_sdata_addr) + (uintptr_t)(x)) +/** Compute kernel data offset from physical address in kernel data space */ +#define PHYS_ADDR_TO_KERN_DATA_OFF(x) \ + (((uintptr_t)(x)) - (uintptr_t)&_sbss_kern_addr) + +/** + * In multi-segment protection domain implementations, it is sufficient to just + * compare incoming pointers against the frame pointer. All incoming pointers + * are dereferenced in the main data segment, which only maps the stacks and + * the shared data section. Since the shared data section is at a higher + * address range than the stacks, the frame pointer check is sufficient. + */ +#define PROT_DOMAINS_CHECK_INCOMING_PTR PROT_DOMAINS_CHECK_INCOMING_PTR_EBP + +void prot_domains_enable_mmio(void); +void prot_domains_disable_mmio(void); + +#endif /* CPU_X86_MM_MULTI_SEGMENT_H_ */ diff --git a/cpu/x86/mm/paging-prot-domains.c b/cpu/x86/mm/paging-prot-domains.c new file mode 100644 index 000000000..6c28c03e2 --- /dev/null +++ b/cpu/x86/mm/paging-prot-domains.c @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include "dma.h" +#include "gdt.h" +#include "gdt-layout.h" +#include "helpers.h" +#include "idt.h" +#include "paging.h" +#include "prot-domains.h" +#include "segmentation.h" +#include "stacks.h" +#include "syscalls.h" +#include "tss.h" + +/*#define DBG_PAGE_ALLOC*/ + +/* Enable PAE-mode paging */ +#define CR4_PAE BIT(5) + +/* Extended Feature Enables MSR */ +#define MSR_EFER 0xC0000080 + +/* Enable Execute Disable bit support */ +#define EFER_NXE BIT(11) + +/* Root page-directory-pointer table */ +static pdpt_t root_pgtbl __attribute__((aligned(32))) ATTR_BSS_KERN; +/* Although the following page tables must be page-aligned, it is infeasible to + * apply the "aligned(4096)" attribute for the reasons described in the linker + * script. + */ +/* Second-level page directory */ +static page_table_t + second_lvl_pgtbl ATTR_BSS_KERN_PAGE_ALIGNED; +/* Leaf-level page table */ +static page_table_t leaf_pgtbl ATTR_BSS_KERN_PAGE_ALIGNED; + +#define LINEAR_ADDR_BOUND (MIN_PAGE_SIZE * ENTRIES_PER_PAGE_TABLE) + +/*---------------------------------------------------------------------------*/ +void +prot_domains_reg(dom_client_data_t *dcd, + uintptr_t mmio, + size_t mmio_sz, + uintptr_t meta, + size_t meta_sz, + bool pio) +{ + dom_id_t dom_id = dcd->dom_id; + volatile struct dom_kern_data *dkd = + prot_domains_kern_data + dom_id; + + /* All addresses and sizes must be page-aligned */ + if((PROT_DOMAINS_ACTUAL_CNT <= dom_id) || + ((mmio & (MIN_PAGE_SIZE - 1)) != 0) || + ((mmio_sz & (MIN_PAGE_SIZE - 1)) != 0) || + ((meta & (MIN_PAGE_SIZE - 1)) != 0) || + ((meta_sz & (MIN_PAGE_SIZE - 1)) != 0) || + (PROT_DOMAINS_MAX_MMIO_SZ < mmio_sz) || + (LINEAR_ADDR_BOUND < (PROT_DOMAINS_META_LINEAR_BASE + meta_sz))) { + halt(); + } + + if((dkd->flags & PROT_DOMAINS_FLAG_INITED) == PROT_DOMAINS_FLAG_INITED) { + halt(); + } + + dkd->mmio = mmio; + dkd->mmio_sz = mmio_sz; + dkd->meta = meta; + dkd->meta_sz = meta_sz; + dkd->flags = PROT_DOMAINS_FLAG_INITED; + if(pio) { + dkd->flags |= PROT_DOMAINS_FLAG_PIO; + } +} +/*---------------------------------------------------------------------------*/ +static void __attribute__((regparm(3))) +set_ptes(uintptr_t start_la, uintptr_t start_pa, uintptr_t end_pa, + pte_t template) +{ +#ifdef DBG_PAGE_ALLOC +#warning Checking page allocations at runtime. + + if(((start_la & (MIN_PAGE_SIZE - 1)) != 0) || + ((start_pa & (MIN_PAGE_SIZE - 1)) != 0) || + ((start_la & (MIN_PAGE_SIZE - 1)) != 0) || + ((end_pa & (MIN_PAGE_SIZE - 1)) != 0) || + (LINEAR_ADDR_BOUND <= (start_la + (end_pa - start_pa)))) { + halt(); + } +#endif + + while(start_pa < end_pa) { + template.addr = start_pa >> 12; + + leaf_pgtbl[start_la >> MIN_PAGE_SIZE_SHAMT] = template; + +#ifdef X86_CONF_USE_INVLPG + __asm__("invlpg %0" :: "m" (*(uint8_t *)start_la)); +#endif + + start_la += MIN_PAGE_SIZE; + start_pa += MIN_PAGE_SIZE; + } +} +/*---------------------------------------------------------------------------*/ +static void __attribute__((fastcall)) +set_ptes_identity_map(uintptr_t start_pa, uintptr_t end_pa, pte_t template) +{ + set_ptes(start_pa, start_pa, end_pa, template); +} +/*---------------------------------------------------------------------------*/ +static inline uint32_t __attribute__((always_inline)) +prot_domains_switch(dom_id_t from_id, dom_id_t to_id, + interrupt_stack_t *intr_stk) +{ + volatile dom_kern_data_t *from, *to; + + from = prot_domains_kern_data + from_id; + to = prot_domains_kern_data + to_id; + + if((from_id == DOM_ID_kern) || + (to_id == DOM_ID_kern)) { + pte_t to_kern_data_pte = { .raw = 0 }; + to_kern_data_pte.present = 1; + to_kern_data_pte.exec_disable = 1; + /* The kernel data region should always be accessible to supervisory code, + * but it is only accessible to user mode in the kernel protection domain. + */ + to_kern_data_pte.user_accessible = 1; + if(to_id == DOM_ID_kern) { + to_kern_data_pte.writable = 1; + } + + set_ptes_identity_map((uintptr_t)&_sbss_kern_addr, + (uintptr_t)&_ebss_syscall_addr, + to_kern_data_pte); + + if(to_id != DOM_ID_kern) { + to_kern_data_pte.user_accessible = 0; + to_kern_data_pte.writable = 0; + } + + set_ptes_identity_map((uintptr_t)&_ebss_syscall_addr, + (uintptr_t)&_ebss_kern_addr, + to_kern_data_pte); + } + + if(to->mmio_sz != 0) { + pte_t pte = { .raw = 0 }; + pte.present = 1; + pte.exec_disable = 1; + pte.user_accessible = 1; + pte.writable = 1; + /* disable caching of MMIO accesses */ + pte.pcd = 1; + + set_ptes(PROT_DOMAINS_MMIO_LINEAR_BASE, + to->mmio, + to->mmio + to->mmio_sz, + pte); + } + if(to->mmio_sz < from->mmio_sz) { + pte_t pte = { .raw = 0 }; + + set_ptes_identity_map(PROT_DOMAINS_MMIO_LINEAR_BASE + to->mmio_sz, + PROT_DOMAINS_MMIO_LINEAR_BASE + from->mmio_sz, + pte); + } + + if(to->meta_sz != 0) { + pte_t pte = { .raw = 0 }; + pte.present = 1; + pte.exec_disable = 1; + pte.user_accessible = 1; + pte.writable = 1; + + set_ptes(PROT_DOMAINS_META_LINEAR_BASE, + to->meta, + to->meta + to->meta_sz, + pte); + } + if(to->meta_sz < from->meta_sz) { + pte_t pte = { .raw = 0 }; + + set_ptes_identity_map(PROT_DOMAINS_META_LINEAR_BASE + to->mmio_sz, + PROT_DOMAINS_META_LINEAR_BASE + from->mmio_sz, + pte); + } + +#ifndef X86_CONF_USE_INVLPG + __asm__ __volatile__ ("mov %%cr3, %%eax\n\t" + "mov %%eax, %%cr3\n\t" ::: "eax"); +#endif + + return 0; +} +/*---------------------------------------------------------------------------*/ +void +prot_domains_gdt_init(void) +{ + gdt_copy_desc_change_dpl(GDT_IDX_DATA, GDT_IDX_DATA_FLAT, PRIV_LVL_USER); + gdt_copy_desc_change_dpl(GDT_IDX_STK_INT, GDT_IDX_STK_EXC, PRIV_LVL_INT); +} +/*---------------------------------------------------------------------------*/ +void +prot_domains_impl_init(void) +{ + pte_t pte = { .raw = 0 }; + + syscalls_int_init(); + + /* Initialize page table: */ + + pte.present = 1; + pte.addr = ((uint32_t)second_lvl_pgtbl) >> MIN_PAGE_SIZE_SHAMT; + + root_pgtbl[0] = pte; + + pte.writable = 1; + pte.user_accessible = 1; + pte.addr = ((uint32_t)leaf_pgtbl) >> MIN_PAGE_SIZE_SHAMT; + + second_lvl_pgtbl[0] = pte; + + /* Map code sections: */ + + pte.writable = 0; + set_ptes_identity_map((uintptr_t)&_stext_addr, (uintptr_t)&_etext_addr, pte); + + /* Map data sections: */ + + pte.writable = 1; + pte.exec_disable = 1; + set_ptes_identity_map((uintptr_t)stacks_main, + (uintptr_t)stacks_main + + STACKS_SIZE_MAIN + + STACKS_SIZE_EXC + + STACKS_SIZE_INT, + pte); + set_ptes_identity_map((uintptr_t)&_sdata_addr, (uintptr_t)&_edata_addr, pte); + + /* Enable XD bit support */ + __asm__ __volatile__ ("wrmsr" :: "c" (MSR_EFER), "a" (EFER_NXE), "d" (0)); + + /* Enable PAE */ + __asm__ __volatile__ ("mov %%cr4, %%eax\n\t" + "or %0, %%eax\n\t" + "mov %%eax, %%cr4\n\t" + : + : "r" (CR4_PAE) + : "eax"); + + /* Load CR3 */ + __asm__ __volatile__ ("mov %0, %%cr3" :: "r" (root_pgtbl)); +} +/*---------------------------------------------------------------------------*/ +uintptr_t +prot_domains_lookup_meta_phys_base(dom_client_data_t *drv) +{ + return prot_domains_kern_data[drv->dom_id].meta; +} +/*---------------------------------------------------------------------------*/ + +/* Enable inter-procedural optimization with procedures in the following file: + */ +#include "syscalls-int.c" diff --git a/cpu/x86/mm/paging-prot-domains.h b/cpu/x86/mm/paging-prot-domains.h new file mode 100644 index 000000000..0f7f54ea3 --- /dev/null +++ b/cpu/x86/mm/paging-prot-domains.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_MM_PAGING_PROT_DOMAINS_H_ +#define CPU_X86_MM_PAGING_PROT_DOMAINS_H_ + +#include +#include +#include +#include "dma.h" +#include "helpers.h" +#include "paging.h" +#include "syscalls-int.h" + +struct dom_kern_data { + /** Base physical address of optional MMIO region */ + uintptr_t mmio; + /** Number of (contiguous) pages in MMIO region */ + size_t mmio_sz; + /** Base physical address of optional metadata region */ + uintptr_t meta; + /** Number of (contiguous) pages in metadata region */ + size_t meta_sz; + /** Flags are defined with the prefix PROT_DOMAINS_FLAG in prot-domains.h */ + uint32_t flags; + /** + * Original return address from call stack when this protection domain + * invoked some other protection domain. This serves to control the return + * entrypoint. The callee is not permitted to modify this value (unless the + * callee is the kernel protection domain). + */ + uintptr_t orig_ret_addr; + + /* align to next-larger power of 2 to enable usage of shifting instead of + * multiplication to index an array of these structures. + */ +} __attribute__((aligned(32))); + +/** Linear base address at which to map the MMIO region. */ +#define PROT_DOMAINS_MMIO_LINEAR_BASE (MIN_PAGE_SIZE + (uintptr_t)&_ebss_kern_addr) + +/** Maximum supported size of MMIO region */ +#define PROT_DOMAINS_MAX_MMIO_SZ 0x4000 + +/** Linear base address at which to map the metadata region */ +#define PROT_DOMAINS_META_LINEAR_BASE \ + (MIN_PAGE_SIZE + (PROT_DOMAINS_MMIO_LINEAR_BASE + PROT_DOMAINS_MAX_MMIO_SZ)) + +#define PROT_DOMAINS_META_OFF_TO_PHYS(off, meta_phys_base) \ + ((meta_phys_base) + ((off) - PROT_DOMAINS_META_LINEAR_BASE)) + +/** Any MMIO region mapping always starts at a particular linear address. */ +#define PROT_DOMAINS_MMIO(dcd) PROT_DOMAINS_MMIO_LINEAR_BASE +/** + * Any metadata region mapping always starts at a particular linear address. + */ +#define PROT_DOMAINS_META(dcd) PROT_DOMAINS_META_LINEAR_BASE + +#define PROT_DOMAINS_ENTER_ISR(exc) \ + PROT_DOMAINS_ENTER_ISR_COMMON(exc) +#define PROT_DOMAINS_LEAVE_ISR(exc) PROT_DOMAINS_LEAVE_ISR_COMMON(exc) + +/* Enable paging */ +#define CR0_PG BIT(31) +/* Enable write protection in supervisor mode */ +#define CR0_WP BIT(16) +/* Enable protected mode */ +#define CR0_PE BIT(0) + +/** + * \brief Enable or disable write protection enforcement in supervisor mode. + * When disabled, supervisory code (i.e. code running at ring levels + * 0-2) is permitted to write to pages that are marked read-only in + * page tables. + * + * \param en Set to true to enable write protection enforcement. + */ +static inline void prot_domains_set_wp(bool en) +{ + uint32_t cr0_val = CR0_PG | CR0_PE; + if(en) { + cr0_val |= CR0_WP; + } + __asm__ __volatile__ ("mov %0, %%cr0" :: "r"(cr0_val)); +} + +#endif /* CPU_X86_MM_PAGING_PROT_DOMAINS_H_ */ diff --git a/cpu/x86/mm/paging.h b/cpu/x86/mm/paging.h new file mode 100644 index 000000000..7882ceab2 --- /dev/null +++ b/cpu/x86/mm/paging.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_MM_PAGING_H_ +#define CPU_X86_MM_PAGING_H_ + +#include + +/** + * Page table entry format for PAE mode page table. See Intel Combined Manual, + * Vol. 3, Section 4.4 for more details. + */ +typedef union pte { + struct { + uint64_t present : 1; + uint64_t writable : 1; + uint64_t user_accessible : 1; + uint64_t pwt : 1; /**< Specify write-through cache policy */ + uint64_t pcd : 1; /**< Disable caching */ + uint64_t accessed : 1; + uint64_t dirty : 1; + uint64_t : 5; + uint64_t addr : 51; + uint64_t exec_disable : 1; + }; + uint64_t raw; +} pte_t; + +#define ENTRIES_PER_PDPT 4 +#define ENTRIES_PER_PAGE_TABLE 512 + +typedef pte_t pdpt_t[ENTRIES_PER_PDPT]; +typedef pte_t page_table_t[ENTRIES_PER_PAGE_TABLE]; + +#define MIN_PAGE_SIZE_SHAMT 12 +#define MIN_PAGE_SIZE (1 << MIN_PAGE_SIZE_SHAMT) + +#endif /* CPU_X86_MM_PAGING_H_ */ diff --git a/cpu/x86/mm/prot-domains.c b/cpu/x86/mm/prot-domains.c new file mode 100644 index 000000000..56461b381 --- /dev/null +++ b/cpu/x86/mm/prot-domains.c @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "prot-domains.h" + +#include "gdt.h" +#include +#include "interrupt.h" +#include +#include +#include "syscalls.h" +#include "stacks.h" + +static dom_kern_data_t __attribute__((section(".kern_prot_dom_bss"))) + ATTR_KERN_ADDR_SPACE PROT_DOMAINS_PDCS_NM(kern_dcd); +PROT_DOMAINS_ALLOC_IMPL(kern_dcd); +static dom_client_data_t ATTR_BSS_KERN kern_dcd; +static dom_kern_data_t __attribute__((section(".app_prot_dom_bss"))) + ATTR_KERN_ADDR_SPACE PROT_DOMAINS_PDCS_NM(app_dcd); +PROT_DOMAINS_ALLOC_IMPL(app_dcd); +static dom_client_data_t ATTR_BSS_KERN app_dcd; + +/*---------------------------------------------------------------------------*/ +void +prot_domains_init(void) +{ + segment_desc_t desc; + + gdt_lookup(GDT_IDX_CODE_EXC, &desc); +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG + /* The exception code segment needs to be readable so that the general + * protection fault handler can decode instructions, but the interrupt and + * user level code segments should not be. + */ + SEG_SET_FLAG(desc, TYPE, SEG_TYPE_CODE_EX); +#endif + + SEG_SET_FLAG(desc, DPL, PRIV_LVL_INT); + gdt_insert(GDT_IDX_CODE_INT, desc); + + SEG_SET_FLAG(desc, DPL, PRIV_LVL_USER); + gdt_insert(GDT_IDX_CODE, desc); + + PROT_DOMAINS_INIT_ID(kern_dcd); + prot_domains_reg(&kern_dcd, 0, 0, 0, 0, true); + PROT_DOMAINS_INIT_ID(app_dcd); + prot_domains_reg(&app_dcd, 0, 0, 0, 0, false); + + prot_domains_impl_init(); +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/mm/prot-domains.h b/cpu/x86/mm/prot-domains.h new file mode 100644 index 000000000..13062612b --- /dev/null +++ b/cpu/x86/mm/prot-domains.h @@ -0,0 +1,376 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_MM_PROT_DOMAINS_H_ +#define CPU_X86_MM_PROT_DOMAINS_H_ + +#if !__ASSEMBLER__ +#include +#include +#include +#include "helpers.h" +#endif + +#define X86_CONF_PROT_DOMAINS__NONE 0 +#define X86_CONF_PROT_DOMAINS__PAGING 1 +#define X86_CONF_PROT_DOMAINS__TSS 2 +#define X86_CONF_PROT_DOMAINS__SWSEG 3 + +#define X86_CONF_PROT_DOMAINS_MULTI_SEG \ + ((X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS) || \ + (X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG)) + +/** Privilege level (ring) for exception handlers and other supervisory code */ +#define PRIV_LVL_EXC 0 +#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__NONE +/** Privilege level for interrupt handlers */ +#define PRIV_LVL_INT 2 +/** Default privilege level */ +#define PRIV_LVL_USER 3 +#else +#define PRIV_LVL_INT PRIV_LVL_EXC +#define PRIV_LVL_USER PRIV_LVL_EXC +#endif + +#define DOM_ID_kern 0 +#define DOM_ID_app 1 + +/** I/O Privilege Level */ +#define EFLAGS_IOPL(pl) ((pl) << 12) +/** Interrupt Enable Flag */ +#define EFLAGS_IF (1u << 9) + +#if !__ASSEMBLER__ + +/** Protection domain ID */ +typedef uint32_t dom_id_t; + +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING +#include "paging-prot-domains.h" +#elif X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS +#include "tss-prot-domains.h" +#elif X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG +#include "swseg-prot-domains.h" +#endif + +#ifndef ATTR_META_ADDR_SPACE +#define ATTR_META_ADDR_SPACE +#endif +#ifndef ATTR_MMIO_ADDR_SPACE +#define ATTR_MMIO_ADDR_SPACE +#endif +#ifndef ATTR_KERN_ADDR_SPACE +#define ATTR_KERN_ADDR_SPACE +#endif + +#ifndef MMIO_READL +#define MMIO_READL(dst, src) dst = (src) +#define MMIO_READW(dst, src) dst = (src) +#define MMIO_READB(dst, src) dst = (src) +#define MMIO_WRITEL(dst, src) MMIO_READL(dst, src) +#define MMIO_WRITEW(dst, src) MMIO_READW(dst, src) +#define MMIO_WRITEB(dst, src) MMIO_READB(dst, src) +#endif +#ifndef KERN_READL +#define KERN_READL(dst, src) dst = (src) +#define KERN_READW(dst, src) dst = (src) +#define KERN_READB(dst, src) dst = (src) +#define KERN_WRITEL(dst, src) KERN_READL(dst, src) +#define KERN_WRITEW(dst, src) KERN_READW(dst, src) +#define KERN_WRITEB(dst, src) KERN_READB(dst, src) +#endif +#ifndef META_READL +#define META_READL(dst, src) dst = (src) +#define META_READW(dst, src) dst = (src) +#define META_READB(dst, src) dst = (src) +#define META_WRITEL(dst, src) META_READL(dst, src) +#define META_WRITEW(dst, src) META_READw(dst, src) +#define META_WRITEB(dst, src) META_READB(dst, src) +#endif + +#ifndef MEMCPY_FROM_META +#define MEMCPY_FROM_META(dst, src, sz) \ + memcpy((void *)(dst), (const void *)(src), (sz)) +#define MEMCPY_TO_META(dst, src, sz) MEMCPY_FROM_META(dst, src, sz) +#endif + +/* The following symbols are defined in the linker script */ +/** Bounds for .text section */ +extern uint32_t _stext_addr, _etext_addr; + +#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__NONE + +/** Metadata that should not be DMA-accessible */ +#define ATTR_BSS_META __attribute__((section(".meta_bss"))) ATTR_META_ADDR_SPACE +/** Kernel-owned data */ +#define ATTR_BSS_KERN __attribute__((section(".kern_bss"))) ATTR_KERN_ADDR_SPACE +/** Code that should only be executable during bootup */ +#define ATTR_CODE_BOOT __attribute__((section(".boot_text"))) + +/** + * Domain-defined metadata must be page-aligned, which is implemented by the + * linker script for variables with this attribute. + */ +#define ATTR_BSS_KERN_PAGE_ALIGNED \ + __attribute__((section(".page_aligned_kern_bss"))) + +/** Bounds for .kern_data, .syscall_data, and .prot_dom_data sections */ +extern uint32_t _sbss_kern_addr, _ebss_kern_addr; +/** End of .syscall_data section */ +extern uint32_t _ebss_syscall_addr; +/** Bounds for other data sections */ +extern uint32_t _sdata_addr, _edata_addr; + +#ifndef SEG_KERN +#define SEG_KERN "d" +#endif + +/** + * If set, this protection domain is already in the call stack and is not + * available for nested invocations. + */ +#define PROT_DOMAINS_FLAG_BUSY BIT(0) +/** If set, this protection domain requires port I/O access. */ +#define PROT_DOMAINS_FLAG_PIO BIT(1) +/** If set, this protection domain is initialized. */ +#define PROT_DOMAINS_FLAG_INITED BIT(2) + +/** + * Data associated with each protection domain that should be fully accessible + * only to the kernel, with limited accesses and modifications permitted from + * other domains. Includes storage for system data structures. + */ +typedef struct dom_kern_data dom_kern_data_t; + +extern volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE prot_domains_kern_data[]; +extern volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE prot_domains_kern_data_end[]; + +#define PROT_DOMAINS_ACTUAL_CNT \ + (prot_domains_kern_data_end - prot_domains_kern_data) + +#define PROT_DOMAINS_GET_DOM_ID(dkd) \ + ((dom_id_t)((dkd) - prot_domains_kern_data)) + +void prot_domains_syscall_dispatcher(void); + +#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__TSS +/** + * Data associated with each protection domain that is owned by clients of that + * domain and used to identify the domain. + */ +struct dom_client_data { + dom_id_t dom_id; +} __attribute__((packed)); +#endif + +#ifndef PROT_DOMAINS_ALLOC_IMPL +#define PROT_DOMAINS_ALLOC_IMPL(nm) +#endif + +/** Allocate the client-owned protection domain data structure. */ +#define PROT_DOMAINS_PDCS_NM(nm) _pdcs_##nm +#define PROT_DOMAINS_ALLOC(typ, nm) \ + static dom_kern_data_t __attribute__((section(".prot_dom_bss"))) \ + ATTR_KERN_ADDR_SPACE PROT_DOMAINS_PDCS_NM(nm); \ + PROT_DOMAINS_ALLOC_IMPL(nm); \ + static typ ATTR_BSS_KERN nm +#define PROT_DOMAINS_INIT_ID(nm) \ + KERN_WRITEL((nm).dom_id, PROT_DOMAINS_GET_DOM_ID(&PROT_DOMAINS_PDCS_NM(nm))) + +/** + * Perform early initialization during boot stage 0 to prepare for boot stage 1 + */ +void prot_domains_gdt_init() ATTR_CODE_BOOT; +/** + * Perform initialization during boot stage 1 to prepare for kernel launch + */ +void prot_domains_init(); +void prot_domains_impl_init(); + +/* Return from cpu_boot_stage1 will invoke prot_domains_launch_kernel due to + * that return address being pushed on the stack by cpu_boot_stage0. + */ +#define prot_domains_leave_boot_stage1() + +/* Return from main will invoke prot_domains_launch_app due to that return + * address being pushed on the stack by cpu_boot_stage0. + */ +#define prot_domains_leave_main() + +void prot_domains_launch_kernel(void); + +/* Whenever changing this, update syscalls-int-asm.S:prot_domains_launch_kernel + * to match: + */ +#define PROT_DOMAINS_INIT_RET_ADDR_CNT 2 + +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS +void prot_domains_launch_app(void); +#else +void app_main(void); +#define prot_domains_launch_app app_main +#endif + +#else + +#define ATTR_BSS_META +#define ATTR_BSS_KERN +#define ATTR_CODE_BOOT + +struct dom_client_data { + uintptr_t mmio; /**< MMIO range base address */ + uintptr_t meta; /**< Domain-defined metadata base address */ +}; + +/** Retrieve the MMIO base address for the specified protection domain. */ +#define PROT_DOMAINS_MMIO(dcd) ((dcd).mmio) + +/** Retrieve the metadata base address for the specified protection domain. */ +#define PROT_DOMAINS_META(dcd) ((dcd).meta) + +#define PROT_DOMAINS_ALLOC(typ, nm) static typ nm +#define PROT_DOMAINS_INIT_ID(nm) + +#define prot_domains_gdt_init() + +#define prot_domains_init() + +int main(void); +#define prot_domains_leave_boot_stage1 main +#define prot_domains_leave_main ENABLE_IRQ(); app_main + +#define PROT_DOMAINS_INIT_RET_ADDR_CNT 0 + +#endif + +/** + * Protection domain data readable by the client. It is used to control + * execution, so it should be protected from modifications by clients. + * Otherwise, there is a risk that one client could modify one of these + * structures used by another client to issue a system call, which could then + * cause the latter client to perform an unintended system call. + */ +typedef struct dom_client_data dom_client_data_t; + +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE +#define prot_domains_reg(dcd, mmio_, mmio_sz, meta_, meta_sz, pio) \ + (dcd)->mmio = (mmio_); \ + (dcd)->meta = (meta_) +#else +/** + * \brief Register a protection domain, which involves creating the + * necessary system data structures for it. + * + * \param dcd Client-accessible domain information + * \param mmio Optional base address for per-domain memory-mapped IO region + * \param mmio_sz Size of MMIO region + * \param meta Optional base address for per-domain metadata + * \param meta_sz Size of metadata + * \param pio Set to true if protection domain requires port IO access + */ +void prot_domains_reg(dom_client_data_t ATTR_KERN_ADDR_SPACE *dcd, + uintptr_t mmio, + size_t mmio_sz, + uintptr_t meta, + size_t meta_sz, + bool pio); +#endif + +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE +#define prot_domains_copy_dcd(dst, src) *(dst) = *(src) +#else +static inline void +/** + * It is necessary to make a local copy of a dom_client_data structure when a + * multi-segment protection domain implementation is in use, segment attributes + * are not supported by the compiler, and a dom_client_data structure needs to + * be passed by value into some function. Otherwise, the compiler will not know + * to access the non-default segment in which *src is stored and will attempt + * to copy it out of the default data segment. + */ +prot_domains_copy_dcd(struct dom_client_data *dst, + struct dom_client_data ATTR_KERN_ADDR_SPACE *src) +{ + KERN_READL(dst->dom_id, src->dom_id); +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS + KERN_READL(dst->tss_sel, src->tss_sel); +#endif +} +#endif + +#if !X86_CONF_PROT_DOMAINS_MULTI_SEG +#define prot_domains_enable_mmio() +#define prot_domains_disable_mmio() + +#define KERN_DATA_OFF_TO_PHYS_ADDR(x) ((uintptr_t)(x)) +#define DATA_OFF_TO_PHYS_ADDR(x) ((uintptr_t)(x)) +#endif + +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE +#define prot_domains_lookup_meta_phys_base(drv) 0 +#else +/** Lookup base physical address of metadata region for specified domain */ +uintptr_t prot_domains_lookup_meta_phys_base(dom_client_data_t ATTR_KERN_ADDR_SPACE *drv); +#endif + +#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__PAGING +#define PROT_DOMAINS_META_OFF_TO_PHYS(off, meta_phys_base) \ + ((meta_phys_base) + (off)) +#endif + +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE +#define PROT_DOMAINS_ENTER_ISR(...) +#define PROT_DOMAINS_LEAVE_ISR(...) +#else +#define PROT_DOMAINS_ENTER_ISR_COMMON(exc) \ + ".if !" #exc "\n\t" \ + /* Save the current stack pointer into a callee-saved register. */ \ + "mov %%esp, %%ebx\n\t" \ + /* Pivot to the main stack of the interrupted context. */ \ + /* Interrupts never have an error code, so the offset is always 44. */ \ + /* No interrupt handlers use anything from the original interrupt stack, */ \ + /* so there is no need to copy anything from it to the main stack. */ \ + "mov 44(%%esp), %%esp\n\t" \ + ".endif\n\t" +#define PROT_DOMAINS_LEAVE_ISR_COMMON(exc) \ + /* Restore the interrupt/exception stack pointer. */ \ + ".if !" #exc "\n\t" \ + "mov %%ebx, %%esp\n\t" \ + ".endif\n\t" +#endif + +#ifdef X86_CONF_PROT_DOMAINS_MULTI_SEG +/* include GDT section definitions used when allocating protection domains: */ +#include "gdt.h" +#endif + +#endif /* !__ASSEMBLER__ */ + +#endif /* CPU_X86_MM_PROT_DOMAINS_H_ */ diff --git a/cpu/x86/mm/segmentation.h b/cpu/x86/mm/segmentation.h new file mode 100644 index 000000000..71cd6beb6 --- /dev/null +++ b/cpu/x86/mm/segmentation.h @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_MM_SEGMENTATION_H_ +#define CPU_X86_MM_SEGMENTATION_H_ + +#include + +#define SEG_FLAG(lbl, val) \ + (((val) & (~0u >> (32 - SEG_WIDTH_##lbl))) << SEG_SHAMT_##lbl) + +#define SEG_SET_FLAG(desc, lbl, val) \ + (desc).flags = ((desc).flags & ~SEG_FLAG(lbl, ~0u)) | SEG_FLAG(lbl, val) + +#define SEG_WIDTH_TYPE 4 +#define SEG_SHAMT_TYPE 0 +#define SEG_WIDTH_DESCTYPE 1 +#define SEG_SHAMT_DESCTYPE 4 +#define SEG_WIDTH_DPL 2 +#define SEG_SHAMT_DPL 5 +#define SEG_WIDTH_PRESENT 1 +#define SEG_SHAMT_PRESENT 7 +#define SEG_WIDTH_LIMIT_HI 4 +#define SEG_SHAMT_LIMIT_HI 8 +#define SEG_WIDTH_AVL 1 +#define SEG_SHAMT_AVL 12 +#define SEG_WIDTH_LONG_MODE 1 +#define SEG_SHAMT_LONG_MODE 13 +/* also used to indicate default operand and address size */ +#define SEG_WIDTH_DIRECTION 1 +#define SEG_SHAMT_DIRECTION 14 +#define SEG_WIDTH_GRAN 1 +#define SEG_SHAMT_GRAN 15 + +#define SEG_TYPE_DATA_RDONLY SEG_FLAG(TYPE, 0x00) /* Read only */ +#define SEG_TYPE_DATA_RDWR SEG_FLAG(TYPE, 0x02) /* Read/Write */ +#define SEG_TYPE_CODE_EXRD SEG_FLAG(TYPE, 0x0A) /* Execute/Read */ +#define SEG_TYPE_CODE_EX SEG_FLAG(TYPE, 0x08) /* Execute only */ +#define SEG_TYPE_LDT SEG_FLAG(TYPE, 0x02) +#define SEG_TYPE_TSS32_AVAIL SEG_FLAG(TYPE, 0x09) + +#define SEG_DESCTYPE_SYS SEG_FLAG(DESCTYPE, 0) +#define SEG_DESCTYPE_NSYS SEG_FLAG(DESCTYPE, 1) + +#define SEG_PRESENT SEG_FLAG(PRESENT, 1) + +#define SEG_DEFL_OPSZ_32BIT SEG_FLAG(DIRECTION, 1) + +#define SEG_GRAN_BYTE SEG_FLAG(GRAN, 0) +#define SEG_GRAN_PAGE SEG_FLAG(GRAN, 1) + +/** + * Maximum length of segment that can be regulated with a byte-granularity + * segment limit. + */ +#define SEG_MAX_BYTE_GRAN_LEN (1 << 20) + +/** + * Segment descriptor. See Intel Combined Manual, + * Vol. 3, Section 3.4.5 for more details. + */ +typedef union segment_desc { + struct { + uint32_t lim_lo : 16; + uint32_t base_lo : 16; + uint32_t base_mid : 8; + uint32_t flags : 16; + uint32_t base_hi : 8; + }; + struct { + uint32_t raw_lo, raw_hi; + }; + uint64_t raw; +} segment_desc_t; + +#define SEG_DESC_NOT_PRESENT 0 + +/* The next two functions are invoked by boot code, so they must always be + * inlined to avoid being placed in a different address space than the initial, + * flat address space. + */ +static inline void __attribute__((always_inline)) +segment_desc_set_limit(segment_desc_t *c_this, uint32_t len) +{ + uint32_t limit = len - 1; + + SEG_SET_FLAG(*c_this, LIMIT_HI, limit >> 16); /* set limit bits 19:16 */ + c_this->lim_lo = limit; /* set limit bits 15:0 */ +} +/** + * \brief Initialize a segment descriptor. + * \param c_this Segment descriptor to be initialized. + * \param base Base address of region to be covered by segment descriptor. + * \param len Length to be specified by segment descriptor. The units may + * be bytes or pages, depending on the flags. + * \param flags Flags to be added to the default flags: present, default + * operand size of 32 bits, and high limit bits. + */ +static inline void __attribute__((always_inline)) +segment_desc_init(segment_desc_t *c_this, + uint32_t base, uint32_t len, uint16_t flags) +{ + c_this->raw = 0; + + /* Create the high 32 bit segment */ + c_this->base_mid = base >> 16; /* set base bits 23:16 */ + c_this->base_hi = base >> 24; /* set base bits 31:24 */ + + /* Create the low 32 bit segment */ + c_this->base_lo = base; /* set base bits 15:0 */ + + c_this->flags = SEG_FLAG(PRESENT, 1) | SEG_DEFL_OPSZ_32BIT | flags; + + /* This must be done after setting the other flags, or else it + * would be partially overridden. + */ + segment_desc_set_limit(c_this, len); +} +#endif /* CPU_X86_MM_SEGMENTATION_H_ */ diff --git a/cpu/x86/mm/stacks.c b/cpu/x86/mm/stacks.c new file mode 100644 index 000000000..60ccb0ebc --- /dev/null +++ b/cpu/x86/mm/stacks.c @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "stacks.h" + +uint8_t stacks_main[STACKS_SIZE_MAIN] + __attribute__((section(".main_stack"), aligned(4))); +#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__NONE +uint8_t stacks_int[STACKS_SIZE_INT] + __attribute__((section(".int_stack"), aligned(4))); +uint8_t stacks_exc[STACKS_SIZE_EXC] + __attribute__((section(".exc_stack"), aligned(4))); +#endif diff --git a/cpu/x86/mm/stacks.h b/cpu/x86/mm/stacks.h new file mode 100644 index 000000000..327e75600 --- /dev/null +++ b/cpu/x86/mm/stacks.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_MM_STACKS_H_ +#define CPU_X86_MM_STACKS_H_ + +#include "prot-domains.h" + +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE +#define STACKS_SIZE_INT 0 +#else +/** + * The necessary amount of space for the interrupt and exception stacks is + * determined by the amount of data pushed on the stack by the CPU when + * delivering an interrupt or exception, and by the additional data pushed + * on the stack by the interrupt dispatcher. See interrupt.h for more details. + */ +#define STACKS_SIZE_INT (14 * 4) +#endif + +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING +/** + * The system call and return dispatchers use this stack, so its size was + * determined by observing their behavior. It is possible that the dispatchers + * could overflow the stack and overwrite data on the other stacks. An + * alternative design that would facilitate detection of such overflows would + * place the exception handler stack on a separate page surrounded by guard + * bands, but that would consume a substantial amount of additional memory. + * + * All stack sizes should be a multiple of 4 to accommodate a 4-byte alignment. + */ +#ifdef __clang__ +#define STACKS_SIZE_EXC 512 +#else +#define STACKS_SIZE_EXC 256 +#endif +#elif X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG +#ifdef __clang__ +#define STACKS_SIZE_EXC 512 +#else +#define STACKS_SIZE_EXC 256 +#endif +#elif X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS +/** + * This should be large enough to execute the exception handler with the + * largest stack requirement: double_fault_handler: + * - 1 word for the return address from calling double_fault_handler + * - 1 word for the saved frame pointer in double_fault_handler + * - 2 words that GCC has been observed to skip on the stack to align it + * to a preferred boundary + * - 1 word for the return address for calling halt + */ +#define STACKS_SIZE_EXC (STACKS_SIZE_INT + (6 * 4)) +#else +#define STACKS_SIZE_EXC STACKS_SIZE_INT +#endif +/** + * The combined size of the stacks should be an even multiple of the 4K page + * size so that they precisely fill some number of pages when paging-based + * protection domains are in use. The stacks are arranged contiguously by + * the linker scripts. See those and README.md for more details. + */ +#define STACKS_SIZE_MAIN (8192 - (STACKS_SIZE_INT + STACKS_SIZE_EXC)) + +#if !__ASSEMBLER__ +/** + * Stack for exception handlers. Also used for system call and return + * dispatchers when paging-based protection domains are enabled. + */ +extern uint8_t stacks_exc[STACKS_SIZE_EXC]; +/** Stack for interrupt handlers. */ +extern uint8_t stacks_int[STACKS_SIZE_INT]; +/** Main C stack. */ +extern uint8_t stacks_main[STACKS_SIZE_MAIN]; + +#define STACKS_INIT_TOP \ + ((uintptr_t)stacks_main + STACKS_SIZE_MAIN - \ + (PROT_DOMAINS_INIT_RET_ADDR_CNT * sizeof(uintptr_t))) + +#endif + +#endif /* CPU_X86_MM_STACKS_H_ */ diff --git a/cpu/x86/mm/swseg-prot-domains.c b/cpu/x86/mm/swseg-prot-domains.c new file mode 100644 index 000000000..78a29aaf6 --- /dev/null +++ b/cpu/x86/mm/swseg-prot-domains.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gdt.h" +#include "helpers.h" +#include "multi-segment.h" +#include "prot-domains.h" + +/*---------------------------------------------------------------------------*/ +void +prot_domains_reg(dom_client_data_t ATTR_KERN_ADDR_SPACE *dcd, + uintptr_t mmio, size_t mmio_sz, + uintptr_t meta, size_t meta_sz, + bool pio) +{ + volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE *dkd; + dom_id_t dom_id; + + KERN_READL(dom_id, dcd->dom_id); + + if(PROT_DOMAINS_ACTUAL_CNT <= dom_id) { + halt(); + } + + dkd = prot_domains_kern_data + dom_id; + + prot_domains_reg_multi_seg(dkd, mmio, mmio_sz, meta, meta_sz); + + KERN_WRITEL(dkd->flags, pio ? PROT_DOMAINS_FLAG_PIO : 0); +} +/*---------------------------------------------------------------------------*/ +static inline void __attribute__((always_inline)) +prot_domains_switch(dom_id_t from_id, dom_id_t to_id, + interrupt_stack_t *intr_stk) +{ + __asm__ __volatile__ ( + "lldt %[_ldt_]\n\t" + "mov %[_meta_seg_], %%eax\n\t" + "lsl %%eax, %%ecx\n\t" + "jz 1f\n\t" /* ZF will only be set if the segment descriptor is valid. */ + "xor %%eax, %%eax\n\t" /* Nullify metadata selector */ + "1: mov %%eax, %%" SEG_META "s\n\t" + "mov %[_kern_seg_], %%eax\n\t" + "mov %%eax, %%" SEG_KERN "s\n\t" + : + : [_ldt_] "r" ((uint16_t)GDT_SEL_LDT(to_id)), + [_meta_seg_] "i" (LDT_SEL_META), + [_kern_seg_] "i" (LDT_SEL_KERN) + : "cc", "eax", "ecx" + ); +} +/*---------------------------------------------------------------------------*/ + +/* Enable inter-procedural optimization with procedures in the following file: + */ +#include "syscalls-int.c" diff --git a/cpu/x86/mm/swseg-prot-domains.h b/cpu/x86/mm/swseg-prot-domains.h new file mode 100644 index 000000000..a503bc6db --- /dev/null +++ b/cpu/x86/mm/swseg-prot-domains.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_MM_SWSEG_PROT_DOMAINS_H_ +#define CPU_X86_MM_SWSEG_PROT_DOMAINS_H_ + +#include +#include +#include +#include "ldt-layout.h" +#include "paging.h" +#include "segmentation.h" +#include "syscalls-int.h" + +struct dom_kern_data { + /** Local Descriptor Table with per-domain descriptors */ + segment_desc_t ldt[LDT_NUM_DESC]; + /** Flags are defined with the prefix PROT_DOMAINS_FLAG in prot-domains.h */ + uint32_t flags; + /** + * Original return address from call stack when this protection domain + * invoked some other protection domain. This serves to control the return + * entrypoint. The callee is not permitted to modify this value (unless the + * callee is the kernel protection domain). + */ + uintptr_t orig_ret_addr; + + /* This structure is precisely 32 bytes in length, a power of 2. If its size + * changes, add an alignment attribute to keep it aligned at a power of 2 so + * that dereferencing arrays of these structures uses shift instructions + * instead of multiplication. Shifting is faster than multiplication. + */ +}; + +/* relies on dom_kern_data: */ +#include "multi-segment.h" + +#define PROT_DOMAINS_ENTER_ISR(exc) \ + MULTI_SEGMENT_ENTER_ISR(exc) \ + PROT_DOMAINS_ENTER_ISR_COMMON(exc) +#define PROT_DOMAINS_LEAVE_ISR(exc) \ + PROT_DOMAINS_LEAVE_ISR_COMMON(exc) \ + MULTI_SEGMENT_LEAVE_ISR(exc) + +#define prot_domains_impl_init syscalls_int_init + +#define prot_domains_set_wp(en) + +/* Allocate one additional GDT entry for each protection domain. Note that + * the particular storage allocated by this statement may actually be used for + * some other protection domain, depending on how the linker happens to arrange + * all of the GDT storage. The GDT_IDX_LDT macro in gdt-layout.h determine + * which storage is used for each protection domain. Thus, this storage should + * not be referenced directly by its variable name. + */ +#define PROT_DOMAINS_ALLOC_IMPL(nm) \ + static segment_desc_t ATTR_BSS_GDT_MID _gdt_storage_##nm + +#endif /* CPU_X86_MM_SWSEG_PROT_DOMAINS_H_ */ diff --git a/cpu/x86/mm/syscalls-int-asm.S b/cpu/x86/mm/syscalls-int-asm.S new file mode 100644 index 000000000..5c88c890b --- /dev/null +++ b/cpu/x86/mm/syscalls-int-asm.S @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "syscalls-int.h" +#include "prot-domains.h" +#include "gdt-layout.h" +#include "stacks.h" + +/* Must match definitions (plus the trailing 's') in multi-segment.h */ +#define SEG_MMIO fs +#define SEG_KERN fs + +.text + +/* Invoke the system call return dispatcher from the default privilege + * level + */ +.global prot_domains_sysret_stub +prot_domains_sysret_stub: + int $PROT_DOMAINS_SYSRET_DISPATCH_INT + +.macro save_segs +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG + /* Save (and restore, in restore_segs) MMIO segment register into + * callee-saved register in case a system call was invoked from a region in + * which MMIO is enabled. + */ + push %SEG_MMIO +#endif +.endm + +.macro restore_segs +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG + pop %SEG_MMIO +#endif +.endm + +/* Refresh most of the segment registers in case they were corrupted by + * userspace code to prevent that from corrupting the operation of the + * privileged code. + */ +.macro load_kern_segs +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG + mov $GDT_SEL_DATA, %eax + mov %eax, %ds + mov %eax, %es + mov $GDT_SEL_DATA_KERN_EXC, %eax + mov %eax, %SEG_KERN +#endif +.endm + +/* Invoke the system call dispatcher C routine */ +.global prot_domains_syscall_dispatcher +prot_domains_syscall_dispatcher: + mov %esp, %ecx /*< interrupt_stack_t *intr_stk */ + /* EDX already set to "dom_client_data_t to_dcd" by syscall stub */ + save_segs + push %eax /*< syscalls_entrypoint_t *syscall */ + load_kern_segs + call prot_domains_syscall_dispatcher_impl + /* fastcall convention, so callee pops arguments */ + restore_segs + iret + +/* Invoke the system call return dispatcher C routine */ +.global prot_domains_sysret_dispatcher +prot_domains_sysret_dispatcher: + mov %esp, %ecx /*< interrupt_stack_t *intr_stk */ + save_segs + load_kern_segs + call prot_domains_sysret_dispatcher_impl + restore_segs + /* Zero caller-saved registers in case they contain secrets. The system call + * handlers and dispatchers need to preserve the callee-saved registers. + */ + xor %eax, %eax + xor %ecx, %ecx + xor %edx, %edx + iret + +.global prot_domains_launch_kernel +prot_domains_launch_kernel: +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING + mov $GDT_SEL_DATA, %eax + mov %eax, %ds + mov %eax, %es + mov %eax, %fs + mov %eax, %gs +#else + mov $GDT_SEL_LDT(DOM_ID_kern), %eax + lldt %ax + call multi_segment_launch_kernel +#endif + /* init interrupt return stack: */ + pushl $GDT_SEL_STK + lea stacks_main, %eax + /* matches STACKS_INIT_TOP, plus 4 since an address has been consumed: */ + add $(STACKS_SIZE_MAIN - 4), %eax + pushl %eax + pushl $EFLAGS_IOPL(PRIV_LVL_INT) + pushl $GDT_SEL_CODE + pushl $0 /* will be overwritten by syscall_dispatcher_impl */ + /* fastcall convention: */ + mov %esp, %ecx + call prot_domains_launch_kernel_impl + iretl diff --git a/cpu/x86/mm/syscalls-int.c b/cpu/x86/mm/syscalls-int.c new file mode 100644 index 000000000..6820d3264 --- /dev/null +++ b/cpu/x86/mm/syscalls-int.c @@ -0,0 +1,318 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "prot-domains.h" +#include "tss.h" +#include "helpers.h" +#include "stacks.h" +#include "idt.h" +#include "syscalls.h" +#include "gdt.h" +#include "gdt-layout.h" +#include "interrupt.h" + +/** + * Current protection domain. Not protected, since it is just a convenience + * variable to avoid unneeded protection domain switches. + */ +dom_id_t cur_dom = DOM_ID_app; + +/* defined in syscalls-int-asm.S */ +void prot_domains_sysret_dispatcher(void); + +/* Maximum depth of inter-domain call stack */ +#define MAX_INTER_DOM_CALL_STK_SZ 4 + +/* Protected call stack for inter-domain system calls. The stack grows up. */ +static volatile dom_id_t ATTR_BSS_KERN + inter_dom_call_stk[MAX_INTER_DOM_CALL_STK_SZ]; + +/* Pointer to the next (free) slot in the inter-domain call stack */ +static int ATTR_BSS_KERN inter_dom_call_stk_ptr; + +/*---------------------------------------------------------------------------*/ +static inline void __attribute__((always_inline)) +update_eflags(dom_id_t from_id, dom_id_t to_id, interrupt_stack_t *intr_stk) +{ + if((to_id == DOM_ID_app) && + (DT_SEL_GET_RPL(intr_stk->cs) == PRIV_LVL_USER)) { + /* Only enable interrupts in the application protection domain cooperative + * scheduling context. + */ + intr_stk->eflags |= EFLAGS_IF; + } else { + intr_stk->eflags &= ~EFLAGS_IF; + } +} +/*---------------------------------------------------------------------------*/ +static inline void __attribute__((always_inline)) +dispatcher_tail(dom_id_t from_id, dom_id_t to_id, interrupt_stack_t *intr_stk) +{ + cur_dom = to_id; + + prot_domains_switch(from_id, to_id, intr_stk); + + prot_domains_set_wp(true); + + update_eflags(from_id, to_id, intr_stk); +} +/*---------------------------------------------------------------------------*/ +int main(void); +static inline void __attribute__((always_inline)) +syscall_dispatcher_tail(interrupt_stack_t *intr_stk, + dom_id_t to_id, + uint32_t syscall_eip) +{ + dom_id_t from_id; + uint32_t tmp; + volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE *from_dkd, *to_dkd; + + uint32_t loc_call_stk_ptr; + + to_dkd = prot_domains_kern_data + to_id; + + /* This implementation of protection domains is non-reentrant. For example, + * it stores the return address taken from the stack of a caller domain + * while dispatching a system call and stores it in a single field in the + * kernel data associated with that protection domain. That model does not + * permit reentrancy. + */ + KERN_READL(tmp, to_dkd->flags); + if((tmp & PROT_DOMAINS_FLAG_BUSY) == PROT_DOMAINS_FLAG_BUSY) { + halt(); + } + tmp |= PROT_DOMAINS_FLAG_BUSY; + KERN_WRITEL(to_dkd->flags, tmp); + + /* Update the interrupt stack so that the IRET instruction will return to the + * system call entrypoint. + */ + intr_stk->eip = syscall_eip; + + KERN_READL(loc_call_stk_ptr, inter_dom_call_stk_ptr); + /* Lookup the information for the caller */ + KERN_READL(from_id, inter_dom_call_stk[loc_call_stk_ptr - 1]); + from_dkd = prot_domains_kern_data + from_id; + + /* Save the current return address from the unprivileged stack to a protected + * location in the kernel-owned data structure. This enforces return + * entrypoint control. + */ + KERN_WRITEL(from_dkd->orig_ret_addr, *(uintptr_t *)intr_stk->esp); + /* Update the unprivileged stack so that when the system call body is + * complete, it will invoke the system call return stub. + */ + *((uintptr_t *)intr_stk->esp) = (uintptr_t)prot_domains_sysret_stub; + + if(MAX_INTER_DOM_CALL_STK_SZ <= loc_call_stk_ptr) { + halt(); + } + KERN_WRITEL(inter_dom_call_stk[loc_call_stk_ptr], to_id); + + loc_call_stk_ptr++; + KERN_WRITEL(inter_dom_call_stk_ptr, loc_call_stk_ptr); + + dispatcher_tail(from_id, to_id, intr_stk); +} +/*---------------------------------------------------------------------------*/ +void __attribute__((fastcall)) +prot_domains_syscall_dispatcher_impl(interrupt_stack_t *intr_stk, + dom_id_t to_id, + syscalls_entrypoint_t *syscall) +{ + uint32_t tmp; + uint32_t syscall_eip; + + if(PROT_DOMAINS_ACTUAL_CNT <= to_id) { + halt(); + } + + /* Get the approved entrypoint for the system call being invoked */ + + if(!((((uintptr_t)syscalls_entrypoints) <= (uintptr_t)syscall) && + (((uintptr_t)syscall) < (uintptr_t)syscalls_entrypoints_end) && + (((((uintptr_t)syscall) - (uintptr_t)syscalls_entrypoints) + % sizeof(syscalls_entrypoint_t)) == 0))) { + /* Assert is not usable when switching protection domains */ + halt(); + } + + KERN_READL(tmp, syscall->doms); + if((BIT(to_id) & tmp) == 0) { + halt(); + } + + KERN_READL(syscall_eip, syscall->entrypoint); + + prot_domains_set_wp(false); + + syscall_dispatcher_tail(intr_stk, to_id, syscall_eip); +} +/*---------------------------------------------------------------------------*/ +int main(void); +void __attribute__((fastcall)) +prot_domains_launch_kernel_impl(interrupt_stack_t *intr_stk) +{ + KERN_WRITEL(inter_dom_call_stk[0], DOM_ID_app); + + KERN_WRITEL(inter_dom_call_stk_ptr, 1); + + syscall_dispatcher_tail(intr_stk, DOM_ID_kern, (uint32_t)main); +} +/*---------------------------------------------------------------------------*/ +void __attribute__((fastcall)) +prot_domains_sysret_dispatcher_impl(interrupt_stack_t *intr_stk) +{ + dom_id_t from_id, to_id; + uint32_t loc_call_stk_ptr; + uint32_t flags; + + KERN_READL(loc_call_stk_ptr, inter_dom_call_stk_ptr); + if(loc_call_stk_ptr <= 1) { + halt(); + } + + KERN_READL(from_id, inter_dom_call_stk[loc_call_stk_ptr - 1]); + KERN_READL(to_id, inter_dom_call_stk[loc_call_stk_ptr - 2]); + + KERN_READL(intr_stk->eip, + prot_domains_kern_data[to_id].orig_ret_addr); + + prot_domains_set_wp(false); + + KERN_READL(flags, prot_domains_kern_data[from_id].flags); + flags &= ~PROT_DOMAINS_FLAG_BUSY; + KERN_WRITEL(prot_domains_kern_data[from_id].flags, flags); + + KERN_WRITEL(inter_dom_call_stk_ptr, loc_call_stk_ptr - 1); + + dispatcher_tail(from_id, to_id, intr_stk); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Lookup the current protection domain. + * \return Kernel data structure for the current protection domain. + */ +static volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE * +get_current_domain(void) +{ + uint32_t loc_call_stk_ptr; + dom_id_t id; + KERN_READL(loc_call_stk_ptr, inter_dom_call_stk_ptr); + KERN_READL(id, inter_dom_call_stk[loc_call_stk_ptr - 1]); + return prot_domains_kern_data + id; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Check whether the protection domain is authorized to perform port + * I/O from the cooperative scheduling context. + * \param dkd Protection domain to check + * \return Result of the check as a Boolean value + */ +static bool +needs_port_io(volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE *dkd) +{ + uint32_t dkd_flags; + KERN_READL(dkd_flags, dkd->flags); + return (dkd_flags & PROT_DOMAINS_FLAG_PIO) == PROT_DOMAINS_FLAG_PIO; +} +/*---------------------------------------------------------------------------*/ +/* Mark the context parameter as volatile so that writes to it will not get + * optimized out. This parameter is not handled like ordinary function + * parameters. It actually partially includes the contents of the exception + * stack, so updates to those locations can affect the operation of the + * subsequent interrupt return. + */ +static void +gp_fault_handler(volatile struct interrupt_context context) +{ + uint32_t cs_lim; + uint8_t opcode; + + volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE *dkd = get_current_domain(); + if (needs_port_io(dkd)) { + __asm__ __volatile__ ( + "mov %%cs, %0\n\t" + "lsl %0, %0\n\t" + : "=r"(cs_lim)); + + if (cs_lim < context.eip) { + halt(); + } + + /* Load first byte of faulting instruction */ + __asm__ __volatile__ ( + "movb %%cs:%1, %0" + : "=q"(opcode) + : "m"(*(uint8_t *)context.eip)); + + switch (opcode) { + case 0xEC: /* inb */ + context.eax = (context.eax & ~0xFF) | inb((uint16_t)context.edx); + break; + case 0xED: /* inl */ + context.eax = inl((uint16_t)context.edx); + break; + case 0xEE: /* outb */ + outb((uint16_t)context.edx, (uint8_t)context.eax); + break; + case 0xEF: /* outl */ + outl((uint16_t)context.edx, context.eax); + break; + default: + halt(); + } + + /* Skip the faulting port I/O instruction that was emulated. */ + context.eip++; + } else { + halt(); + } +} +/*---------------------------------------------------------------------------*/ +void +syscalls_int_init(void) +{ + tss_init(); + + SET_EXCEPTION_HANDLER(13, 1, gp_fault_handler); + + /* Register system call dispatchers: */ + + idt_set_intr_gate_desc(PROT_DOMAINS_SYSCALL_DISPATCH_INT, + (uint32_t)prot_domains_syscall_dispatcher, + GDT_SEL_CODE_EXC, + PRIV_LVL_USER); + idt_set_intr_gate_desc(PROT_DOMAINS_SYSRET_DISPATCH_INT, + (uint32_t)prot_domains_sysret_dispatcher, + GDT_SEL_CODE_EXC, + PRIV_LVL_USER); +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/mm/syscalls-int.h b/cpu/x86/mm/syscalls-int.h new file mode 100644 index 000000000..a5478d1c5 --- /dev/null +++ b/cpu/x86/mm/syscalls-int.h @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_MM_SYSCALLS_INT_H_ +#define CPU_X86_MM_SYSCALLS_INT_H_ + +/** Software interrupt number for dispatching a system call */ +#define PROT_DOMAINS_SYSCALL_DISPATCH_INT 100 +/** Software interrupt number for returning from a system call */ +#define PROT_DOMAINS_SYSRET_DISPATCH_INT 101 + +#if !__ASSEMBLER__ + +#include + +extern dom_id_t cur_dom; + +#define SYSCALLS_STUB_EPILOGUE(nm) \ + /* Load the system call identifier into EAX, as required by */ \ + /* prot_domains_syscall_dispatcher: */ \ + " mov $" EXP_STRINGIFY(_syscall_ent_##nm) ", %eax\n\t" \ + /* Check whether the server protection domain is already active: */ \ + " cmp %edx, cur_dom\n\t" \ + /* If so, skip the system call dispatcher and directly invoke the */ \ + /* system call body: */ \ + " je _syscall_" #nm "\n\t" \ + " int $" EXP_STRINGIFY(PROT_DOMAINS_SYSCALL_DISPATCH_INT) "\n\t" + +#define SYSCALLS_STUB(nm) \ + SYSCALLS_ALLOC_ENTRYPOINT(nm); \ + asm ( \ + ".text\n\t" \ + ".global " #nm "\n\t" \ + #nm ":\n\t" \ + /* First, load server protection domain ID into EDX, as required by */ \ + /* prot_domains_syscall_dispatcher: */ \ + /* Skip past return address on stack to obtain address of protection */ \ + /* domain ID parameter: */ \ + " mov 4(%esp), %edx\n\t" \ + SYSCALLS_STUB_EPILOGUE(nm)) + +#define SYSCALLS_STUB_SINGLETON(nm, dcd) \ + SYSCALLS_ALLOC_ENTRYPOINT(nm); \ + asm ( \ + ".text\n\t" \ + ".global " #nm "\n\t" \ + #nm ":\n\t" \ + /* First, load server protection domain ID into EDX, as required by */ \ + /* prot_domains_syscall_dispatcher: */ \ + " mov %" SEG_KERN "s:" #dcd ", %edx\n\t" \ + SYSCALLS_STUB_EPILOGUE(nm)) + +void syscalls_int_init(void); + +void prot_domains_sysret_stub(void); + +/* Inter-privilege level interrupt stack with no error code. */ +typedef struct interrupt_stack { + uint32_t eip; + uint32_t cs; + uint32_t eflags; + uint32_t esp; + uint32_t ss; +} interrupt_stack_t; + +#if 0 +/* Declaration only included for documentation purposes: */ +/** + * \brief Switch to a different protection domain. + * \param from_id Origin protection domain. + * \param to_id Destination protection domain. + * \return Segment selector for kernel data access (only used for + * multi-segment implementations). + */ +uint32_t prot_domains_switch(dom_id_t from_id, + dom_id_t to_id, + interrupt_stack_t *intr_stk); +#endif + +#endif + +#endif /* CPU_X86_MM_SYSCALLS_INT_H_ */ diff --git a/cpu/x86/mm/syscalls.h b/cpu/x86/mm/syscalls.h new file mode 100644 index 000000000..cae8ff2f5 --- /dev/null +++ b/cpu/x86/mm/syscalls.h @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_MM_SYSCALLS_H_ +#define CPU_X86_MM_SYSCALLS_H_ + +#include "helpers.h" +#include "prot-domains.h" +#include + +typedef uint32_t dom_id_bitmap_t; + +typedef struct syscalls_entrypoint { + uintptr_t entrypoint; + dom_id_bitmap_t doms; +} syscalls_entrypoint_t; +extern syscalls_entrypoint_t ATTR_KERN_ADDR_SPACE syscalls_entrypoints[]; +extern syscalls_entrypoint_t ATTR_KERN_ADDR_SPACE syscalls_entrypoints_end[]; + +#define SYSCALLS_ACTUAL_CNT (syscalls_entrypoints_end - syscalls_entrypoints) + +#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__NONE + +#define SYSCALLS_ALLOC_ENTRYPOINT(nm) \ + syscalls_entrypoint_t __attribute__((section(".syscall_bss"))) \ + ATTR_KERN_ADDR_SPACE _syscall_ent_##nm + +#define SYSCALLS_INIT(nm) \ + KERN_WRITEL(_syscall_ent_##nm.entrypoint, (uintptr_t)_syscall_##nm); \ + KERN_WRITEL(_syscall_ent_##nm.doms, 0) + +#define SYSCALLS_DEFINE(nm, ...) \ + void _syscall_##nm(__VA_ARGS__); \ + SYSCALLS_STUB(nm); \ + void _syscall_##nm(__VA_ARGS__) + +#define SYSCALLS_DEFINE_SINGLETON(nm, dcd, ...) \ + void _syscall_##nm(__VA_ARGS__); \ + SYSCALLS_STUB_SINGLETON(nm, dcd); \ + void _syscall_##nm(__VA_ARGS__) + +#define SYSCALLS_AUTHZ_UPD(nm, drv, set) \ + { \ + dom_id_t _sc_tmp_id; \ + dom_id_bitmap_t _sc_tmp_bm; \ + KERN_READL(_sc_tmp_id, (drv).dom_id); \ + KERN_READL(_sc_tmp_bm, _syscall_ent_##nm.doms); \ + if(set) { \ + _sc_tmp_bm |= BIT(_sc_tmp_id); \ + } else { \ + _sc_tmp_bm &= ~BIT(_sc_tmp_id); \ + } \ + KERN_WRITEL(_syscall_ent_##nm.doms, _sc_tmp_bm); \ + } + +/** + * Check that any untrusted pointer that could have been influenced by a caller + * (i.e. a stack parameter or global variable) refers to a location at or above + * a certain stack boundary and halt otherwise. This is used to prevent a + * protection domain from calling a different protection domain and passing a + * pointer that references a location in the callee's stack other than its + * parameters. + * + * This also checks that the pointer is either within the stack region or the + * shared data region, which is important for preventing redirection of data + * accesses to MMIO or metadata regions. This check is omitted for multi- + * segment protection domain implementations, since the segment settings + * already enforce this property for pointers dereferenced in DS. Pointers + * that can be influenced by a caller should not be dereferenced in any other + * segment. + * + * The pointer is both validated and copied to a new storage location, which + * must be within the callee's local stack region (excluding the parameter + * region). This is to mitigate scenarios such as two pointers being validated + * and an adversary later inducing a write through one of the pointers to the + * other pointer to corrupt the latter pointer before it is used. + * + * The frame address is adjusted to account for the first word pushed on the + * local frame and the return address, since neither of those should ever be + * referenced by an incoming pointer. In particular, if an incoming pointer + * references the return address, it could potentially redirect execution with + * the privileges of the callee protection domain. + */ +#if X86_CONF_PROT_DOMAINS_MULTI_SEG +#define PROT_DOMAINS_VALIDATE_PTR(validated, untrusted, sz) \ + validated = untrusted; \ + if(((uintptr_t)(validated)) < \ + ((2 * sizeof(uintptr_t)) + (uintptr_t)__builtin_frame_address(0))) { \ + halt(); \ + } +#else +#define PROT_DOMAINS_VALIDATE_PTR(validated, untrusted, sz) \ + validated = untrusted; \ + if((((uintptr_t)(validated)) < \ + ((2 * sizeof(uintptr_t)) + (uintptr_t)__builtin_frame_address(0))) || \ + (((uintptr_t)&_edata_addr) <= (((uintptr_t)(validated)) + (sz)))) { \ + halt(); \ + } +#endif + +#else + +#define SYSCALLS_ALLOC_ENTRYPOINT(nm) +#define SYSCALLS_INIT(nm) +#define SYSCALLS_DEFINE(nm, ...) void nm(__VA_ARGS__) +#define SYSCALLS_DEFINE_SINGLETON(nm, dcd, ...) void nm(__VA_ARGS__) +#define SYSCALLS_AUTHZ_UPD(nm, drv, set) +#define PROT_DOMAINS_VALIDATE_PTR(validated, untrusted, sz) validated = untrusted + +#endif + +#define SYSCALLS_AUTHZ(nm, drv) SYSCALLS_AUTHZ_UPD(nm, drv, true) +#define SYSCALLS_DEAUTHZ(nm, drv) SYSCALLS_AUTHZ_UPD(nm, drv, false) + +#endif /* CPU_X86_MM_SYSCALLS_H_ */ diff --git a/cpu/x86/mm/tss-prot-domains-asm.S b/cpu/x86/mm/tss-prot-domains-asm.S new file mode 100644 index 000000000..45832a62c --- /dev/null +++ b/cpu/x86/mm/tss-prot-domains-asm.S @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2015, Intel Corporation. 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. + */ + +.text + +/* Initialize the TSS fields in prot_domains_reg accordingly: + * Note: Each of these must be a callee-saved register, so that they are + * restored to their original values prior to the task returning. This will + * result in the same values being loaded when the task is next invoked. + */ +#define CUR_DOM_ID_BITMAP esi + +/* Must match SEG_KERN (plus the trailing 's') in multi-segment.h */ +#define SEG_KERN fs + +.global prot_domains_syscall_dispatcher +prot_domains_syscall_dispatcher: +#define PROT_DOMAINS_SYSCALL eax + mov prot_domains_syscall, %PROT_DOMAINS_SYSCALL + cmp $syscalls_entrypoints, %PROT_DOMAINS_SYSCALL + jl halt + cmp $syscalls_entrypoints_end, %PROT_DOMAINS_SYSCALL + jnl halt +#define SYSCALLS_ENTRYPOINTS_ALIGN_MASK ebp + mov $3, %SYSCALLS_ENTRYPOINTS_ALIGN_MASK + and %PROT_DOMAINS_SYSCALL, %SYSCALLS_ENTRYPOINTS_ALIGN_MASK + jnz halt + + /* Compare allowed domains bitmask against current domain ID bitmap. If + * the check fails, then the current domain ID bitmap value will be zeroed + * out, which could cause incorrect behavior in the future. However, the + * response to a failed check is to halt the system, so destroying the + * current domain ID bitmap value will have no effect. + */ + and %SEG_KERN:4(%PROT_DOMAINS_SYSCALL), %CUR_DOM_ID_BITMAP + jz halt + + mov prot_domains_main_esp, %esp + + /* Must be a callee-saved register: */ +#define ORIG_RET_ADDR edi + /* Update the caller's stack to return back to here */ + pop %ORIG_RET_ADDR + push $sysret_dispatcher + /* Jump to the system call body */ + jmp *%SEG_KERN:(%PROT_DOMAINS_SYSCALL) + +sysret_dispatcher: + push %ORIG_RET_ADDR + + iret + + /* The task will resume here for the next system call, so it is necessary + * to jump back to the top. + */ + jmp prot_domains_syscall_dispatcher + +.global dev_not_avail_isr +dev_not_avail_isr: + clts + iret diff --git a/cpu/x86/mm/tss-prot-domains.c b/cpu/x86/mm/tss-prot-domains.c new file mode 100644 index 000000000..40041a6d1 --- /dev/null +++ b/cpu/x86/mm/tss-prot-domains.c @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "gdt.h" +#include "helpers.h" +#include "idt.h" +#include "prot-domains.h" +#include "stacks.h" +#include "syscalls.h" +#include "tss.h" + +uint32_t prot_domains_main_esp; +syscalls_entrypoint_t ATTR_KERN_ADDR_SPACE *prot_domains_syscall; + +/*---------------------------------------------------------------------------*/ +void app_main(void); +void +prot_domains_reg(dom_client_data_t ATTR_KERN_ADDR_SPACE *dcd, + uintptr_t mmio, size_t mmio_sz, + uintptr_t meta, size_t meta_sz, + bool pio) +{ + segment_desc_t desc; + uint32_t eflags; + dom_id_t dom_id; + volatile struct dom_kern_data ATTR_KERN_ADDR_SPACE *dkd; + + KERN_READL(dom_id, dcd->dom_id); + + dkd = prot_domains_kern_data + dom_id; + + prot_domains_reg_multi_seg(dkd, mmio, mmio_sz, meta, meta_sz); + + /* Only the kernel protection domain requires port I/O access outside of the + * interrupt handlers. + */ + eflags = EFLAGS_IOPL(pio ? PRIV_LVL_USER : PRIV_LVL_INT); + if(dom_id == DOM_ID_app) { + eflags |= EFLAGS_IF; + } + + /* Keep this initialization in sync with the register definitions in + * tss-prot-domains-asm.S. + */ + KERN_WRITEL(dkd->tss.ebp, 0); + KERN_WRITEL(dkd->tss.ebx, 0); + KERN_WRITEL(dkd->tss.esi, BIT(dom_id)); + KERN_WRITEL(dkd->tss.eip, + (dom_id == DOM_ID_app) ? + (uint32_t)app_main : + (uint32_t)prot_domains_syscall_dispatcher); + KERN_WRITEL(dkd->tss.cs, GDT_SEL_CODE); + KERN_WRITEL(dkd->tss.ds, GDT_SEL_DATA); + KERN_WRITEL(dkd->tss.es, GDT_SEL_DATA); + KERN_WRITEL(dkd->tss.fs, LDT_SEL_KERN); + KERN_WRITEL(dkd->tss.gs, + (meta_sz == 0) ? GDT_SEL_NULL : LDT_SEL_META); + KERN_WRITEL(dkd->tss.ss, GDT_SEL_STK); + /* This stack pointer is only actually used in application protection domain. + * Other domains enter at system call dispatcher, which switches to main + * stack. + */ + KERN_WRITEL(dkd->tss.esp, + /* Two return addresses have been consumed: */ + STACKS_INIT_TOP + (2 * sizeof(uintptr_t))); + KERN_WRITEL(dkd->tss.eflags, eflags); + KERN_WRITEL(dkd->tss.ldt, GDT_SEL_LDT(dom_id)); + KERN_WRITEL(dkd->tss.esp2, STACKS_SIZE_MAIN + STACKS_SIZE_INT); + KERN_WRITEL(dkd->tss.ss2, GDT_SEL_STK_INT); + KERN_WRITEL(dkd->tss.esp0, + STACKS_SIZE_MAIN + STACKS_SIZE_INT + STACKS_SIZE_EXC); + KERN_WRITEL(dkd->tss.ss0, GDT_SEL_STK_EXC); + KERN_WRITEW(dkd->tss.t, 0); + KERN_WRITEW(dkd->tss.iomap_base, sizeof(tss_t)); + KERN_WRITEL(dkd->tss.cr3, 0); + + segment_desc_init(&desc, + KERN_DATA_OFF_TO_PHYS_ADDR((uint32_t)&(dkd->tss)), + sizeof(dkd->tss), + /* It should be possible for code at any privilege level to invoke the task's + * system call dispatcher. + */ + SEG_FLAG(DPL, PRIV_LVL_USER) | SEG_TYPE_TSS32_AVAIL); + + gdt_insert(GDT_IDX_TSS(dom_id), desc); + + KERN_WRITEW(dcd->tss_sel, GDT_SEL(GDT_IDX_TSS(dom_id), PRIV_LVL_USER)); +} +/*---------------------------------------------------------------------------*/ +void dev_not_avail_isr(void); +void +prot_domains_impl_init(void) +{ + __asm__ __volatile__ ("ltr %0" :: "r" ((uint16_t)GDT_SEL_TSS(DOM_ID_kern))); + __asm__ __volatile__ ("lldt %0" :: "r" ((uint16_t)GDT_SEL_LDT(DOM_ID_kern))); + + idt_set_intr_gate_desc(7, + (uint32_t)dev_not_avail_isr, + GDT_SEL_CODE_EXC, PRIV_LVL_EXC); +} +/*---------------------------------------------------------------------------*/ +int main(); +void +prot_domains_launch_kernel(void) +{ + multi_segment_launch_kernel(); + + /* Activate kernel protection domain, entering the kernel at main. */ + __asm__ __volatile__ ( + "pushl %[_ss_]\n\t" + "pushl %[_top_of_stk_]\n\t" + "pushl %[_eflags_]\n\t" + "pushl %[_cs_]\n\t" + "pushl %[_kern_start_]\n\t" + "iretl\n\t" + : + : [_ss_] "g" (GDT_SEL_STK), + [_eflags_] "g" (EFLAGS_IOPL(PRIV_LVL_USER)), + [_cs_] "g" (GDT_SEL_CODE), + [_kern_start_] "g" (main), + /* one address has already been consumed */ + [_top_of_stk_] "g" (STACKS_INIT_TOP + sizeof(uint32_t)) + ); +} +/*---------------------------------------------------------------------------*/ +void +prot_domains_launch_app() +{ + far_pointer_t app_ptr = { 0, GDT_SEL_TSS(DOM_ID_app) }; + __asm__ __volatile__ ("ljmp *%0" :: "m" (app_ptr)); +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/mm/tss-prot-domains.h b/cpu/x86/mm/tss-prot-domains.h new file mode 100644 index 000000000..d61d97504 --- /dev/null +++ b/cpu/x86/mm/tss-prot-domains.h @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_MM_TSS_PROT_DOMAINS_H_ +#define CPU_X86_MM_TSS_PROT_DOMAINS_H_ + +#include +#include +#include +#include "ldt-layout.h" +#include "segmentation.h" +#include "tss.h" + +struct dom_kern_data { + /** Task State Segment */ + tss_t tss; + /** Local Descriptor Table with per-domain descriptors */ + segment_desc_t ldt[LDT_NUM_DESC]; +} __attribute__((packed)); + +/* relies on dom_kern_data: */ +#include "multi-segment.h" + +/* relies on ATTR_KERN_ADDR_SPACE: */ +#include "syscalls.h" + +/** + * Data associated with each protection domain that is owned by clients of that + * domain and used to identify the domain. + */ +struct dom_client_data { + dom_id_t dom_id; + /** The selector is only 16 bits, but it is padded to 32 bits. */ + uint32_t tss_sel; +}; + +extern uint32_t prot_domains_main_esp; + +#define SYSCALLS_STUB_MIDDLE(nm) \ + /* If already in the callee protection domain, skip the protection */ \ + /* domain switch and directly invoke the system call body */ \ + " je _syscall_" #nm "\n\t" \ + " movl $" EXP_STRINGIFY(_syscall_ent_##nm) ", prot_domains_syscall\n\t" \ + " mov %esp, prot_domains_main_esp\n\t" + +#define SYSCALLS_STUB(nm) \ + SYSCALLS_ALLOC_ENTRYPOINT(nm); \ + asm ( \ + ".text\n\t" \ + ".global " #nm "\n\t" \ + #nm ":\n\t" \ + " str %ax\n\t" \ + /* Compare current Task Register selector to selector for callee */ \ + /* protection domain, in tss_sel field of dom_client_data */ \ + " cmpw %ax, 8(%esp)\n\t" \ + SYSCALLS_STUB_MIDDLE(nm) \ + /* This will treat the dom_id field as the offset for the call, but */ \ + /* that is ignored when performing a far call to a task */ \ + " lcall *4(%esp)\n\t" \ + " ret\n\t") + +#define SYSCALLS_STUB_SINGLETON(nm, dcd) \ + SYSCALLS_ALLOC_ENTRYPOINT(nm); \ + asm ( \ + ".text\n\t" \ + ".global " #nm "\n\t" \ + #nm ":\n\t" \ + " str %ax\n\t" \ + /* Compare current Task Register selector to selector for callee */ \ + /* protection domain, in tss_sel field of dom_client_data */ \ + " cmpw %ax, %" SEG_KERN "s:(4 + " #dcd ")\n\t" \ + SYSCALLS_STUB_MIDDLE(nm) \ + /* This will treat the dom_id field as the offset for the call, but */ \ + /* that is ignored when performing a far call to a task */ \ + " lcall *%" SEG_KERN "s:" #dcd "\n\t" \ + " ret\n\t") + +#define PROT_DOMAINS_ENTER_ISR(exc) \ + MULTI_SEGMENT_ENTER_ISR(exc) \ + /* It is possible that the system call dispatcher is being interrupted, */ \ + /* and some interrupt handlers perform system calls. Thus, it is */ \ + /* necessary to save and restore the system call dispatcher parameters */ \ + /* (in callee-saved registers). */ \ + "mov prot_domains_main_esp, %%esi\n\t" \ + "mov prot_domains_syscall, %%edi\n\t" \ + PROT_DOMAINS_ENTER_ISR_COMMON(exc) +#define PROT_DOMAINS_LEAVE_ISR(exc) \ + PROT_DOMAINS_LEAVE_ISR_COMMON(exc) \ + "mov %%edi, prot_domains_syscall\n\t" \ + "mov %%esi, prot_domains_main_esp\n\t" \ + MULTI_SEGMENT_LEAVE_ISR(exc) + +/* Allocate two additional GDT entries for each protection domain. Note that + * the particular storage allocated by this statement may actually be used for + * some other protection domain, depending on how the linker happens to arrange + * all of the GDT storage. The GDT_IDX_TSS and GDT_IDX_LDT macros in + * gdt-layout.h determine which storage is used for each protection domain. + * Thus, this storage should not be referenced directly by its variable name. + */ +#define PROT_DOMAINS_ALLOC_IMPL(nm) \ + static segment_desc_t ATTR_BSS_GDT_MID _gdt_storage_##nm[2] + +#endif /* CPU_X86_MM_TSS_PROT_DOMAINS_H_ */ diff --git a/cpu/x86/mm/tss.c b/cpu/x86/mm/tss.c new file mode 100644 index 000000000..b6e0f3deb --- /dev/null +++ b/cpu/x86/mm/tss.c @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "gdt.h" +#include "gdt-layout.h" +#include "prot-domains.h" +#include "segmentation.h" +#include "stacks.h" +#include "tss.h" + +/* System-wide TSS */ +tss_t ATTR_BSS_KERN sys_tss; + +static segment_desc_t ATTR_BSS_GDT sys_tss_desc; + +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize system-wide TSS. + */ +void +tss_init(void) +{ + segment_desc_t seg_desc; + + /* Initialize TSS */ + KERN_WRITEW(sys_tss.iomap_base, sizeof(sys_tss)); + KERN_WRITEL(sys_tss.esp2, ((uint32_t)stacks_int) + STACKS_SIZE_INT); + KERN_WRITEL(sys_tss.ss2, GDT_SEL_STK_INT); + KERN_WRITEL(sys_tss.esp0, ((uint32_t)stacks_exc) + STACKS_SIZE_EXC); + KERN_WRITEL(sys_tss.ss0, GDT_SEL_STK_EXC); + + segment_desc_init(&seg_desc, + KERN_DATA_OFF_TO_PHYS_ADDR(&sys_tss), sizeof(sys_tss), + SEG_FLAG(DPL, PRIV_LVL_EXC) | + SEG_DESCTYPE_SYS | SEG_TYPE_TSS32_AVAIL); + gdt_insert(GDT_IDX_OF_DESC(&sys_tss_desc), seg_desc); + + __asm__ __volatile__ ( + "ltr %0" + : + : "r" ((uint16_t)GDT_SEL_OF_DESC(&sys_tss_desc, 0))); +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/x86/mm/tss.h b/cpu/x86/mm/tss.h new file mode 100644 index 000000000..e8431d388 --- /dev/null +++ b/cpu/x86/mm/tss.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2015, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_MM_TSS_H_ +#define CPU_X86_MM_TSS_H_ + +#include + +/** + * Task State Segment. Used by the CPU to manage switching between + * different protection domains (tasks). The current task is referenced + * by the Task Register. When the CPU switches away from a task due to + * a far call, etc., it updates the associated in-memory TSS with the + * current state of the task. It then loads CPU state from the TSS for + * the new task. See Intel Combined Manual, Vol. 3, Chapter 7 for more + * details. + */ +typedef struct tss { + uint32_t prev_tsk; /**< The selector of the task that called this one, if applicable */ + uint32_t esp0; /**< Stack pointer for ring 0 code in this task */ + uint32_t ss0; /**< Stack segment selector for ring 0 code in this task */ + uint32_t esp1; /**< Stack pointer for ring 1 code in this task */ + uint32_t ss1; /**< Stack segment selector for ring 1 code in this task */ + uint32_t esp2; /**< Stack pointer for ring 2 code in this task */ + uint32_t ss2; /**< Stack segment selector for ring 2 code in this task */ + uint32_t cr3; /**< CR3 for this task when paging is enabled */ + uint32_t eip; /**< Stored instruction pointer value */ + uint32_t eflags; /**< Settings for EFLAGS register */ + /** General purpose register values */ + uint32_t eax, ecx, edx, ebx, esp, ebp, esi, edi; + /** Segment register selector values */ + uint32_t es, cs, ss, ds, fs, gs; + /** Selector for Local Descriptor Table */ + uint32_t ldt; + /** Debug-related flag */ + uint16_t t; + /** Offset from base of TSS to base of IO permission bitmap, if one is installed */ + uint16_t iomap_base; +} tss_t; + +void tss_init(void); + +#endif /* CPU_X86_TSS_H_ */ diff --git a/cpu/x86/quarkX1000.ld b/cpu/x86/quarkX1000.ld index b50c47bb8..d4ea66aa6 100644 --- a/cpu/x86/quarkX1000.ld +++ b/cpu/x86/quarkX1000.ld @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,30 +37,39 @@ SECTIONS { OS-Dev Wiki says it is common for kernels to start at 1M. Addresses before that are used by BIOS/EFI, the bootloader and memory-mapped I/O. - The UEFI GenFw program inserts a 0x240-byte offset between the image base and + The UEFI GenFw program inserts a 0x220-byte offset between the image base and the .text section. We add that same offset here to align the symbols in the UEFI DLL with those in the final UEFI binary to make debugging easier. We also apply 32-byte alignments to sections rather than more conventional 4K-byte alignments to avoid symbols being shifted from the intermediate DLL to the final UEFI image as would occur if the GenFw program shifted the .text section - from a higher, 4K-aligned offset to the 0x240-byte offset from the image base. + from a higher, 4K-aligned offset to the 0x220-byte offset from the image base. Such shifting may make debugging more difficult by preventing the DLL from being a directly-useful source of symbol information. The debugging symbols are not included in the final UEFI image. The GenFw program uses a minimum section alignment of 32 bytes, so smaller alignment granularities may also result in symbol perturbation. */ - . = 1M + 0x240; + . = 1M + 0x220; .text ALIGN (32) : { KEEP(*(.multiboot)) + *(.boot_text) *(.text*) } .rodata ALIGN (32) : { *(.rodata*) + + _sdata_kern_startup_func = .; + KEEP(*(.kern_startup_func)) + _edata_kern_startup_func = .; + + _sdata_shared_isr = .; + KEEP(*(.shared_isr_data*)) + _edata_shared_isr = .; } .data ALIGN (32) : @@ -71,6 +80,17 @@ SECTIONS { .bss ALIGN (32) : { *(COMMON) + *(.main_stack) *(.bss*) + + *(.gdt_bss_start) + /* + The other GDT-related sections defined in gdt.h are only used when + protection domain support is enabled. Thus, they do not need to be + included here. + */ + _ebss_gdt_addr = .; } + + _ebss_pre_dma_addr = ALIGN(32); } diff --git a/cpu/x86/quarkX1000_dma.ld b/cpu/x86/quarkX1000_dma.ld new file mode 100644 index 000000000..4cecac839 --- /dev/null +++ b/cpu/x86/quarkX1000_dma.ld @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. 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. + */ + +SECTIONS { + + .bss.dma (NOLOAD) : AT(_ebss_pre_dma_addr) ALIGN (32) + { + /* IMRs are used to restrict DMA, and they require 1K physical address alignment. */ + . += ALIGN(_ebss_pre_dma_addr, 1K) - ALIGN(_ebss_pre_dma_addr, 32); + *(.dma_bss) + } + + _sbss_dma_addr = LOADADDR(.bss.dma) + ALIGN(_ebss_pre_dma_addr, 1K) - ALIGN(_ebss_pre_dma_addr, 32); + /* + Effectively pointing beyond the end of .bss.dma is acceptable, since + .bss.dma is the last section in memory. + */ + _ebss_dma_addr = ALIGN(LOADADDR(.bss.dma) + SIZEOF(.bss.dma), 1K); + +} diff --git a/cpu/x86/quarkX1000_multi_seg.ld b/cpu/x86/quarkX1000_multi_seg.ld new file mode 100644 index 000000000..c4e6293cf --- /dev/null +++ b/cpu/x86/quarkX1000_multi_seg.ld @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2015, Intel Corporation. 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. + */ + +OUTPUT_FORMAT("elf32-i386") + +ENTRY(start) + +/* + The TSS-based protection domain implementation does not explicitly reference + these symbols, so we list them here to prevent them from being garbage- + collected. +*/ +EXTERN(stacks_int) +EXTERN(stacks_exc) + +PHDRS { + boot_text PT_LOAD; + text PT_LOAD; + data PT_LOAD; +} + +SECTIONS { + /* + OS-Dev Wiki says it is common for kernels to start at 1M. Addresses before that + are used by BIOS/EFI, the bootloader and memory-mapped I/O. + + The UEFI GenFw program inserts a 0x220 byte offset between the image base and + the .text section. We add that same offset here to align the symbols in the + UEFI DLL with those in the final UEFI binary to make debugging easier. + */ + . = 1M + 0x220; + + /* + The GenFw program in the EDK2 UEFI toolchain outputs UEFI images with a + section alignment of at least 32 bytes. Thus, it is desirable to use at + least that alignment granularity to avoid symbols being shifted from the + intermediate DLL to the final UEFI image. Such shifting may make + debugging more difficult by preventing the DLL from being a useful + source of symbol information. The debugging symbols are not included in + the final UEFI image. + */ + .text.boot : ALIGN (32) + { + *(.multiboot) + /* + The initial bootstrap code expects to operate in a flat address + space with an identity mapping between linear and physical + addresses. + */ + *(.boot_text) + } :boot_text + + /* The post-boot code segments define tight bounds around the code + section, so this directive resets the virtual address to 0. */ + . = 0; + + /* The virtual address differs from the load address. */ + .text : AT(LOADADDR(.text.boot) + ALIGN(SIZEOF(.text.boot), 32)) ALIGN (32) + { + /* + These BYTE directives emit a UD2 instruction to cause execution to + halt if the control flow ever deviates to address 0. This also + prevents other code from being placed at address 0. Some code + considers a function pointer to address 0 to be a null function + pointer. + */ + BYTE(0x0F); + BYTE(0x0B); + *(.text*) + + /* + An alternative design to eliminate the need for ALIGN directives + within the AT directives in later sections could have padded + each section out to a 32-byte boundary. However, that would have + enabled unneeded software accesses to the padding past the end of actual + code/data in each section, since segments are also configured based on + the values of the SIZEOF expressions. As a general principle, accesses + should be as restricted as is feasible. + */ + } :text + + _stext_addr = LOADADDR(.text); + _etext_addr = LOADADDR(.text) + SIZEOF(.text); + + . = 0; + + .data : AT(ALIGN(_etext_addr, 32)) ALIGN (32) + { + *(.main_stack) + *(.int_stack) + *(.exc_stack) + *(.rodata*) + *(.data*) + + _sdata_kern_startup_func = .; + KEEP(*(.kern_startup_func)) + _edata_kern_startup_func = .; + + /* + These could alternatively be treated as read-only data to prevent tampering + from the user privilege level. + */ + _sdata_shared_isr = .; + KEEP(*(.shared_isr_data*)) + _edata_shared_isr = .; + } :data + + .bss : ALIGN (32) + { + *(COMMON) + *(.bss*) + } + + _sdata_addr = LOADADDR(.data); + _edata_addr = LOADADDR(.bss) + SIZEOF(.bss); + + . = 0; + + .bss.kern (NOLOAD) : AT(ALIGN(_edata_addr, 32)) ALIGN (32) + { + /* + This directive prevents any data from being allocated at address + zero, since the address 0 is commonly used to represent null + pointers. + */ + LONG(0); + *(.kern_bss) + + syscalls_entrypoints = .; + *(.syscall_bss) + syscalls_entrypoints_end = .; + } + + _ebss_syscall_addr = LOADADDR(.bss.kern) + SIZEOF(.bss.kern); + + .bss.kern_priv (NOLOAD) : ALIGN (32) + { + prot_domains_kern_data = .; + /* + The kernel and app protection domain control structures must always + be placed in the first two slots in this order, so that they have + well-known protection domain IDs: + */ + *(.kern_prot_dom_bss) + *(.app_prot_dom_bss) + *(.prot_dom_bss) + prot_domains_kern_data_end = .; + + *(.gdt_bss_start) + KEEP(*(.gdt_bss_mid)) + *(.gdt_bss) + _ebss_gdt_addr = .; + } + + _sbss_kern_addr = LOADADDR(.bss.kern); + _ebss_kern_addr = LOADADDR(.bss.kern_priv) + SIZEOF(.bss.kern_priv); + + . = _ebss_kern_addr; + + .bss.meta (NOLOAD) : AT(ALIGN(_ebss_kern_addr, 32)) ALIGN (32) + { + *(.meta_bss) + } + + /* .bss.meta may be empty, so this uses .bss.kern_priv as a base instead: */ + _ebss_pre_dma_addr = ALIGN(ALIGN(_ebss_kern_addr, 32) + SIZEOF(.bss.meta), 32); +} diff --git a/cpu/x86/quarkX1000_paging.ld b/cpu/x86/quarkX1000_paging.ld new file mode 100644 index 000000000..87c89ed8b --- /dev/null +++ b/cpu/x86/quarkX1000_paging.ld @@ -0,0 +1,210 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. 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. + */ + +OUTPUT_FORMAT("elf32-i386") + +ENTRY(start) + +SECTIONS { + /* + OS-Dev Wiki says it is common for kernels to start at 1M. Addresses before that + are used by BIOS/EFI, the bootloader and memory-mapped I/O. + + The UEFI GenFw program inserts a 0x220-byte offset between the image base and + the .text section. We add that same offset here to align the symbols in the + UEFI DLL with those in the final UEFI binary to make debugging easier. + */ + . = 1M + 0x220; + + .text.boot : ALIGN (32) + { + *(.multiboot) + *(.boot_text) + + /* + Fill out the section to the next 4K boundary so that the UEFI GenFw + program does not shift the following .text section forward into the + gap and perturb the symbols. This only works if the size of this + section is less than 4K - 0x220 bytes. + */ + . = 4K - 0x220; + } + + /* + It is actually desired that each of the following sections be page- + aligned. However, the UEFI GenFw program ratchets up its alignment + granularity to the maximum granularity discovered in its input file. + Using page-alignment perturbs the symbols, hindering debugging. Thus, + this file simply pads each section out to the desired page alignment and + declares a section alignment granularity of 32 bytes. + */ + + .text : ALIGN (32) + { + *(.text*) + + . = ALIGN(4K); + } + + _stext_addr = ADDR(.text); + _etext_addr = ADDR(.text) + SIZEOF(.text); + + .data.stack : ALIGN (32) + { + /* + Introduce a guard band page before the stacks to facilitate stack + overflow detection. This approach wastes a page of memory for each + guard band, but has the advantage of enabling an identity mapping + for all linear to physical addresses except those in the MMIO + regions. The guard bands are marked not-present in the page tables + to facilitate stack overflow detection. + + This padding must be placed inside of the section, or else it will + get dropped when the UEFI GenFw program generates the UEFI binary. + */ + . += 4K; + + /* + Place the main stack first so that an overflow is detected and does + not overwrite the interrupt or supervisor stacks. Usage of the + interrupt and stack is predictable, since it is only used by short + trampoline code sequences that quickly pivot to the main stack. + */ + *(.main_stack) + *(.int_stack) + *(.exc_stack) + + /* + The combined sizes of the stacks is an even multiple of 4K, so there + is no need to align the location counter here. + */ + + /* + Introduce a guard band page after the stacks to detect stack underflow. + Note that an underflow that only affects the interrupt and supervisor + stacks will not generate a page fault. Detecting such conditions by + placing the interrupt and supervisor stacks on separate pages would + substantially increase memory usage. + */ + . += 4K; + } + + .data : ALIGN (32) + { + /* + The UEFI GenFw program treats all sections that are alloc and read- + only as code sections. By that criteria, .rodata would be a code + section, but making such data executable is undesirable. Thus, this + script lumps in .rodata with other data. It may be desirable in the + future to actually write-protect this data. + */ + *(.rodata*) + *(.data*) + + _sdata_kern_startup_func = .; + KEEP(*(.kern_startup_func)) + _edata_kern_startup_func = .; + + /* + These could alternatively be treated as read-only data to prevent tampering + from the user privilege level. + */ + _sdata_shared_isr = .; + KEEP(*(.shared_isr_data*)) + _edata_shared_isr = .; + + . = ALIGN(4K); + } + + .bss : ALIGN (32) + { + *(COMMON) + *(.bss*) + + . = ALIGN(4K); + } + + _sdata_addr = ADDR(.data); + _edata_addr = ADDR(.bss) + SIZEOF(.bss); + + .bss.kern (NOLOAD) : ALIGN (32) + { + /* + Page-aligned data is output first. + It is infeasible to apply a page-alignment attribute to them in the + source code, because that increases the alignment of this section to + be page-aligned, which causes problems when generating a UEFI binary + as described above. + */ + *(.page_aligned_kern_bss) + *(.kern_bss) + + syscalls_entrypoints = .; + *(.syscall_bss) + syscalls_entrypoints_end = .; + + . = ALIGN(4K); + } + + _ebss_syscall_addr = ADDR(.bss.kern) + SIZEOF(.bss.kern); + + .bss.kern_priv (NOLOAD) : ALIGN (32) + { + prot_domains_kern_data = .; + /* + The kernel and app protection domain control structures must always + be placed in the first two slots in this order, so that they have + well-known protection domain IDs: + */ + *(.kern_prot_dom_bss) + *(.app_prot_dom_bss) + *(.prot_dom_bss) + prot_domains_kern_data_end = .; + + *(.gdt_bss_start) + *(.gdt_bss_mid) + *(.gdt_bss) + _ebss_gdt_addr = .; + + . = ALIGN(4K); + } + + _sbss_kern_addr = ADDR(.bss.kern); + _ebss_kern_addr = ADDR(.bss.kern_priv) + SIZEOF(.bss.kern_priv); + + .bss.meta (NOLOAD) : ALIGN (32) + { + *(.meta_bss) + + . = ALIGN(4K); + } + + _ebss_pre_dma_addr = ALIGN(32); +} diff --git a/cpu/x86/startup.h b/cpu/x86/startup.h new file mode 100644 index 000000000..56ad3b482 --- /dev/null +++ b/cpu/x86/startup.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CPU_X86_STARTUP_H_ +#define CPU_X86_STARTUP_H_ + +/** + * \brief Declare a function that will be automatically invoked from the kernel + * protection domain during boot, after all of the default device + * initialization has been completed. + */ +#define KERN_STARTUP_FUNC(f) \ +static void f(void); \ +static uintptr_t \ + __attribute__((used, section(".kern_startup_func"))) \ + __kern_startup_f = (uintptr_t)f; \ +static void f(void) + +#endif /* CPU_X86_STARTUP_H_ */ diff --git a/cpu/x86/uefi/bootstrap_uefi.c b/cpu/x86/uefi/bootstrap_uefi.c index f6981eb96..5ef778cca 100644 --- a/cpu/x86/uefi/bootstrap_uefi.c +++ b/cpu/x86/uefi/bootstrap_uefi.c @@ -35,7 +35,12 @@ void start(void); -EFI_STATUS EFIAPI +/* The section attribute below is copied from ATTR_BOOT_CODE in prot-domains.h. + * prot-domains.h includes stdlib.h which defines NULL. The UEFI headers also + * define NULL, which induces a warning when the compiler detects the conflict. + * To avoid that, we avoid including prot-domains.h from this file. + */ +EFI_STATUS EFIAPI __attribute__((section(".boot_text"))) uefi_start(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable) { EFI_MEMORY_DESCRIPTOR mem_map[MAX_MEM_DESC]; diff --git a/dev/cc1200/cc1200.c b/dev/cc1200/cc1200.c index 1f3bfd499..bed33c5b6 100644 --- a/dev/cc1200/cc1200.c +++ b/dev/cc1200/cc1200.c @@ -374,6 +374,17 @@ extern const cc1200_rf_cfg_t CC1200_RF_CFG; } while(0) #endif /*---------------------------------------------------------------------------*/ +/* Sniffer configuration */ +#if CC1200_SNIFFER +static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; +#include "dev/uart.h" +#define write_byte(b) uart_write_byte(CC1200_RF_CONF_SNIFFER_UART, b) +#define flush() +#else /* CC1200_SNIFFER */ +#define write_byte(b) +#define flush() +#endif /* CC1200_SNIFFER */ +/*---------------------------------------------------------------------------*/ /* Variables */ /*---------------------------------------------------------------------------*/ /* Flag indicating whether non-interrupt routines are using SPI */ @@ -870,6 +881,10 @@ read(void *buf, unsigned short buf_len) int len = 0; + #if CC1200_SNIFFER + uint8_t i; + #endif + if(rx_pkt_len > 0) { int8_t rssi = rx_pkt[rx_pkt_len - 2]; @@ -896,8 +911,22 @@ read(void *buf, unsigned short buf_len) packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, crc_lqi & ~(1 << 7)); - RIMESTATS_ADD(llrx); + #if CC1200_SNIFFER + write_byte(magic[0]); + write_byte(magic[1]); + write_byte(magic[2]); + write_byte(magic[3]); + write_byte(len + 2); + for(i = 0; i < len; ++i) { + write_byte(((unsigned char *)(buf))[i]); + } + write_byte(rssi); + write_byte(crc_lqi); + flush(); + #endif + + RIMESTATS_ADD(llrx); } } diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c index 60dded31a..6d7704e7f 100644 --- a/dev/enc28j60/enc28j60.c +++ b/dev/enc28j60/enc28j60.c @@ -207,7 +207,7 @@ setregbank(uint8_t new_bank) } /*---------------------------------------------------------------------------*/ static void -writedata(uint8_t *data, int datalen) +writedata(const uint8_t *data, int datalen) { int i; enc28j60_arch_spi_select(); @@ -477,7 +477,7 @@ reset(void) } /*---------------------------------------------------------------------------*/ void -enc28j60_init(uint8_t *mac_addr) +enc28j60_init(const uint8_t *mac_addr) { if(initialized) { return; @@ -496,7 +496,7 @@ enc28j60_init(uint8_t *mac_addr) } /*---------------------------------------------------------------------------*/ int -enc28j60_send(uint8_t *data, uint16_t datalen) +enc28j60_send(const uint8_t *data, uint16_t datalen) { uint16_t dataend; diff --git a/dev/enc28j60/enc28j60.h b/dev/enc28j60/enc28j60.h index 059528816..473cceca4 100644 --- a/dev/enc28j60/enc28j60.h +++ b/dev/enc28j60/enc28j60.h @@ -32,9 +32,9 @@ #ifndef ENC28J60_H #define ENC28J60_H -void enc28j60_init(uint8_t *mac_addr); +void enc28j60_init(const uint8_t *mac_addr); -int enc28j60_send(uint8_t *data, uint16_t datalen); +int enc28j60_send(const uint8_t *data, uint16_t datalen); int enc28j60_read(uint8_t *buffer, uint16_t bufsize); diff --git a/doc/uip6-doc.txt b/doc/uip6-doc.txt index b120bccef..492337f25 100644 --- a/doc/uip6-doc.txt +++ b/doc/uip6-doc.txt @@ -161,7 +161,7 @@ Determine the link-layer address of a %neighbor given its IPv6 address.\n \li Neighbor unreachability detection\n Verify that a neighbor is still reachable via a cached link-layer address.\n --> send a NS (done in #uip_ds6_neighbor_periodic). +-> send a NS (done in uip_ds6_neighbor_periodic). \li Next-hop determination\n Map an IPv6 destination address into the IPv6 address of the %neighbor to which traffic for the destination should be sent.\n diff --git a/examples/avr-rss2/avr_radio_power/AtMega256RFR2-summary-power.dat b/examples/avr-rss2/avr_radio_power/AtMega256RFR2-summary-power.dat new file mode 100644 index 000000000..bc4e1f0cc --- /dev/null +++ b/examples/avr-rss2/avr_radio_power/AtMega256RFR2-summary-power.dat @@ -0,0 +1,25 @@ + +# Atmega256RFR2 @ 20C, UNT-61E, RSS2 Mote 2015-12-30 +# TX-PWR RPC=0x0 vs RPC=0xFF. Current mA +# +15 14.6 11.8 +14 15.0 12.1 +13 15.3 12.5 +12 15.6 12.8 +11 15.9 13.1 +10 16.1 13.4 + 9 16.3 13.7 + 8 16.5 13.8 + 7 16.7 13.9 + 6 16.9 14.0 + 5 17.0 14.2 + 4 17.2 14.3 + 3 17.2 14.5 + 2 17.2 14.6 + 1 17.3 14.6 + 0 17.4 14.5 +RX 13.7 7.3 +IDLE 0 0 + + + diff --git a/examples/avr-rss2/avr_radio_power/Makefile b/examples/avr-rss2/avr_radio_power/Makefile new file mode 100644 index 000000000..abaab89f1 --- /dev/null +++ b/examples/avr-rss2/avr_radio_power/Makefile @@ -0,0 +1,9 @@ +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" + +CONTIKI_PROJECT = avr_radio_power +APPS+=powertrace +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. +CONTIKI_WITH_RIME = 1 +include $(CONTIKI)/Makefile.include diff --git a/examples/avr-rss2/avr_radio_power/README.md b/examples/avr-rss2/avr_radio_power/README.md new file mode 100644 index 000000000..745a31790 --- /dev/null +++ b/examples/avr-rss2/avr_radio_power/README.md @@ -0,0 +1,79 @@ +avr_radio_power +=============== + +Motivation +----------- +Spins over different radio seting for the Atmel radio. The motivation is to +get understanding and also to get correct data for avrora and Contiki + simulations. Program loops over different TX-power setting and measures +RX consumption also radio off and idle power use in SLEEP_MODE_PWR_SAVE is +measured. Program disables radio duty cycling (RDC) and sets MCU in deep +sleep mode to only get radio consumption. + +Usage +----- +The different setting is printed on the terminal. You need a way to measure +the current consumption and relate to the tests. + +Example +------- +Program printout with added measurements. The used board was RSS2 mote +with a AtMega256RFR2 CPU. Max is when 0xFF is written to the RPC register. + + +Run/setup Current use +------------------------------------------------ +TX with PWR=0 RPC=0x00 17.80 mA (MAX TX-pwr) +TX with PWR=1 RPC=0x00 17.74 +TX with PWR=2 RPC=0x00 +TX with PWR=3 RPC=0x00 +TX with PWR=4 RPC=0x00 +TX with PWR=5 RPC=0x00 17.43 +TX with PWR=6 RPC=0x00 +TX with PWR=7 RPC=0x00 +TX with PWR=8 RPC=0x00 +TX with PWR=9 RPC=0x00 17.68 +TX with PWR=10 RPC=0x00 +TX with PWR=11 RPC=0x00 +TX with PWR=12 RPC=0x00 +TX with PWR=13 RPC=0x00 +TX with PWR=14 RPC=0x00 +TX with PWR=15 RPC=0x00 +RX with RPC=0x00 -------------------- 13.43 (RX) + +------------------------------------------------- +TX with PWR=0 RPC=0xff 14.63 mA (MAX TX-pwr) +TX with PWR=1 RPC=0xff +TX with PWR=2 RPC=0xff +TX with PWR=3 RPC=0xff +TX with PWR=4 RPC=0xff +TX with PWR=5 RPC=0xff +TX with PWR=6 RPC=0xff 14.45 +TX with PWR=7 RPC=0xff +TX with PWR=8 RPC=0xff +TX with PWR=9 RPC=0xff +TX with PWR=10 RPC=0xff +TX with PWR=11 RPC=0xff +TX with PWR=12 RPC=0xff +TX with PWR=13 RPC=0xff +TX with PWR=14 RPC=0xff +TX with PWR=15 RPC=0xff +RX with RPC=0xFF -------------------- 7.11 (RX) + +RX radio off 0.001 mA + + +Comments +-------- +We see TX consumption decreases from 17.80 to 14.63 mA using Max RPC (0xFF). +NOTE! For RX 13.43 to 7.11 mA. Nice. This actual measurements. +The avr-rss2 port adds support for the AtMegaXXXRFR2 including the new RPC +function. + + +References +---------- +Atmel application note. AT02594: Smart Reduced Power Consumption Techniques +[Here] (http://www.atmel.com/images/atmel-42356-smart-reduced-power-consumption-techniques_applicationnote_at02594.pdf) + +Multimeter UNI-T UT61E with USB-logging. \ No newline at end of file diff --git a/examples/avr-rss2/avr_radio_power/avr_radio_power.c b/examples/avr-rss2/avr_radio_power/avr_radio_power.c new file mode 100644 index 000000000..5be61d8bd --- /dev/null +++ b/examples/avr-rss2/avr_radio_power/avr_radio_power.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2015, Copyright Robert Olsson / Radio Sensors AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the 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. + * + * + * Author : Robert Olsson robert@radio-sensors.com + * Created : 2015-12-30 + */ + +/** + * \file + * An application for monitoring current use on Atmel + * radios also supporting the RPC function on RFR2 chips. + * Current needs to be measured with amp-meter. + */ + +#include "contiki.h" +#include "net/rime/rime.h" +#include "powertrace.h" +#include +#include "dev/leds.h" +#include "rf230bb.h" +#include "net/packetbuf.h" +#include "net/rime/rimestats.h" +#include "net/netstack.h" +#include +#include + +#define TEST_PERIOD 6 + +static int ps = 0; /* Power-save false */ +static char buf[110]; +static struct etimer et; + +PROCESS(power_use_process, "Power use test"); +PROCESS(sleep_process, "Sleep process"); +AUTOSTART_PROCESSES(&power_use_process, &sleep_process); + +static void +broadcast_recv(struct broadcast_conn *c, const linkaddr_t *from) +{ + printf("broadcast message received from %d.%d: '%s'\n", + from->u8[0], from->u8[1], (char *)packetbuf_dataptr()); +} + +static const struct broadcast_callbacks broadcast_call = {broadcast_recv}; +static struct broadcast_conn broadcast; + + +PROCESS_THREAD(power_use_process, ev, data) +{ + static int i, j; + PROCESS_EXITHANDLER(broadcast_close(&broadcast);) + PROCESS_BEGIN(); + + /* powertrace_start(CLOCK_SECOND * 2); */ + broadcast_open(&broadcast, 129, &broadcast_call); + leds_init(); + rf230_set_channel(25); + + for(i=0; i < 2; i++) { /* Loop over min and max rpc settings */ + + NETSTACK_RADIO.off(); /* Radio off for rpc change */ + NETSTACK_RADIO.off(); + etimer_set(&et, CLOCK_SECOND * 8); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + if(i == 0) + rf230_set_rpc(0x0); /* Disbable all RPC features */ + else + rf230_set_rpc(0xFF); /* Enable all RPC features. Only XRFR2 radios */ + NETSTACK_RADIO.on(); + + /* Loop over the different TX power settings 0-15 */ + + for(j=15; j >= 0; j--) { + NETSTACK_RADIO.on(); + rf230_set_txpower(j); + ps = 0; + printf("TX with PWR=%d RPC=0x%02x\n", rf230_get_txpower(), rf230_get_rpc()); + ps = 1; + + etimer_set(&et, CLOCK_SECOND * TEST_PERIOD); + + while(1) { + if(etimer_expired(&et)) + break; + packetbuf_copyfrom(buf, sizeof(buf)); /* Dummy data */ + broadcast_send(&broadcast); + PROCESS_PAUSE(); + //leds_on(LEDS_RED); + } + /* Barrier so we can see next run */ + NETSTACK_RADIO.off(); + etimer_set(&et, CLOCK_SECOND * TEST_PERIOD); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + } + + /* RX */ + NETSTACK_RADIO.on(); + ps = 0; + printf("RX radio on RPC=0x%02x\n", rf230_get_rpc()); + ps = 1; + etimer_set(&et, CLOCK_SECOND * TEST_PERIOD); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + NETSTACK_RADIO.off(); + } + + /* Last just RX OFF*/ + ps = 0; + printf("RX radio off\n"); + ps = 1; + etimer_set(&et, CLOCK_SECOND * TEST_PERIOD); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + PROCESS_END(); +} + +/* Sleep process is just put MCU in sleep so we minimiza MCU impact */ +PROCESS_THREAD(sleep_process, ev, data) +{ + PROCESS_BEGIN(); + while(1) { + watchdog_periodic(); + if(ps) + set_sleep_mode(SLEEP_MODE_PWR_SAVE); + else + set_sleep_mode(SLEEP_MODE_IDLE); + cli(); + sleep_enable(); + sei(); + sleep_cpu(); + sleep_disable(); + sei(); + PROCESS_PAUSE(); + } + PROCESS_END(); +} + diff --git a/examples/avr-rss2/avr_radio_power/project-conf.h b/examples/avr-rss2/avr_radio_power/project-conf.h new file mode 100644 index 000000000..8d1bc434f --- /dev/null +++ b/examples/avr-rss2/avr_radio_power/project-conf.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015, Copyright Robert Olsson / Radio Sensors AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the 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. + * + * + * Author : Robert Olsson robert@radio-sensors.com + * Created : 2015-11-22 + */ + +/** + * \file + * Project specific configuration defines for example + * + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define NETSTACK_CONF_RDC nullrdc_driver +#define NETSTACK_CONF_MAC nullmac_driver + +//#define NETSTACK_CONF_MAC csma_driver +//#define NETSTACK_CONF_RDC contikimac_driver + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/avr-rss2/hello-sensors/Makefile b/examples/avr-rss2/hello-sensors/Makefile new file mode 100644 index 000000000..0d1d41b9f --- /dev/null +++ b/examples/avr-rss2/hello-sensors/Makefile @@ -0,0 +1,19 @@ +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" +CONTIKI_PROJECT = hello-sensors +all: $(CONTIKI_PROJECT) + +# We use floating vars. Add library. +PRINTF_LIB_FLT = -Wl,-u,vfprintf -lprintf_flt -lm +PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min +PRINTF_LIB = $(PRINTF_LIB_FLT) +CLIBS = $(PRINTF_LIB) + + +CUSTOM_RULE_LINK = 1 +%.$(TARGET): %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a + $(LD) $(LDFLAGS) $(TARGET_STARTFILES) ${filter-out %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -o $@ $(CLIBS) + + + +CONTIKI = ../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/avr-rss2/hello-sensors/README.md b/examples/avr-rss2/hello-sensors/README.md new file mode 100644 index 000000000..9b204a2a6 --- /dev/null +++ b/examples/avr-rss2/hello-sensors/README.md @@ -0,0 +1,11 @@ +Hello-sensors +============= + +Simple demo to read out sensors from the RSS2 mote. + +Demo uses double which has the same size as float on Atmel. We sacrifice +some bytes for this. + +Build +----- +make TARGET=avr-rss2 diff --git a/examples/avr-rss2/hello-sensors/hello-sensors.c b/examples/avr-rss2/hello-sensors/hello-sensors.c new file mode 100644 index 000000000..42be6109e --- /dev/null +++ b/examples/avr-rss2/hello-sensors/hello-sensors.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2015, Copyright Robert Olsson / Radio Sensors AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the 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. + * + * + * Author : Robert Olsson robert@radio-sensors.com + * Created : 2015-11-22 + */ + +/** + * \file + * A simple application showing sensor reading on RSS2 mote + */ + +#include "contiki.h" +#include "sys/etimer.h" +#include +#include "adc.h" +#include "i2c.h" +#include "dev/leds.h" +#include "dev/battery-sensor.h" +#include "dev/temp-sensor.h" +#include "dev/temp_mcu-sensor.h" +#include "dev/light-sensor.h" +#include "dev/pulse-sensor.h" +#ifdef CO2 +#include "dev/co2_sa_kxx-sensor.h" +#endif +/*---------------------------------------------------------------------------*/ +PROCESS(hello_sensors_process, "Hello sensor process"); +AUTOSTART_PROCESSES(&hello_sensors_process); + +static struct etimer et; + +static void +read_values(void) +{ + char serial[16]; + + int i; + + /* Read out mote unique 128 bit ID */ + i2c_at24mac_read((char *) &serial, 0); + printf("128_bit_ID="); + for(i=0; i < 15; i++) + printf("%02x", serial[i]); + printf("%02x\n", serial[15]); + printf("T=%-5.2f", ((double) temp_sensor.value(0)/100.)); + printf(" V_MCU=%-3.1f", ((double) battery_sensor.value(0))/1000.); + printf(" V_IN=%-4.2f", adc_read_v_in()); + printf(" V_AD1=%-4.2f", adc_read_a1()); + printf(" V_AD2=%-4.2f", adc_read_a2()); + printf(" T_MCU=%-4.1f", ((double) temp_mcu_sensor.value(0)/10.)); + printf(" LIGHT=%-d", light_sensor.value(0)); + printf(" PULSE_0=%-d", pulse_sensor.value(0)); + printf(" PULSE_1=%-d", pulse_sensor.value(1)); +#ifdef CO2 + printf(" CO2=%-d", co2_sa_kxx_sensor.value( CO2_SA_KXX_CO2)); +#endif + printf("\n"); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(hello_sensors_process, ev, data) +{ + PROCESS_BEGIN(); + + SENSORS_ACTIVATE(temp_sensor); + SENSORS_ACTIVATE(battery_sensor); + SENSORS_ACTIVATE(temp_mcu_sensor); + SENSORS_ACTIVATE(light_sensor); + SENSORS_ACTIVATE(pulse_sensor); +#ifdef CO2 + SENSORS_ACTIVATE(co2_sa_kxx_sensor); +#endif + leds_init(); + leds_on(LEDS_RED); + leds_on(LEDS_YELLOW); + + /* + * Delay 5 sec + * Gives a chance to trigger some pulses + */ + + etimer_set(&et, CLOCK_SECOND * 5); + while(1) { + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + read_values(); + etimer_reset(&et); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/avr-rss2/hello-sensors/project-conf.h b/examples/avr-rss2/hello-sensors/project-conf.h new file mode 100644 index 000000000..8d1bc434f --- /dev/null +++ b/examples/avr-rss2/hello-sensors/project-conf.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015, Copyright Robert Olsson / Radio Sensors AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the 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. + * + * + * Author : Robert Olsson robert@radio-sensors.com + * Created : 2015-11-22 + */ + +/** + * \file + * Project specific configuration defines for example + * + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define NETSTACK_CONF_RDC nullrdc_driver +#define NETSTACK_CONF_MAC nullmac_driver + +//#define NETSTACK_CONF_MAC csma_driver +//#define NETSTACK_CONF_RDC contikimac_driver + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/Makefile b/examples/avr-rss2/ipv6/dc-rpl-coap/Makefile new file mode 100644 index 000000000..46a7e9c3f --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/Makefile @@ -0,0 +1,49 @@ +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" + +all: coap-client coap-server +APPS=servreg-hack +CONTIKI=../../../.. + +ifdef WITH_COMPOWER +APPS+=powertrace +CFLAGS+= -DCONTIKIMAC_CONF_COMPOWER=1 -DWITH_COMPOWER=1 -DQUEUEBUF_CONF_NUM=4 +endif + +ifdef SERVER_REPLY +CFLAGS+=-DSERVER_REPLY=$(SERVER_REPLY) +endif +ifdef PERIOD +CFLAGS+=-DPERIOD=$(PERIOD) +endif + +### -------------------------------------------------------- ### + +#CONTIKI_TARGET_SOURCEFILES += control.c vdc.c + +# automatically build RESTful resources +REST_RESOURCES_DIR = ./resources +REST_RESOURCES_FILES = $(notdir $(shell find $(REST_RESOURCES_DIR) -name '*.c')) + +DC_SENSOR_DIR = ./dev +DC_SENSOR_FILES = $(notdir $(shell find $(DC_SENSOR_DIR) -name '*.c')) + +PROJECTDIRS += $(REST_RESOURCES_DIR) $(DC_SENSOR_DIR) +PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) $(DC_SENSOR_FILES) + +# linker optimizations +SMALL=1 + +# REST Engine shall use Erbium CoAP implementation +APPS += er-coap +APPS += rest-engine + +#CFLAGS += -DUIP_CONF_BUFFER_SIZE=384 +CFLAGS += -DREST_MAX_CHUNK_SIZE=128 +CFLAGS += -DCOAP_MAX_HEADER_SIZE=64 + +CFLAGS += -DUIP_CONF_TCP=0 + +### -------------------------------------------------------- ### + +CONTIKI_WITH_IPV6 = 1 +include $(CONTIKI)/Makefile.include diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/README.md b/examples/avr-rss2/ipv6/dc-rpl-coap/README.md new file mode 100644 index 000000000..ba14cb756 --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/README.md @@ -0,0 +1,67 @@ +Example: mockup of DC converter functionality for IoT-grid. +=========================================== +This example imitates DC converter functionality for IoT-grid. +We use standard IoT protocol stack with CoAP application-level protocol. +The settings are as follows. + +* APPLICATION: CoAP +* TRANSPORT: UDP +* NETWORK: IPv6/RPL +* ADAPTATION: 6LoWPAN +* MAC: nullmac_driver +* RADIO DUTY CYCLE: nullrdc_driver +* PHYSICAL: IEEE 802.15.4 + +CoAP resources +---------------- +We define a CoAP resource for each functionality of DC converter. +Since each functionality may have several parameters, we define each resource +as a vector of parameters as follows. + +* /dcdc/status read-only parameters for power monitoring. +It also support periodic monitoring through CoAP observe option. + ** 0 VOUT Output voltage + ** 1 VIN Input voltage + ** 2 IOUT Output current + ** 3 IIN Input current + +* /dcdc/vdc configurable parameters for voltage droop control function. + ** 0 VGRID Desired grid output voltage + ** 1 SLOPE Slope of voltage droop control function + ** 2 PMAX Maximum output power allowed + +* /dcdc/hwcfg configurable parameters for DC converter hardware. + ** 0 VMAX Maximum output voltage allowed + ** 1 IMAX Maximum output current allowed + +Each functionality is implemented as a sensor type device. +They are located in "dev" folder. +* dc-status-sensor for /dcdc/status +* dc-vdc-sensor for /dcdc/vdc +* dc-hw-sensor for /dcdc/hwcfg + +The corresponding CoAP handler for each resource is defined in "resources" folder. +* res-dc-status-obs for /dcdc/status +* res-dc-vdc for /dcdc/vdc +* res-dc-hwcfg for /dcdc/hwcfg + +coap-server.c +---------------- +The server acts as the RPL root node. +It has 3 CoAP resources as described above. + +coap-client.c +---------------- +The client periodically send a CoAP command (either GET or PUT) to monitor/update +values of parameters of a resource. + +project-conf.h +---------------- +This file contains definitions needed for this IoT-grid example as follows. +* Enable IPv6 network stack +* Set nullrdc_driver +* Set nullmac_driver +* Activate CoAP observe client library (COAP_OBSERVE_CLIENT = 1) +* Increase the maximum number of observee and maximum number of open transaction to 10 +(COAP_MAX_OPEN_TRANSACTIONS and COAP_MAX_OBSERVEES = 10) + diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/coap-client.c b/examples/avr-rss2/ipv6/dc-rpl-coap/coap-client.c new file mode 100644 index 000000000..691b48e40 --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/coap-client.c @@ -0,0 +1,413 @@ +/* + * 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" +#include "contiki-net.h" +#include "lib/random.h" +#include "sys/ctimer.h" +#include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" +#include "net/ip/uip-udp-packet.h" +#ifdef WITH_COMPOWER +#include "powertrace.h" +#endif +#include +#include + +/**************************************************************************/ +/* from er-rest-example/er-rexample-client.c */ +#include +#include "er-coap-engine.h" +#include "er-coap.h" +#include "er-coap-observe-client.h" +/* #include "dev/button-sensor.h" */ + +#if PLATFORM_HAS_LEDS +#include "dev/leds.h" +#endif + +#define DEBUG 1 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) +#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) +#else +#define PRINTF(...) +#define PRINT6ADDR(addr) +#define PRINTLLADDR(addr) +#endif + +/* FIXME: This server address is hard-coded for Cooja and link-local for unconnected border router. */ +/* #define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7402, 0x0002, 0x0202) / * cooja2 * / */ +/* #define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xbbbb, 0, 0, 0, 0, 0, 0, 0x1) */ + +/* #define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0x2000, 0, 0, 0, 0, 0, 0, 0x0001) */ +#define LOCAL_PORT UIP_HTONS(COAP_DEFAULT_PORT + 1) +#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) + +#define GET_INTERVAL 10 +/* #define OBSERVE_INTERVAL 10 */ + +/**************************************************************************/ + +#define UDP_CLIENT_PORT 8765 +#define UDP_SERVER_PORT 5678 + +#define UDP_EXAMPLE_ID 190 + +/* #define DEBUG DEBUG_PRINT */ +/* #include "net/ip/uip-debug.h" */ + +#ifndef PERIOD +/* #define PERIOD 60 */ +#define PERIOD 10 +#endif + +#define START_INTERVAL (15 * CLOCK_SECOND) +#define SEND_INTERVAL (PERIOD * CLOCK_SECOND) +#define SEND_TIME (random_rand() % (SEND_INTERVAL)) + +/* static struct uip_udp_conn *client_conn; */ +static uip_ipaddr_t server_ipaddr; +static coap_observee_t *obs; +static int count_notify = 0; + +/**************************************************************************/ +static struct etimer et; + +/* Example URIs that can be queried. */ +#define NUMBER_OF_URLS 4 +/* leading and ending slashes only for demo purposes, get cropped automatically when setting the Uri-Path */ +char *service_urls[NUMBER_OF_URLS] = +{ ".well-known/core", "/dcdc/status", "/dcdc/vdc", "/dcdc/hwcfg" }; +/* + #if PLATFORM_HAS_BUTTON + static int uri_switch = 0; + #endif + */ +/* This function is will be passed to COAP_BLOCKING_REQUEST() to handle responses. */ +void +client_chunk_handler(void *response) +{ + const uint8_t *chunk; + + int len = coap_get_payload(response, &chunk); + +#if PLATFORM_HAS_LEDS + /* set red led when receiving a packet */ + leds_on(LEDS_RED); +#endif + +/* printf("|%.*s", len, (char *)chunk); */ + printf("RX: %d\n%s\n", len, (char *)chunk); +} +/**************************************************************************/ + +/*---------------------------------------------------------------------------*/ +PROCESS(coap_client_process, "CoAP client process"); +AUTOSTART_PROCESSES(&coap_client_process); +/*---------------------------------------------------------------------------*/ +static void +tcpip_handler(void) +{ + char *str; + + if(uip_newdata()) { + str = uip_appdata; + str[uip_datalen()] = '\0'; + printf("DATA recv '%s'\n", str); + } +} +/*---------------------------------------------------------------------------*/ +static void +print_local_addresses(void) +{ + int i; + uint8_t state; + + PRINTF("Client IPv6 addresses: "); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && + (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n"); + /* hack to make address "final" */ + if(state == ADDR_TENTATIVE) { + uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; + } + } + } +} +/*---------------------------------------------------------------------------*/ +static void +set_global_address(void) +{ + uip_ipaddr_t ipaddr; + + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + +/* The choice of server address determines its 6LoPAN header compression. + * (Our address will be compressed Mode 3 since it is derived from our link-local address) + * Obviously the choice made here must also be selected in udp-server.c. + * + * For correct Wireshark decoding using a sniffer, add the /64 prefix to the 6LowPAN protocol preferences, + * e.g. set Context 0 to aaaa::. At present Wireshark copies Context/128 and then overwrites it. + * (Setting Context 0 to aaaa::1111:2222:3333:4444 will report a 16 bit compressed address of aaaa::1111:22ff:fe33:xxxx) + * + * Note the IPCMV6 checksum verification depends on the correct uncompressed addresses. + */ + +#if 0 +/* Mode 1 - 64 bits inline */ + uip_ip6addr(&server_ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 1); +#elif 1 +/* Mode 2 - 16 bits inline */ + uip_ip6addr(&server_ipaddr, 0xaaaa, 0, 0, 0, 0, 0x00ff, 0xfe00, 1); +#else +/* Mode 3 - derived from server link-local (MAC) address */ + uip_ip6addr(&server_ipaddr, 0xaaaa, 0, 0, 0, 0x0250, 0xc2ff, 0xfea8, 0xcd1a); /* redbee-econotag */ +#endif +/* Voravit Added */ +/* PRINTF("VORAVIT CLIENT: SERVER IPv6 addresses: \n"); */ +/* PRINT6ADDR(&server_ipaddr); */ +} +/*---------------------------------------------------------------------------*/ + +static void +generate_random_payload(int type, char *msg) +{ + if(type == 2) { /* /dcdc/vdc */ + snprintf((char *)msg, 64, "&VG=%d&SL=%d&PMX=%d", (random_rand() % 25) + 1, (random_rand() % 10) + 1, (random_rand() % 100) + 1); + } else if(type == 3) { /* /dcdc/hwcfg */ + snprintf((char *)msg, 64, "&VMX=%d&IMX=%d", (random_rand() % 25) + 1, (random_rand() % 6) + 1); + } +} +/*----------------------------------------------------------------------------*/ +/* + * Handle the response to the observe request and the following notifications + */ +static void +notification_callback(coap_observee_t *obs, void *notification, coap_notification_flag_t flag) +{ + int len = 0; + const uint8_t *payload = NULL; + +/* printf("Notification handler\n"); */ +/* printf("Observee URI: %s\n", obs->url); */ + if(notification) { + len = coap_get_payload(notification, &payload); + } + switch(flag) { + case NOTIFICATION_OK: + count_notify++; + printf("NOTIFICATION OK: %d\n%*s\n", count_notify, len, (char *)payload); + break; + case OBSERVE_OK: /* server accepeted observation request */ + printf("OBSERVE_OK: \n%*s\n", len, (char *)payload); + break; + case OBSERVE_NOT_SUPPORTED: + printf("OBSERVE_NOT_SUPPORTED: \n%*s\n", len, (char *)payload); + obs = NULL; + break; + case ERROR_RESPONSE_CODE: + printf("ERROR_RESPONSE_CODE: \n%*s\n", len, (char *)payload); + obs = NULL; + break; + case NO_REPLY_FROM_SERVER: + printf("NO_REPLY_FROM_SERVER: " + "removing observe registration with token %x%x\n", + obs->token[0], obs->token[1]); + obs = NULL; + break; + } +} +/*---------------------------------------------------------------------------*/ +/* + * Toggle the observation of the remote resource + */ +void +toggle_observation(void) +{ + if(obs) { + printf("Stopping observation\n"); + coap_obs_remove_observee(obs); + obs = NULL; + } else { + printf("Starting observation\n"); + obs = coap_obs_request_registration(&server_ipaddr, REMOTE_PORT, service_urls[1], notification_callback, NULL); + } +} +/*---------------------------------------------------------------------------*/ +static int count_get = 0; +static int count_put = 0; +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(coap_client_process, ev, data) +{ +/* + #if WITH_COMPOWER + static int print = 0; + #endif + */ + PROCESS_BEGIN(); + + PROCESS_PAUSE(); + + set_global_address(); + + PRINTF("CoAP client process started\n"); + + print_local_addresses(); + +/**************************************************************************/ + static coap_packet_t request[1]; /* This way the packet can be treated as pointer as usual. */ + + /* receives all CoAP messages */ + coap_init_engine(); + + etimer_set(&et, GET_INTERVAL * CLOCK_SECOND); + + while(1) { + PROCESS_YIELD(); + + if(ev == tcpip_event) { + printf("TCPIP_HANDLER\n"); + tcpip_handler(); + } + + if(etimer_expired(&et)) { + count_get++; + +/*---------------------------------------------------------------------------*/ + if(count_get < 10) { /* we do normal GET 3 times for each resource */ + /* TEST GET: looping through the 3 resources: status, vdc, hwcfg */ + /* Also CoAP GET doesn't need to have a payload */ + coap_init_message(request, COAP_TYPE_CON, COAP_GET, 0); + if(count_get % 3 == 1) { + coap_set_header_uri_path(request, service_urls[1]); + PRINTF("GET %d: %s\n", count_get, service_urls[1]); + } else if(count_get % 3 == 2) { + coap_set_header_uri_path(request, service_urls[2]); + PRINTF("GET %d: %s\n", count_get, service_urls[2]); + } else { + coap_set_header_uri_path(request, service_urls[3]); + PRINTF("GET %d: %s\n", count_get, service_urls[3]); + } + +#if PLATFORM_HAS_LEDS + /* set yellow led when sending packet */ + leds_on(LEDS_YELLOW); +#endif + COAP_BLOCKING_REQUEST(&server_ipaddr, REMOTE_PORT, request, + client_chunk_handler); + } /* if (count_get < 10) */ +/*---------------------------------------------------------------------------*/ + /* test PUT: vdc and hwcfg on odd and even packet */ + /* every 10th timer we PUT a resource: vdc and hwcfg alternately */ + if(count_get % 10 == 0) { + /* static char msg[64] = ""; */ + char msg[64] = ""; + + /*---------------------------------------------------------------------------*/ + /* We read CO2 sensor if it is enable */ + #ifdef CO2 + coap_init_message(request, COAP_TYPE_CON, COAP_GET, 0); + coap_set_header_uri_path(request, "/dcdc/co2"); + PRINTF("GET %d: %s\n", count_get, "/dcdc/co2"); + #if PLATFORM_HAS_LEDS + leds_on(LEDS_YELLOW); + #endif + COAP_BLOCKING_REQUEST(&server_ipaddr, REMOTE_PORT, request, + client_chunk_handler); + #endif + /*---------------------------------------------------------------------------*/ + + count_put++; + coap_init_message(request, COAP_TYPE_CON, COAP_PUT, 0); + + if(count_put % 2 == 0) { + coap_set_header_uri_path(request, service_urls[3]); + generate_random_payload(3, msg); + coap_set_payload(request, (uint8_t *)msg, sizeof(msg) - 1); + PRINTF("PUT %d: %s PAYLOAD: %s\n", count_get, service_urls[3], msg); + } else { + coap_set_header_uri_path(request, service_urls[2]); + generate_random_payload(2, msg); + coap_set_payload(request, (uint8_t *)msg, sizeof(msg) - 1); + PRINTF("PUT %d: %s PAYLOAD: %s\n", count_get, service_urls[2], msg); + } + +#if PLATFORM_HAS_LEDS + /* set yellow led when sending packet */ + leds_on(LEDS_YELLOW); +#endif + COAP_BLOCKING_REQUEST(&server_ipaddr, REMOTE_PORT, request, + client_chunk_handler); + + + } + + /* after 2 more timeout we do GET to check the resource new value */ + if((count_get > 10) && ((count_get - 2) % 10 == 0)) { + coap_init_message(request, COAP_TYPE_CON, COAP_GET, 0); + + if(count_put % 2 == 0) { + coap_set_header_uri_path(request, service_urls[3]); + PRINTF("GET %d: %s\n", count_get, service_urls[3]); + } else { + coap_set_header_uri_path(request, service_urls[2]); + PRINTF("GET %d: %s\n", count_get, service_urls[2]); + } + +#if PLATFORM_HAS_LEDS + /* set yellow led when sending packet */ + leds_on(LEDS_YELLOW); +#endif + COAP_BLOCKING_REQUEST(&server_ipaddr, REMOTE_PORT, request, + client_chunk_handler); + } + +/*---------------------------------------------------------------------------*/ + + /* test GET with observe option when timer expires the 15th time */ + if(count_get == 15) { + /* PRINTF("GET %d: OBSERVE: %s\n", count_get, service_urls[2]); */ + toggle_observation(); + } + + etimer_reset(&et); + } + } /* END_WHILE(1) */ + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/coap-server.c b/examples/avr-rss2/ipv6/dc-rpl-coap/coap-server.c new file mode 100644 index 000000000..8e1ee552d --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/coap-server.c @@ -0,0 +1,269 @@ +/* + * 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" +#include "contiki-lib.h" +#include "contiki-net.h" +#include "net/ip/uip.h" +#include "net/rpl/rpl.h" + +#include "net/netstack.h" +/* #include "dev/leds.h" */ +#include +#include +#include +#include + +/* + #define DEBUG DEBUG_PRINT + #include "net/ip/uip-debug.h" + */ +/**************************************************************************/ +/* add mock-up code for DC-DC converter */ +/* #include "control.h" */ +/* #include "vdc.h" */ +#ifdef CO2 +#include "dev/co2_sa_kxx-sensor.h" +#endif +#include "dev/dc-status-sensor.h" +#include "dev/dc-vdc-sensor.h" +#include "dev/dc-hw-sensor.h" + +/* from er-rest-example/er-rexample-server.c */ +#include "rest-engine.h" +/* #include "er-coap.h" */ + +#if PLATFORM_HAS_LEDS +#include "dev/leds.h" +#endif + +/* + #if PLATFORM_HAS_BUTTON + #include "dev/button-sensor.h" + #endif + */ +#define DEBUG 1 +#if DEBUG +/* #include */ +#define PRINTF(...) printf(__VA_ARGS__) +#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) +#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) +#else +#define PRINTF(...) +#define PRINT6ADDR(addr) +#define PRINTLLADDR(addr) +#endif + +/* #define TOGGLE_INTERVAL 10 */ +/* #define OBSERVE_INTERVAL 10 */ + +/* + * Resources to be activated need to be imported through the extern keyword. + * The build system automatically compiles the resources in the corresponding sub-directory. + */ +extern resource_t +/* res_hello, */ +/* res_push, */ +/* res_event, */ +/* res_sub; */ +/* res_dc_status_obs; */ +/* res_dc_status, */ +#ifdef CO2 + res_dc_co2, +#endif + res_dc_status_obs, + res_dc_vdc, + res_dc_hwcfg; +/* + #if PLATFORM_HAS_LEDS + extern resource_t + // res_leds, + res_toggle; + #endif + */ +/* #if PLATFORM_HAS_LIGHT */ +/* #include "dev/light-sensor.h" */ +/* extern resource_t res_light; */ +/* #endif */ + +/**************************************************************************/ + +PROCESS(coap_server_process, "CoAP server process"); +AUTOSTART_PROCESSES(&coap_server_process); +/*---------------------------------------------------------------------------*/ +static void +print_local_addresses(void) +{ + int i; + uint8_t state; + + PRINTF("Server IPv6 addresses: "); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(state == ADDR_TENTATIVE || state == ADDR_PREFERRED) { + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n"); + /* hack to make address "final" */ + if(state == ADDR_TENTATIVE) { + uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; + } + } + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(coap_server_process, ev, data) +{ + uip_ipaddr_t ipaddr; + struct uip_ds6_addr *root_if; + + PROCESS_BEGIN(); + + PROCESS_PAUSE(); + +/* SENSORS_ACTIVATE(button_sensor); */ +#ifdef CO2 + SENSORS_ACTIVATE(co2_sa_kxx_sensor); +#endif + SENSORS_ACTIVATE(dc_status_sensor); + SENSORS_ACTIVATE(dc_vdc_sensor); + SENSORS_ACTIVATE(dc_hw_sensor); + +/**************************************************************************/ + +#if PLATFORM_HAS_LEDS +/* initialize leds */ + leds_init(); + leds_on(LEDS_RED); + leds_on(LEDS_YELLOW); +#endif + +/* Initilize DC-DC converter parameters */ +/* ValueInit(); */ +/* VDCInit(); */ +/* + #ifdef PARAMS_CHANNEL + PRINTF("PARAMs channel: %u\n", PARAMS_CHANNEL); + #endif + */ +#ifdef RF_CHANNEL + PRINTF("RF channel: %u\n", RF_CHANNEL); +#endif +#ifdef IEEE802154_PANID + PRINTF("PAN ID: 0x%04X\n", IEEE802154_PANID); +#endif + + PRINTF("uIP buffer: %u\n", UIP_BUFSIZE); + PRINTF("LL header: %u\n", UIP_LLH_LEN); + PRINTF("IP+UDP header: %u\n", UIP_IPUDPH_LEN); + PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE); + + /* Initialize the REST engine. */ + rest_init_engine(); + + /* + * Bind the resources to their Uri-Path. + * WARNING: Activating twice only means alternate path, not two instances! + * All static variables are the same for each URI path. + */ +/* rest_activate_resource(&res_hello, "test/hello"); */ +/* rest_activate_resource(&res_mirror, "debug/mirror"); */ +/* rest_activate_resource(&res_chunks, "test/chunks"); */ +/* rest_activate_resource(&res_separate, "test/separate"); */ +/* rest_activate_resource(&res_push, "test/push"); */ +/* rest_activate_resource(&res_event, "sensors/button"); */ +/* rest_activate_resource(&res_sub, "test/sub"); */ +/* rest_activate_resource(&res_b1_sep_b2, "test/b1sepb2"); */ +#ifdef CO2 + rest_activate_resource(&res_dc_co2, "dcdc/co2"); +#endif + rest_activate_resource(&res_dc_status_obs, "dcdc/status"); +/* rest_activate_resource(&res_dc_status, "dcdc/status"); */ + rest_activate_resource(&res_dc_vdc, "dcdc/vdc"); + rest_activate_resource(&res_dc_hwcfg, "dcdc/hwcfg"); +/* #if PLATFORM_HAS_LEDS */ +/* / * rest_activate_resource(&res_leds, "actuators/leds"); * / */ +/* rest_activate_resource(&res_toggle, "actuators/toggle"); */ +/* #endif */ +/* #if PLATFORM_HAS_LIGHT */ +/* rest_activate_resource(&res_light, "sensors/light"); */ +/* SENSORS_ACTIVATE(light_sensor); */ +/* #endif */ + +/**************************************************************************/ + + PRINTF("CoAP server started\n"); + +#if UIP_CONF_ROUTER +/* The choice of server address determines its 6LoPAN header compression. + * Obviously the choice made here must also be selected in udp-client.c. + * + * For correct Wireshark decoding using a sniffer, add the /64 prefix to the 6LowPAN protocol preferences, + * e.g. set Context 0 to aaaa::. At present Wireshark copies Context/128 and then overwrites it. + * (Setting Context 0 to aaaa::1111:2222:3333:4444 will report a 16 bit compressed address of aaaa::1111:22ff:fe33:xxxx) + * Note Wireshark's IPCMV6 checksum verification depends on the correct uncompressed addresses. + */ + +#if 0 +/* Mode 1 - 64 bits inline */ + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 1); +#elif 1 +/* Mode 2 - 16 bits inline */ + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0x00ff, 0xfe00, 1); +#else +/* Mode 3 - derived from link local (MAC) address */ + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); +#endif + + uip_ds6_addr_add(&ipaddr, 0, ADDR_MANUAL); + root_if = uip_ds6_addr_lookup(&ipaddr); + if(root_if != NULL) { + rpl_dag_t *dag; + dag = rpl_set_root(RPL_DEFAULT_INSTANCE, (uip_ip6addr_t *)&ipaddr); + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + rpl_set_prefix(dag, &ipaddr, 64); + PRINTF("created a new RPL dag\n"); + } else { + PRINTF("failed to create a new RPL DAG\n"); + } +#endif /* UIP_CONF_ROUTER */ + + print_local_addresses(); + + /* The data sink runs with a 100% duty cycle in order to ensure high + packet reception rates. */ + NETSTACK_MAC.off(1); + + while(1) { + PROCESS_WAIT_EVENT(); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/dc-rpl-coap.csc b/examples/avr-rss2/ipv6/dc-rpl-coap/dc-rpl-coap.csc new file mode 100644 index 000000000..40faff223 --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/dc-rpl-coap.csc @@ -0,0 +1,168 @@ + + + [CONTIKI_DIR]/tools/cooja/apps/mrm + [CONTIKI_DIR]/tools/cooja/apps/mspsim + [CONTIKI_DIR]/tools/cooja/apps/avrora + [CONTIKI_DIR]/tools/cooja/apps/native_gateway + [CONTIKI_DIR]/tools/cooja/apps/serial_socket + /home/user/contikiprojects/sics.se/mobility + [CONTIKI_DIR]/tools/cooja/apps/collect-view + /home/user/contikiprojects/sics.se/powertracker + + My simulation + 123456 + 1000000 + + se.sics.cooja.radiomediums.UDGM + 50.0 + 100.0 + 1.0 + 1.0 + + + 40000 + + + se.sics.cooja.avrmote.RSS2MoteType + mote1 + Mote1 + [CONTIKI_DIR]/platform/avr-rss2/examples/ipv6/dc-rpl-coap/coap-server.c + make coap-server.avr-rss2 TARGET=avr-rss2 MCU=atmega128rfr2 + [CONTIKI_DIR]/platform/avr-rss2/examples/ipv6/dc-rpl-coap/coap-server.avr-rss2 + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.RimeAddress + se.sics.cooja.interfaces.IPAddress + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + se.sics.cooja.avrmote.interfaces.AvroraClock + se.sics.cooja.avrmote.interfaces.AvroraMoteID + se.sics.cooja.avrmote.interfaces.AvroraUsart0 + se.sics.cooja.avrmote.interfaces.AvroraUsart1 + se.sics.cooja.avrmote.interfaces.RFR2Radio + se.sics.cooja.avrmote.interfaces.AvroraADC + se.sics.cooja.avrmote.interfaces.AvroraLED + + + se.sics.cooja.avrmote.RSS2MoteType + mote2 + Mote2 + [CONTIKI_DIR]/platform/avr-rss2/examples/ipv6/dc-rpl-coap/coap-client.c + make coap-client.avr-rss2 TARGET=avr-rss2 MCU=atmega128rfr2 + [CONTIKI_DIR]/platform/avr-rss2/examples/ipv6/dc-rpl-coap/coap-client.avr-rss2 + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.RimeAddress + se.sics.cooja.interfaces.IPAddress + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + se.sics.cooja.avrmote.interfaces.AvroraClock + se.sics.cooja.avrmote.interfaces.AvroraMoteID + se.sics.cooja.avrmote.interfaces.AvroraUsart0 + se.sics.cooja.avrmote.interfaces.AvroraUsart1 + se.sics.cooja.avrmote.interfaces.RFR2Radio + se.sics.cooja.avrmote.interfaces.AvroraADC + se.sics.cooja.avrmote.interfaces.AvroraLED + + + + + se.sics.cooja.interfaces.Position + 100.0 + 100.0 + 0.0 + + + se.sics.cooja.avrmote.interfaces.AvroraMoteID + 1 + + mote1 + + + + + se.sics.cooja.interfaces.Position + 110.0 + 100.0 + 0.0 + + + se.sics.cooja.avrmote.interfaces.AvroraMoteID + 2 + + mote2 + + + + se.sics.cooja.plugins.SimControl + 280 + 9 + 160 + 400 + 0 + + + se.sics.cooja.plugins.Visualizer + + true + se.sics.cooja.plugins.skins.IDVisualizerSkin + se.sics.cooja.plugins.skins.GridVisualizerSkin + 3.908924509090908 0.0 0.0 3.908924509090908 -216.43707345454544 -217.89245090909074 + + 400 + 5 + 400 + 1 + 1 + + + se.sics.cooja.plugins.LogListener + + + + + + 1269 + 8 + 240 + 400 + 160 + + + se.sics.cooja.plugins.Notes + + Enter notes here + true + + 989 + 6 + 160 + 680 + 0 + + + se.sics.cooja.plugins.MoteInterfaceViewer + 0 + + Serial port + 0,0 + + 508 + 4 + 389 + 13 + 413 + + + se.sics.cooja.plugins.MoteInterfaceViewer + 1 + + Serial port + 0,0 + + 545 + 3 + 392 + 531 + 413 + + + diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-hw-sensor.c b/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-hw-sensor.c new file mode 100644 index 000000000..d5715b820 --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-hw-sensor.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015, ICT/COS/NSLab, KTH Royal Institute of Technology + * 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 + * dcdc/hwcfg for DC-DC converter hardware configuration + * \author + * Voravit Tanyingyong + */ + +#include "contiki.h" +/* #include "lib/sensors.h" */ +#include "dev/dc-hw-sensor.h" + +const struct sensors_sensor dc_hw_sensor; + +/* + * hw contains 2 parameters + * hw[0] VMAX + * hw[1] IMAX + */ + +uint32_t volatile hw[2] = { 25, 6 }; + +static int +value(int type) +{ + switch(type) { + case 0: + return hw[0]; + + case 1: + return hw[1]; + } + return -1; +} +static int +configure(int type, int c) +{ + switch(type) { + case 0: + if((c >= 0) && (c <= 25)) { + hw[0] = c; + return 0; + } else { + return 1; + } + + case 1: + if((c >= 0) && (c <= 6)) { + hw[1] = c; + return 0; + } else { + return 0; + } + } + return 1; +} +static int +status(int type) +{ + return 1; +} +SENSORS_SENSOR(dc_hw_sensor, "hw sensors", value, configure, status); + diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-hw-sensor.h b/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-hw-sensor.h new file mode 100644 index 000000000..538dd2be3 --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-hw-sensor.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015, ICT/COS/NSLab, KTH Royal Institute of Technology + * 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 + * dcdc/hwcfg header file + * \author + * Voravit Tanyingyong + */ + +#ifndef DC_HW_SENSOR_H +#define DC_HW_SENSOR_H + +#include "lib/sensors.h" + +extern const struct sensors_sensor dc_hw_sensor; + +#endif /* DC_HW_SENSOR_H */ diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-status-sensor.c b/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-status-sensor.c new file mode 100644 index 000000000..c4998e61c --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-status-sensor.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015, ICT/COS/NSLab, KTH Royal Institute of Technology + * 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 + * dcdc/status read-only parameters for power monitoring + * \author + * Voravit Tanyingyong + */ + +#include "contiki.h" +/* #include "lib/sensors.h" */ +#include "dev/dc-status-sensor.h" + +const struct sensors_sensor dc_status_sensor; + +/* + * Status contains 4 parameters + * status[0] VOUT + * status[1] VIN + * status[2] IOUT + * status[3] IIN + */ + +uint32_t volatile s[4] = { 18, 20, 1, 2 }; + +static int +value(int type) +{ + switch(type) { + case 0: + return s[0]; + + case 1: + return s[1]; + + case 2: + return s[2]; + + case 3: + return s[3]; + } + return -1; +} +static int +configure(int type, int c) +{ + return 0; +} +static int +status(int type) +{ + return 1; +} +SENSORS_SENSOR(dc_status_sensor, "DC status sensors", value, configure, status); + diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-status-sensor.h b/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-status-sensor.h new file mode 100644 index 000000000..97bb7c0c2 --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-status-sensor.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015, ICT/COS/NSLab, KTH Royal Institute of Technology + * 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 + * dcdc/status header file + * \author + * Voravit Tanyingyong + */ + +#ifndef DC_STATUS_SENSOR_H +#define DC_STATUS_SENSOR_H + +#include "lib/sensors.h" + +extern const struct sensors_sensor dc_status_sensor; + +#endif /* DC_STATUS_SENSOR_H */ diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-vdc-sensor.c b/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-vdc-sensor.c new file mode 100644 index 000000000..bdec4df70 --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-vdc-sensor.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2015, ICT/COS/NSLab, KTH Royal Institute of Technology + * 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 + * dcdc/vdc for voltage droop control function + * \author + * Voravit Tanyingyong + */ + +#include "contiki.h" +/* #include "lib/sensors.h" */ +#include "dev/dc-vdc-sensor.h" + +const struct sensors_sensor dc_vdc_sensor; + +/* + * vdc contains 3 parameters + * vdc[0] VGRID + * vdc[1] SLOPE + * vdc[2] PMAX + */ + +uint32_t volatile vdc[3] = { 18, 1, 100 }; + +static int +value(int type) +{ + switch(type) { + case 0: + return vdc[0]; + + case 1: + return vdc[1]; + + case 2: + return vdc[2]; + } + return -1; +} +static int +configure(int type, int c) +{ + switch(type) { + case 0: + if((c >= 0) && (c <= 25)) { + vdc[0] = c; + return 0; + } else { + return 1; + } + + case 1: + vdc[1] = c; + return 0; + + case 2: + vdc[2] = c; + return 0; + } + return 1; +} +static int +status(int type) +{ + return 1; +} +SENSORS_SENSOR(dc_vdc_sensor, "vdc sensors", value, configure, status); + diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-vdc-sensor.h b/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-vdc-sensor.h new file mode 100644 index 000000000..72749c1c6 --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/dev/dc-vdc-sensor.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2015, ICT/COS/NSLab, KTH Royal Institute of Technology + * 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 + * dcdc/vdc sensor header file + * \author + * Voravit Tanyingyong + */ + +#ifndef DC_VDC_SENSOR_H +#define DC_VDC_SENSOR_H + +#include "lib/sensors.h" + +extern const struct sensors_sensor dc_vdc_sensor; + +#endif /* DC_VDC_SENSOR_H */ diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/er-dc-test.h b/examples/avr-rss2/ipv6/dc-rpl-coap/er-dc-test.h new file mode 100644 index 000000000..5c34cb847 --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/er-dc-test.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015, ICT/COS/NSLab, KTH Royal Institute of Technology + * 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 + * header file for resources + * \author + * Voravit Tanyingyong + */ + +#ifndef __ER_DC_TEST_H__ +#define __ER_DC_TEST_H__ + +#define DEBUG 1 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#define PRINT6ADDR(addr) PRINTF("[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) +#define PRINTLLADDR(lladdr) PRINTF("[%02x:%02x:%02x:%02x:%02x:%02x]", (lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3], (lladdr)->addr[4], (lladdr)->addr[5]) +#else +#define PRINTF(...) +#define PRINT6ADDR(addr) +#define PRINTLLADDR(addr) +#endif + +/* double expansion */ +#define TO_STRING2(x) # x +#define TO_STRING(x) TO_STRING2(x) + +#define MAX_COAP_PAYLOAD 64 + 1 /* +1 for the terminating zero, which is not transmitted */ +/* #define MAX_PLUGFEST_BODY 2048 */ +/* #define CHUNKS_TOTAL 2012 */ + +#endif /* __ER_DC_TEST_H__ */ diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/project-conf.h b/examples/avr-rss2/ipv6/dc-rpl-coap/project-conf.h new file mode 100644 index 000000000..8193c1ee0 --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/project-conf.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015, ICT/COS/NSLab, KTH Royal Institute of Technology + * 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 + * test rpl configuration. + * \author + * Voravit Tanyingyong + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +/* enable IPv6 */ +/* #ifndef NETSTACK_CONF_WITH_IPV6 */ +#define NETSTACK_CONF_WITH_IPV6 1 +/* #endif / * NETSTACK_CONF_WITH_IPV6 * / */ + +#define NETSTACK_CONF_RDC nullrdc_driver +#define NETSTACK_CONF_MAC nullmac_driver + +#define COAP_OBSERVE_CLIENT 1 +#define COAP_MAX_OBSERVEES 10 +#define COAP_MAX_OPEN_TRANSACTIONS 10 + +/* enable debug to activate PRINT6ADDR macro */ +/* #undef DEBUG_PRINT */ +/* #define DEBUG_PRINT 1 */ + +/* #define PRINTF(...) printf(__VA_ARGS__) */ +/* #define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15]) */ + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/resources/res-dc-co2.c b/examples/avr-rss2/ipv6/dc-rpl-coap/resources/res-dc-co2.c new file mode 100644 index 000000000..45860653a --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/resources/res-dc-co2.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2015, ICT/COS/NSLab, KTH Royal Institute of Technology + * 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 + * dcdc/co2 testing coap with CO2 sensor from SenseAir + * \author + * Voravit Tanyingyong + */ + +/* #include */ +#include +#include +#include "rest-engine.h" +#include "er-coap.h" +#include "er-dc-test.h" +#if PLATFORM_HAS_LEDS +#include "dev/leds.h" +#endif +#include "dev/co2_sa_kxx-sensor.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +RESOURCE(res_dc_co2, "title=\"co2 reading\"", res_get_handler, NULL, NULL, NULL); + +/*---------------------------------------------------------------------------*/ +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + coap_packet_t *const coap_req = (coap_packet_t *)request; + + int co2 = co2_sa_kxx_sensor.value(CO2_SA_KXX_CO2); // 0 is CO2_SA_KXX_CO2 + +#if PLATFORM_HAS_LEDS + /* set red led when receiving a packet */ + leds_on(LEDS_RED); +#endif + + PRINTF("dcdc/co2 GET (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); + + /* Code 2.05 CONTENT is default. */ + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + /* REST.set_header_max_age(response, 30); */ + REST.set_response_payload( + response, + buffer, +/* snprintf((char *)buffer, MAX_COAP_PAYLOAD, "VMX\t%d.000\nIMX\t%d.000\nINT\t%d\n", v_max, i_max, interval)); */ + snprintf((char *)buffer, MAX_COAP_PAYLOAD, "CO2\t%d\n", co2)); + +#if PLATFORM_HAS_LEDS + /* set yellow led when sending packet */ + leds_on(LEDS_YELLOW); +#endif +} + diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/resources/res-dc-hwcfg.c b/examples/avr-rss2/ipv6/dc-rpl-coap/resources/res-dc-hwcfg.c new file mode 100644 index 000000000..6c8091774 --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/resources/res-dc-hwcfg.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2015, ICT/COS/NSLab, KTH Royal Institute of Technology + * 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 + * dcdc/vdc configurable parameters for voltage droop control function + * \author + * Voravit Tanyingyong + */ + +/* #include */ +#include +#include +#include "rest-engine.h" +#include "er-coap.h" +#include "er-dc-test.h" +#if PLATFORM_HAS_LEDS +#include "dev/leds.h" +#endif +#include "dev/dc-hw-sensor.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +RESOURCE(res_dc_hwcfg, "title=\"hwcfg parameters\"", res_get_handler, res_post_put_handler, res_post_put_handler, NULL); + +/*---------------------------------------------------------------------------*/ +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + coap_packet_t *const coap_req = (coap_packet_t *)request; + + int v_max = dc_hw_sensor.value(0); + int i_max = dc_hw_sensor.value(1); + +#if PLATFORM_HAS_LEDS + /* set red led when receiving a packet */ + leds_on(LEDS_RED); +#endif + + PRINTF("dcdc/hwcfg GET (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); + + /* Code 2.05 CONTENT is default. */ + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + /* REST.set_header_max_age(response, 30); */ + REST.set_response_payload( + response, + buffer, +/* snprintf((char *)buffer, MAX_COAP_PAYLOAD, "VMX\t%d.000\nIMX\t%d.000\nINT\t%d\n", v_max, i_max, interval)); */ + snprintf((char *)buffer, MAX_COAP_PAYLOAD, "VMX\t%d.000\nIMX\t%d.000\n", v_max, i_max)); + +#if PLATFORM_HAS_LEDS + /* set yellow led when sending packet */ + leds_on(LEDS_YELLOW); +#endif +} +/*---------------------------------------------------------------------------*/ +static void +res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + coap_packet_t *const coap_req = (coap_packet_t *)request; + +#if PLATFORM_HAS_LEDS + /* set red led when receiving a packet */ + leds_on(LEDS_RED); +#endif + + PRINTF("dcdc/hwcfg PUT (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); + + const char *variable = NULL; + + if(REST.get_post_variable(request, "VMX", &variable) > 0) { + int v_max = atoi(variable); + if(dc_hw_sensor.configure(0, v_max)) { + PRINTF("Value out of range: must be 0 <= VMX <= 30"); + } + } + + if(REST.get_post_variable(request, "IMX", &variable) > 0) { + int i_max = atoi(variable); + if(dc_hw_sensor.configure(1, i_max)) { + PRINTF("Value out of range: must be 0 <= Imax <= 6"); + } + } + + REST.set_response_status(response, REST.status.CHANGED); + +#if PLATFORM_HAS_LEDS + /* set yellow led when sending packet */ + leds_on(LEDS_YELLOW); +#endif +} diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/resources/res-dc-status-obs.c b/examples/avr-rss2/ipv6/dc-rpl-coap/resources/res-dc-status-obs.c new file mode 100644 index 000000000..75d992fe2 --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/resources/res-dc-status-obs.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2015, ICT/COS/NSLab, KTH Royal Institute of Technology + * 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 + * dcdc/status read-only parameters for power monitoring + * \author + * Voravit Tanyingyong + */ + +#include +#include +#include "rest-engine.h" +#include "er-coap.h" +#include "er-coap-observe.h" +#include "../er-dc-test.h" +#if PLATFORM_HAS_LEDS +#include "dev/leds.h" +#endif +#include "dev/dc-status-sensor.h" + +static void res_dc_status_obs_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_dc_status_obs_periodic_handler(void); + +PERIODIC_RESOURCE(res_dc_status_obs, "title=\"status parameters\"", res_dc_status_obs_get_handler, NULL, NULL, NULL, 10 * CLOCK_SECOND, res_dc_status_obs_periodic_handler); + +static uint32_t observe = 0; +static count = 0; +/*---------------------------------------------------------------------------*/ +static void +res_dc_status_obs_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + + int vout_value = dc_status_sensor.value(0); + int vin_value = dc_status_sensor.value(1); + int iout_value = dc_status_sensor.value(2); + int iin_value = dc_status_sensor.value(3); + + /* a request comes from a remote host */ + if(request != NULL) { + +#if PLATFORM_HAS_LEDS + /* set red led when receiving a packet */ + leds_on(LEDS_RED); +#endif + + coap_packet_t *const coap_req = (coap_packet_t *)request; + + PRINTF("dcdc/status GET (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); + + /* if comes with observe then register it */ + if(coap_get_header_observe(request, &observe)) { +/* PRINTF("OBSERVE set\n"); */ + /* respond with empty ack */ + REST.set_header_content_type(response, observe); + REST.set_response_payload(response, 0, 0); + } else { /* if no observe option, then answer to GET request as normal */ +/* PRINTF("OBSERVE NOT set\n"); */ + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + REST.set_response_payload( + response, + buffer, + snprintf((char *)buffer, MAX_COAP_PAYLOAD, "ST\tON\nVO\t%d.000\nIO\t%d.000\nVI\t%d.000\nII\t%d.000\n", vout_value, iout_value, vin_value, iin_value)); + } + } else { /* this is a notification: need to set payload */ +/* PRINTF("NULL REQUEST = PERIODIC\n"); */ + REST.set_response_payload( + response, + buffer, + snprintf((char *)buffer, MAX_COAP_PAYLOAD, "ST\tON\nVO\t%d.000\nIO\t%d.000\nVI\t%d.000\nII\t%d.000\n", vout_value, iout_value, vin_value, iin_value)); + } + count++; + printf("PERIODIC %d: ST:ON VO:%d IO:%d VI:%d II:%d\n", count, vout_value, iout_value, vin_value, iin_value); +#if PLATFORM_HAS_LEDS + /* set yellow led when sending packet */ + leds_on(LEDS_YELLOW); +#endif +} +/*---------------------------------------------------------------------------*/ +static void +res_dc_status_obs_periodic_handler() +{ + /* send periodic notification to the observers */ + REST.notify_subscribers(&res_dc_status_obs); +} diff --git a/examples/avr-rss2/ipv6/dc-rpl-coap/resources/res-dc-vdc.c b/examples/avr-rss2/ipv6/dc-rpl-coap/resources/res-dc-vdc.c new file mode 100644 index 000000000..8157fbf90 --- /dev/null +++ b/examples/avr-rss2/ipv6/dc-rpl-coap/resources/res-dc-vdc.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2015, ICT/COS/NSLab, KTH Royal Institute of Technology + * 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 + * dcdc/vdc configurable parameters for voltage droop control function + * \author + * Voravit Tanyingyong + */ + +/* #include */ +#include +#include +#include "rest-engine.h" +#include "er-coap.h" +#include "er-dc-test.h" +#if PLATFORM_HAS_LEDS +#include "dev/leds.h" +#endif +#include "dev/dc-vdc-sensor.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +RESOURCE(res_dc_vdc, "title=\"vdc parameters\"", res_get_handler, res_post_put_handler, res_post_put_handler, NULL); + +/*---------------------------------------------------------------------------*/ +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + coap_packet_t *const coap_req = (coap_packet_t *)request; + + int vdc_grid = dc_vdc_sensor.value(0); + int vdc_slope = dc_vdc_sensor.value(1); + int vdc_pmax = dc_vdc_sensor.value(2); + +#if PLATFORM_HAS_LEDS + /* set red led when receiving a packet */ + leds_on(LEDS_RED); +#endif + + PRINTF("dcdc/vdc GET (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); + + /* Code 2.05 CONTENT is default. */ + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + /* REST.set_header_max_age(response, 30); */ + REST.set_response_payload( + response, + buffer, + snprintf((char *)buffer, MAX_COAP_PAYLOAD, "VG\t%d.000\nSL\t%d.000\nPMAX\t%d.000\n", vdc_grid, vdc_slope, vdc_pmax)); + +#if PLATFORM_HAS_LEDS + /* set yellow led when sending packet */ + leds_on(LEDS_YELLOW); +#endif +} +/*---------------------------------------------------------------------------*/ +static void +res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + coap_packet_t *const coap_req = (coap_packet_t *)request; + +#if PLATFORM_HAS_LEDS + /* set red led when receiving a packet */ + leds_on(LEDS_RED); +#endif + + PRINTF("dcdc/vdc PUT (%s %u)\n", coap_req->type == COAP_TYPE_CON ? "CON" : "NON", coap_req->mid); + + const char *variable = NULL; + + if(REST.get_post_variable(request, "VG", &variable) > 0) { + int vdc_grid = atoi(variable); + /* PRINTF("VG: %d\n",vdc_grid); */ + if(dc_vdc_sensor.configure(0, vdc_grid)) { + PRINTF("Value out of range: must be 0 <= Vgrid <= Vmax"); + } + } + + if(REST.get_post_variable(request, "SL", &variable) > 0) { + int vdc_slope = atoi(variable); + /* PRINTF("SL: %d\n",vdc_slope); */ + if(dc_vdc_sensor.configure(1, vdc_slope)) { + PRINTF("Error: SLOPE is not set!"); + } + } + + if(REST.get_post_variable(request, "PMX", &variable) > 0) { + int vdc_pmax = atoi(variable); + /* PRINTF("PMAX: %d\n",vdc_pmax); */ + if(dc_vdc_sensor.configure(2, vdc_pmax)) { + PRINTF("Error: PMAX is not set!"); + } + } + + REST.set_response_status(response, REST.status.CHANGED); +#if PLATFORM_HAS_LEDS + /* set yellow led when sending packet */ + leds_on(LEDS_YELLOW); +#endif +} diff --git a/examples/avr-rss2/ipv6/rpl-border-router/Makefile b/examples/avr-rss2/ipv6/rpl-border-router/Makefile new file mode 100644 index 000000000..630d9dd53 --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-border-router/Makefile @@ -0,0 +1,55 @@ +CONTIKI_PROJECT=border-router +all: $(CONTIKI_PROJECT) + +CONTIKI=../../../.. + +#linker optimizations +SMALL=1 + +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" +PROJECT_SOURCEFILES += eth-bridge.c +#PROJECT_SOURCEFILES += enc28j60.c +PROJECT_SOURCEFILES += enc28j60-ip64-driver.c + +APPS += ping6 + +MODULES += dev/enc28j60 core/net/ip64 + +#Simple built-in webserver is the default. +#Override with make WITH_WEBSERVER=0 for no webserver. +#WITH_WEBSERVER=webserver-name will use /apps/webserver-name if it can be +#found in the /apps, /platform/$(TARGET)/apps/, or current directory (in that order). +# WITH_WEBSERVER=webserver for /apps/webserver +# WITH_WEBSERVER=raven-webserver for /platform/avr-raven/apps/raven-webserver/ +#make clean before changing webservers! + +#Note /apps/webserver contains a 2500 byte style sheet which is a severe test +#of the slip connection. Large MSS together with low baud rates without flow +#control will overrun the transmit buffer when the style sheet is requested. + +WITH_WEBSERVER=1 +ifeq ($(WITH_WEBSERVER),1) +CFLAGS += -DUIP_CONF_TCP=1 +CFLAGS += -DWEBSERVER=1 +PROJECT_SOURCEFILES += httpd-simple.c +else ifneq ($(WITH_WEBSERVER), 0) +APPS += $(WITH_WEBSERVER) +CFLAGS += -DUIP_CONF_TCP=1 +CFLAGS += -DWEBSERVER=2 +endif + +ifeq ($(PREFIX),) + PREFIX = aaaa::1/64 +endif + +CONTIKI_WITH_IPV6 = 1 +include $(CONTIKI)/Makefile.include + +$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c + (cd $(CONTIKI)/tools && $(MAKE) tunslip6) + +connect-router: $(CONTIKI)/tools/tunslip6 + sudo $(CONTIKI)/tools/tunslip6 $(PREFIX) + +connect-router-cooja: $(CONTIKI)/tools/tunslip6 + sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 $(PREFIX) diff --git a/examples/avr-rss2/ipv6/rpl-border-router/README.ETHERNET.md b/examples/avr-rss2/ipv6/rpl-border-router/README.ETHERNET.md new file mode 100644 index 000000000..ab63e9ae3 --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-border-router/README.ETHERNET.md @@ -0,0 +1,66 @@ +Document version: 2015-12-29 + +HOWTO connect the Microchip enc28j60 module +=========================================== + +It's possible to to add Ethernet to most microcontrollers having a SPI inter- +face. In the Atmel world the SPI pins are used for the ISP programming. Usually +a 6-pin header. Named MOSI, MISO, SCK, CS (Chup Select), Vcc, GND + +One popular Ethernet chip is Microchip ENC28J60. It been used for quite some +time and is easy to program and are also supported by many platforms and +projects. Contiki has files under: + +Most focus fon AVR platforms. The SPI is used by Atmel ISP-progammings +interface. In addition to those pins you to selects a pin for chip +select (CS). + +dev/enc28j60/ +The low-level SPI drives is platform or rather CPU-specific. The avr-rss2 +platform adds the low-level drivers for Atmel. + +platform/avr-rss2/enc28j60_avr.[ch] +This should be usable on most 8-bit avr platforms. + +The power consumption might be a problem. The enc28j60 consumes 160mA at 3.3V +when transmitting. The LDO (voltage reg. LP2950) on the mote can only handle +100mA. So external power is needed. Below is a description of a prototype. + +Used components: +---------------- +Externel power supply 5V. +Small breadboard +DC-jack +Voltage Reg. LCP1700 3.3V +Capacitor 4.7uF +enc28j60 (From Ebay) +Pin-headers +Cables 2x5 (enc28j60) 2x3 SPI (AtMega node) + +Used colors: +Black GND +Red VCC 3.3V +Yellow SCK +Green MISO +White MOSI +Blue CS (Chip select) + +SPI (Connector view) +-------------------- +GREEN YELLOW NC +RED WHITE BLACK + +CS is connected to external temp sensor middle pin. Consequently the +external temp sensor can not be used in this application. + +Pictures +-------- +![Module] ( http://www.radio-sensors.com/pictures/enc28j60.jpg) +![Connector] (http://www.radio-sensors.com/pictures/enc28c60-cable.jpg) + + +References +----------- + + + diff --git a/examples/avr-rss2/ipv6/rpl-border-router/README.md b/examples/avr-rss2/ipv6/rpl-border-router/README.md new file mode 100644 index 000000000..fa3019c2d --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-border-router/README.md @@ -0,0 +1,17 @@ +Document version: 2016-02-22 + +An ethernet-to-802.15.4 NAT/GW IP64 +=================================== + +This project is heavily based on the rpl-border-router in the example directory +using the IP64 framework. This work is done Contiki/Thingsquare as the driver +for enc28j60. + +But rather than using slip as in the original example an ethernet interface +the Microchip enc28j60 is used. The needed SPI-glue for AtMega's is added by +this platform. (avr-rss2) + +See the README.ETHERNET.md for ethernet module info. + + + diff --git a/examples/avr-rss2/ipv6/rpl-border-router/border-router.c b/examples/avr-rss2/ipv6/rpl-border-router/border-router.c new file mode 100644 index 000000000..6a992982f --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-border-router/border-router.c @@ -0,0 +1,388 @@ +/* + * 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 + * border-router + * \author + * Niclas Finne + * Joakim Eriksson + * Nicolas Tsiftes + */ + +#include "contiki.h" +#include "contiki-lib.h" +#include "contiki-net.h" +#include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" +#include "ip64.h" +#include "net/rpl/rpl.h" +#include "enc28j60.h" +#include "enc28j60-ip64-driver.h" +#include "net/netstack.h" +#include "dev/button-sensor.h" +#include "dev/slip.h" +#include "dev/leds.h" + +#include +#include +#include +#include + +#define DEBUG DEBUG_PRINT +#include "net/ip/uip-debug.h" + +static uip_ipaddr_t prefix; +static uint8_t prefix_set; + +PROCESS(border_router_process, "Border router process"); + +#if WEBSERVER==0 +/* No webserver */ +AUTOSTART_PROCESSES(&border_router_process); +#elif WEBSERVER>1 +/* Use an external webserver application */ +#include "webserver-nogui.h" +AUTOSTART_PROCESSES(&border_router_process,&webserver_nogui_process); +#else +/* Use simple webserver with only one page for minimum footprint. + * Multiple connections can result in interleaved tcp segments since + * a single static buffer is used for all segments. + */ +#include "httpd-simple.h" +/* The internal webserver can provide additional information if + * enough program flash is available. + */ +#define WEBSERVER_CONF_LOADTIME 1 +#define WEBSERVER_CONF_FILESTATS 1 +#define WEBSERVER_CONF_NEIGHBOR_STATUS 1 +/* Adding links requires a larger RAM buffer. To avoid static allocation + * the stack can be used for formatting; however tcp retransmissions + * and multiple connections can result in garbled segments. + * TODO:use PSOCk_GENERATOR_SEND and tcp state storage to fix this. + */ +#define WEBSERVER_CONF_ROUTE_LINKS 1 +#if WEBSERVER_CONF_ROUTE_LINKS +#define BUF_USES_STACK 1 +#endif + +PROCESS(webserver_nogui_process, "Web server"); +PROCESS_THREAD(webserver_nogui_process, ev, data) +{ + PROCESS_BEGIN(); + + httpd_init(); + + while(1) { + PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event); + httpd_appcall(data); + } + + PROCESS_END(); +} +AUTOSTART_PROCESSES(&border_router_process,&webserver_nogui_process); + +static const char *TOP = "ContikiRPL\n"; +static const char *BOTTOM = "\n"; +#if BUF_USES_STACK +static char *bufptr, *bufend; +#define ADD(...) do { \ + bufptr += snprintf(bufptr, bufend - bufptr, __VA_ARGS__); \ + } while(0) +#else +static char buf[256]; +static int blen; +#define ADD(...) do { \ + blen += snprintf(&buf[blen], sizeof(buf) - blen, __VA_ARGS__); \ + } while(0) +#endif + +/*---------------------------------------------------------------------------*/ +static void +ipaddr_add(const uip_ipaddr_t *addr) +{ + uint16_t a; + int i, f; + for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0) ADD("::"); + } else { + if(f > 0) { + f = -1; + } else if(i > 0) { + ADD(":"); + } + ADD("%x", a); + } + } +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(generate_routes(struct httpd_state *s)) +{ + static uip_ds6_route_t *r; + static uip_ds6_nbr_t *nbr; +#if BUF_USES_STACK + char buf[256]; +#endif +#if WEBSERVER_CONF_LOADTIME + static clock_time_t numticks; + numticks = clock_time(); +#endif + + PSOCK_BEGIN(&s->sout); + + SEND_STRING(&s->sout, TOP); +#if BUF_USES_STACK + bufptr = buf;bufend=bufptr+sizeof(buf); +#else + blen = 0; +#endif + ADD("Neighbors
");
+
+  for(nbr = nbr_table_head(ds6_neighbors);
+      nbr != NULL;
+      nbr = nbr_table_next(ds6_neighbors, nbr)) {
+
+#if WEBSERVER_CONF_NEIGHBOR_STATUS
+#if BUF_USES_STACK
+{char* j=bufptr+25;
+      ipaddr_add(&nbr->ipaddr);
+      while (bufptr < j) ADD(" ");
+      switch (nbr->state) {
+      case NBR_INCOMPLETE: ADD(" INCOMPLETE");break;
+      case NBR_REACHABLE: ADD(" REACHABLE");break;
+      case NBR_STALE: ADD(" STALE");break;
+      case NBR_DELAY: ADD(" DELAY");break;
+      case NBR_PROBE: ADD(" NBR_PROBE");break;
+      }
+}
+#else
+{uint8_t j=blen+25;
+      ipaddr_add(&nbr->ipaddr);
+      while (blen < j) ADD(" ");
+      switch (nbr->state) {
+      case NBR_INCOMPLETE: ADD(" INCOMPLETE");break;
+      case NBR_REACHABLE: ADD(" REACHABLE");break;
+      case NBR_STALE: ADD(" STALE");break;
+      case NBR_DELAY: ADD(" DELAY");break;
+      case NBR_PROBE: ADD(" NBR_PROBE");break;
+      }
+}
+#endif
+#else
+      ipaddr_add(&nbr->ipaddr);
+#endif
+
+      ADD("\n");
+#if BUF_USES_STACK
+      if(bufptr > bufend - 45) {
+        SEND_STRING(&s->sout, buf);
+        bufptr = buf; bufend = bufptr + sizeof(buf);
+      }
+#else
+      if(blen > sizeof(buf) - 45) {
+        SEND_STRING(&s->sout, buf);
+        blen = 0;
+      }
+#endif
+  }
+  ADD("
Routes
");
+  SEND_STRING(&s->sout, buf);
+#if BUF_USES_STACK
+  bufptr = buf; bufend = bufptr + sizeof(buf);
+#else
+  blen = 0;
+#endif
+
+  for(r = uip_ds6_route_head(); r != NULL; r = uip_ds6_route_next(r)) {
+
+#if BUF_USES_STACK
+#if WEBSERVER_CONF_ROUTE_LINKS
+    ADD("ipaddr);
+    ADD("]/status.shtml>");
+    ipaddr_add(&r->ipaddr);
+    ADD("");
+#else
+    ipaddr_add(&r->ipaddr);
+#endif
+#else
+#if WEBSERVER_CONF_ROUTE_LINKS
+    ADD("ipaddr);
+    ADD("]/status.shtml>");
+    SEND_STRING(&s->sout, buf); //TODO: why tunslip6 needs an output here, wpcapslip does not
+    blen = 0;
+    ipaddr_add(&r->ipaddr);
+    ADD("");
+#else
+    ipaddr_add(&r->ipaddr);
+#endif
+#endif
+    ADD("/%u (via ", r->length);
+    ipaddr_add(uip_ds6_route_nexthop(r));
+    if(1 || (r->state.lifetime < 600)) {
+      ADD(") %lus\n", (unsigned long)r->state.lifetime);
+    } else {
+      ADD(")\n");
+    }
+    SEND_STRING(&s->sout, buf);
+#if BUF_USES_STACK
+    bufptr = buf; bufend = bufptr + sizeof(buf);
+#else
+    blen = 0;
+#endif
+  }
+  ADD("
"); + +#if WEBSERVER_CONF_FILESTATS + static uint16_t numtimes; + ADD("
This page sent %u times",++numtimes); +#endif + +#if WEBSERVER_CONF_LOADTIME + numticks = clock_time() - numticks + 1; + ADD(" (%lu.%02lu sec)",numticks/CLOCK_SECOND,((100*(numticks%CLOCK_SECOND))/CLOCK_SECOND)); +#endif + + + SEND_STRING(&s->sout, buf); + SEND_STRING(&s->sout, BOTTOM); + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +httpd_simple_script_t +httpd_simple_get_script(const char *name) +{ + return generate_routes; +} + +#endif /* WEBSERVER */ + +/*---------------------------------------------------------------------------*/ +static void +print_local_addresses(void) +{ + int i; + uint8_t state; + + PRINTA("Server IPv6 addresses:\n"); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && + (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { + PRINTA(" "); + uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); + PRINTA("\n"); + } + } +} +/*---------------------------------------------------------------------------*/ +void +request_prefix(void) +{ + /* mess up uip_buf with a dirty request... */ + uip_buf[0] = '?'; + uip_buf[1] = 'P'; + uip_len = 2; + //slip_send(); + uip_clear_buf(); +} +/*---------------------------------------------------------------------------*/ +void +set_prefix_64(uip_ipaddr_t *prefix_64) +{ + rpl_dag_t *dag; + uip_ipaddr_t ipaddr; + memcpy(&prefix, prefix_64, 16); + memcpy(&ipaddr, prefix_64, 16); + prefix_set = 1; + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + + dag = rpl_set_root(RPL_DEFAULT_INSTANCE, &ipaddr); + if(dag != NULL) { + rpl_set_prefix(dag, &prefix, 64); + PRINTF("created a new RPL dag\n"); + } +} + +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(border_router_process, ev, data) +{ + PROCESS_BEGIN(); + uip_ipaddr_t ipaddr; + +/* While waiting for the prefix to be sent through the SLIP connection, the future + * border router can join an existing DAG as a parent or child, or acquire a default + * router that will later take precedence over the SLIP fallback interface. + * Prevent that by turning the radio off until we are initialized as a DAG root. + */ + prefix_set = 0; + NETSTACK_MAC.off(0); + + PROCESS_PAUSE(); + + SENSORS_ACTIVATE(button_sensor); + leds_init(); + ip64_init(); + + PRINTF("RPL-Border router started\n"); +#if 0 + /* The border router runs with a 100% duty cycle in order to ensure high + packet reception rates. + Note if the MAC RDC is not turned off now, aggressive power management of the + cpu will interfere with establishing the SLIP connection */ + NETSTACK_MAC.off(1); +#endif + + /* Now turn the radio on, but disable radio duty cycling. + * Since we are the DAG root, reception delays would constrain mesh throughbut. + */ + NETSTACK_MAC.off(1); + +/* Derived from link local (MAC) address */ + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + set_prefix_64(&ipaddr); + print_local_addresses(); + + while(1) { + PROCESS_YIELD(); + leds_on(LEDS_YELLOW); + if (ev == sensors_event && data == &button_sensor) { + PRINTF("Initiating global repair\n"); + rpl_repair_root(RPL_DEFAULT_INSTANCE); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/avr-rss2/ipv6/rpl-border-router/enc28j60-ip64-driver.c b/examples/avr-rss2/ipv6/rpl-border-router/enc28j60-ip64-driver.c new file mode 100644 index 000000000..6bc4122a4 --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-border-router/enc28j60-ip64-driver.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2012-2013, Thingsquare, http://www.thingsquare.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. + * + */ + +#include "contiki.h" +#include "enc28j60.h" +#include "enc28j60-ip64-driver.h" +#include "net/linkaddr.h" + +#include "ip64.h" +#include "ip64-eth.h" + +#include +#include + +PROCESS(enc28j60_ip64_driver_process, "ENC28J60 IP64 driver"); + +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ + uint8_t eui64[8]; + uint8_t macaddr[6]; + + /* Assume that linkaddr_node_addr holds the EUI64 of this device. */ + memcpy(eui64, &linkaddr_node_addr, sizeof(eui64)); + + /* Mangle the EUI64 into a 48-bit Ethernet address. */ + memcpy(&macaddr[0], &eui64[0], 3); + memcpy(&macaddr[3], &eui64[5], 3); + + /* In case the OUI happens to contain a broadcast bit, we mask that + out here. */ + macaddr[0] = (macaddr[0] & 0xfe); + + /* Set the U/L bit, in order to create a locally administered MAC address */ + macaddr[0] = (macaddr[0] | 0x02); + + memcpy(ip64_eth_addr.addr, macaddr, sizeof(macaddr)); + + printf("MAC addr %02x:%02x:%02x:%02x:%02x:%02x\n", + macaddr[0], macaddr[1], macaddr[2], + macaddr[3], macaddr[4], macaddr[5]); + enc28j60_init(macaddr); + process_start(&enc28j60_ip64_driver_process, NULL); +} +/*---------------------------------------------------------------------------*/ +static int +output(uint8_t *packet, uint16_t len) +{ + enc28j60_send(packet, len); + return len; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(enc28j60_ip64_driver_process, ev, data) +{ + static int len; + static struct etimer e; + PROCESS_BEGIN(); + + while(1) { + etimer_set(&e, 1); + PROCESS_WAIT_EVENT(); + len = enc28j60_read(ip64_packet_buffer, ip64_packet_buffer_maxlen); + if(len > 0) { + IP64_INPUT(ip64_packet_buffer, len); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +const struct ip64_driver enc28j60_ip64_driver = { + init, + output +}; +/*---------------------------------------------------------------------------*/ diff --git a/examples/avr-rss2/ipv6/rpl-border-router/enc28j60-ip64-driver.h b/examples/avr-rss2/ipv6/rpl-border-router/enc28j60-ip64-driver.h new file mode 100644 index 000000000..29d3ed5a4 --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-border-router/enc28j60-ip64-driver.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012-2013, Thingsquare, http://www.thingsquare.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. + * + */ + +#ifndef ENC28J60_IP64_DRIVER_H +#define ENC28J60_IP64_DRIVER_H + +#include "ip64-driver.h" +extern const struct ip64_driver enc28j60_ip64_driver; + +#endif /* ENC28J60_IP64_DRIVER_H */ diff --git a/examples/avr-rss2/ipv6/rpl-border-router/eth-bridge.c b/examples/avr-rss2/ipv6/rpl-border-router/eth-bridge.c new file mode 100644 index 000000000..b5d9ec498 --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-border-router/eth-bridge.c @@ -0,0 +1,33 @@ +#include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" +#include +#include "ip64-eth-interface.h" + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) + +#define DEBUG DEBUG_NONE +#include "net/ip/uip-debug.h" + +static void +init(void) +{ + PRINTF("eth-bridge: init\n"); + ip64_eth_interface.init(); +} +/*---------------------------------------------------------------------------*/ +static int +output() +{ + PRINTF("eth-bridge: src="); + PRINT6ADDR(&UIP_IP_BUF->srcipaddr); + PRINTF(" dst="); + PRINT6ADDR(&UIP_IP_BUF->destipaddr); + PRINTF("\n"); + ip64_eth_interface.output(); + return 0; +} +/*---------------------------------------------------------------------------*/ +const struct uip_fallback_interface rpl_interface = { + init, output +}; +/*---------------------------------------------------------------------------*/ diff --git a/examples/avr-rss2/ipv6/rpl-border-router/httpd-simple.c b/examples/avr-rss2/ipv6/rpl-border-router/httpd-simple.c new file mode 100644 index 000000000..115e54d45 --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-border-router/httpd-simple.c @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \file + * A simple web server forwarding page generation to a protothread + * \author + * Adam Dunkels + * Niclas Finne + * Joakim Eriksson + */ + +#include +#include + +#include "contiki-net.h" + +//#include "urlconv.h" + +#include "httpd-simple.h" +#define webserver_log_file(...) +#define webserver_log(...) + +#ifndef WEBSERVER_CONF_CFS_CONNS +#define CONNS UIP_CONNS +#else /* WEBSERVER_CONF_CFS_CONNS */ +#define CONNS WEBSERVER_CONF_CFS_CONNS +#endif /* WEBSERVER_CONF_CFS_CONNS */ + +#ifndef WEBSERVER_CONF_CFS_URLCONV +#define URLCONV 0 +#else /* WEBSERVER_CONF_CFS_URLCONV */ +#define URLCONV WEBSERVER_CONF_CFS_URLCONV +#endif /* WEBSERVER_CONF_CFS_URLCONV */ + +#define STATE_WAITING 0 +#define STATE_OUTPUT 1 + +MEMB(conns, struct httpd_state, CONNS); + +#define ISO_nl 0x0a +#define ISO_space 0x20 +#define ISO_period 0x2e +#define ISO_slash 0x2f + +/*---------------------------------------------------------------------------*/ +static const char *NOT_FOUND = "" +"
" +"

404 - file not found

" +"
" +"" +""; +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(send_string(struct httpd_state *s, const char *str)) +{ + PSOCK_BEGIN(&s->sout); + + SEND_STRING(&s->sout, str); + + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +const char http_content_type_html[] = "Content-type: text/html\r\n\r\n"; +static +PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr)) +{ + /* char *ptr; */ + + PSOCK_BEGIN(&s->sout); + + SEND_STRING(&s->sout, statushdr); + + /* ptr = strrchr(s->filename, ISO_period); */ + /* if(ptr == NULL) { */ + /* s->ptr = http_content_type_plain; */ + /* } else if(strcmp(http_html, ptr) == 0) { */ + /* s->ptr = http_content_type_html; */ + /* } else if(strcmp(http_css, ptr) == 0) { */ + /* s->ptr = http_content_type_css; */ + /* } else if(strcmp(http_png, ptr) == 0) { */ + /* s->ptr = http_content_type_png; */ + /* } else if(strcmp(http_gif, ptr) == 0) { */ + /* s->ptr = http_content_type_gif; */ + /* } else if(strcmp(http_jpg, ptr) == 0) { */ + /* s->ptr = http_content_type_jpg; */ + /* } else { */ + /* s->ptr = http_content_type_binary; */ + /* } */ + /* SEND_STRING(&s->sout, s->ptr); */ + SEND_STRING(&s->sout, http_content_type_html); + PSOCK_END(&s->sout); +} +/*---------------------------------------------------------------------------*/ +const char http_header_200[] = "HTTP/1.0 200 OK\r\nServer: Contiki/2.4 http://www.sics.se/contiki/\r\nConnection: close\r\n"; +const char http_header_404[] = "HTTP/1.0 404 Not found\r\nServer: Contiki/2.4 http://www.sics.se/contiki/\r\nConnection: close\r\n"; +static +PT_THREAD(handle_output(struct httpd_state *s)) +{ + PT_BEGIN(&s->outputpt); + + s->script = NULL; + s->script = httpd_simple_get_script(&s->filename[1]); + if(s->script == NULL) { + strncpy(s->filename, "/notfound.html", sizeof(s->filename)); + PT_WAIT_THREAD(&s->outputpt, + send_headers(s, http_header_404)); + PT_WAIT_THREAD(&s->outputpt, + send_string(s, NOT_FOUND)); + uip_close(); + webserver_log_file(&uip_conn->ripaddr, "404 - not found"); + PT_EXIT(&s->outputpt); + } else { + PT_WAIT_THREAD(&s->outputpt, + send_headers(s, http_header_200)); + PT_WAIT_THREAD(&s->outputpt, s->script(s)); + } + s->script = NULL; + PSOCK_CLOSE(&s->sout); + PT_END(&s->outputpt); +} +/*---------------------------------------------------------------------------*/ +const char http_get[] = "GET "; +const char http_index_html[] = "/index.html"; +//const char http_referer[] = "Referer:" +static +PT_THREAD(handle_input(struct httpd_state *s)) +{ + PSOCK_BEGIN(&s->sin); + + PSOCK_READTO(&s->sin, ISO_space); + + if(strncmp(s->inputbuf, http_get, 4) != 0) { + PSOCK_CLOSE_EXIT(&s->sin); + } + PSOCK_READTO(&s->sin, ISO_space); + + if(s->inputbuf[0] != ISO_slash) { + PSOCK_CLOSE_EXIT(&s->sin); + } + +#if URLCONV + s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0; + urlconv_tofilename(s->filename, s->inputbuf, sizeof(s->filename)); +#else /* URLCONV */ + if(s->inputbuf[1] == ISO_space) { + strncpy(s->filename, http_index_html, sizeof(s->filename)); + } else { + s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0; + strncpy(s->filename, s->inputbuf, sizeof(s->filename)); + } +#endif /* URLCONV */ + + webserver_log_file(&uip_conn->ripaddr, s->filename); + + s->state = STATE_OUTPUT; + + while(1) { + PSOCK_READTO(&s->sin, ISO_nl); +#if 0 + if(strncmp(s->inputbuf, http_referer, 8) == 0) { + s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0; + webserver_log(s->inputbuf); + } +#endif + } + + PSOCK_END(&s->sin); +} +/*---------------------------------------------------------------------------*/ +static void +handle_connection(struct httpd_state *s) +{ + handle_input(s); + if(s->state == STATE_OUTPUT) { + handle_output(s); + } +} + +/*---------------------------------------------------------------------------*/ +void +httpd_appcall(void *state) +{ + struct httpd_state *s = (struct httpd_state *)state; + + if(uip_closed() || uip_aborted() || uip_timedout()) { + if(s != NULL) { + s->script = NULL; + memb_free(&conns, s); + } + } else if(uip_connected()) { + s = (struct httpd_state *)memb_alloc(&conns); + if(s == NULL) { + uip_abort(); + webserver_log_file(&uip_conn->ripaddr, "reset (no memory block)"); + return; + } + tcp_markconn(uip_conn, s); + PSOCK_INIT(&s->sin, (uint8_t *)s->inputbuf, sizeof(s->inputbuf) - 1); + PSOCK_INIT(&s->sout, (uint8_t *)s->inputbuf, sizeof(s->inputbuf) - 1); + PT_INIT(&s->outputpt); + s->script = NULL; + s->state = STATE_WAITING; + timer_set(&s->timer, CLOCK_SECOND * 10); + handle_connection(s); + } else if(s != NULL) { + if(uip_poll()) { + if(timer_expired(&s->timer)) { + uip_abort(); + s->script = NULL; + memb_free(&conns, s); + webserver_log_file(&uip_conn->ripaddr, "reset (timeout)"); + } + } else { + timer_restart(&s->timer); + } + handle_connection(s); + } else { + uip_abort(); + } +} + +/*---------------------------------------------------------------------------*/ +void +httpd_init(void) +{ + + tcp_listen(UIP_HTONS(80)); + memb_init(&conns); +#if URLCONV + urlconv_init(); +#endif /* URLCONV */ +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/avr-rss2/ipv6/rpl-border-router/httpd-simple.h b/examples/avr-rss2/ipv6/rpl-border-router/httpd-simple.h new file mode 100644 index 000000000..a16dbd99e --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-border-router/httpd-simple.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \file + * A simple webserver + * \author + * Adam Dunkels + * Niclas Finne + * Joakim Eriksson + */ + +#ifndef HTTPD_SIMPLE_H_ +#define HTTPD_SIMPLE_H_ + +#include "contiki-net.h" + +/* The current internal border router webserver ignores the requested file name */ +/* and needs no per-connection output buffer, so save some RAM */ +#ifndef WEBSERVER_CONF_CFS_PATHLEN +#define HTTPD_PATHLEN 2 +#else /* WEBSERVER_CONF_CFS_CONNS */ +#define HTTPD_PATHLEN WEBSERVER_CONF_CFS_PATHLEN +#endif /* WEBSERVER_CONF_CFS_CONNS */ + +struct httpd_state; +typedef char (* httpd_simple_script_t)(struct httpd_state *s); + +struct httpd_state { + struct timer timer; + struct psock sin, sout; + struct pt outputpt; + char inputbuf[HTTPD_PATHLEN + 24]; +/*char outputbuf[UIP_TCP_MSS]; */ + char filename[HTTPD_PATHLEN]; + httpd_simple_script_t script; + char state; +}; + +void httpd_init(void); +void httpd_appcall(void *state); + +httpd_simple_script_t httpd_simple_get_script(const char *name); + +#define SEND_STRING(s, str) PSOCK_SEND(s, (uint8_t *)str, strlen(str)) + +#endif /* HTTPD_SIMPLE_H_ */ diff --git a/examples/avr-rss2/ipv6/rpl-border-router/project-conf.h b/examples/avr-rss2/ipv6/rpl-border-router/project-conf.h new file mode 100644 index 000000000..f1d9e8cda --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-border-router/project-conf.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef PROJECT_ROUTER_CONF_H_ +#define PROJECT_ROUTER_CONF_H_ + +#define NETSTACK_CONF_RDC nullrdc_driver +#define NETSTACK_CONF_MAC nullmac_driver + +#ifndef UIP_FALLBACK_INTERFACE +#define UIP_FALLBACK_INTERFACE rpl_interface +#endif + +#ifndef QUEUEBUF_CONF_NUM +#define QUEUEBUF_CONF_NUM 4 +#endif + +#ifndef UIP_CONF_BUFFER_SIZE +#define UIP_CONF_BUFFER_SIZE 600 +#endif + +#ifndef UIP_CONF_RECEIVE_WINDOW +#define UIP_CONF_RECEIVE_WINDOW 60 +#endif + +#ifndef WEBSERVER_CONF_CFS_CONNS +#define WEBSERVER_CONF_CFS_CONNS 2 +#endif + +#endif /* PROJECT_ROUTER_CONF_H_ */ diff --git a/examples/avr-rss2/ipv6/rpl-udp-report/Makefile b/examples/avr-rss2/ipv6/rpl-udp-report/Makefile new file mode 100644 index 000000000..f4c90317e --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-udp-report/Makefile @@ -0,0 +1,21 @@ + +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" + +all: report sink +APPS=servreg-hack +CONTIKI=../../../.. + +ifdef WITH_COMPOWER +APPS+=powertrace +CFLAGS+= -DCONTIKIMAC_CONF_COMPOWER=1 -DWITH_COMPOWER=1 -DQUEUEBUF_CONF_NUM=4 +endif + +ifdef SERVER_REPLY +CFLAGS+=-DSERVER_REPLY=$(SERVER_REPLY) +endif +ifdef PERIOD +CFLAGS+=-DPERIOD=$(PERIOD) +endif + +CONTIKI_WITH_IPV6 = 1 +include $(CONTIKI)/Makefile.include diff --git a/examples/avr-rss2/ipv6/rpl-udp-report/README.md b/examples/avr-rss2/ipv6/rpl-udp-report/README.md new file mode 100644 index 000000000..1f10ff7e5 --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-udp-report/README.md @@ -0,0 +1,17 @@ + +This application is derived form rpl-udp. + +It's modified to show: + +* Reading out sensors from the avr-rss2 platform. Which should follow the + Contiki conventions. + +* Encode the data according to the sensd TAG format. In effect the sensd + GW and rest of "eco-system" as Mobile apps etc can be used for a simple + and flexible data collection, Sink mote will be connected to sensd GW. + +References and code: +https://github.com/herjulf/sensd +https://github.com/herjulf/Read-Sensors (Android app. Also at Google Play) + + diff --git a/examples/avr-rss2/ipv6/rpl-udp-report/project-conf.h b/examples/avr-rss2/ipv6/rpl-udp-report/project-conf.h new file mode 100644 index 000000000..b004c6335 --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-udp-report/project-conf.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015, RAdio Sensors AB, Uppsala Sweden + * 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 + * Project specific configuration defines for example + * + * \author + * Robert Olsson + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define NETSTACK_CONF_RDC nullrdc_driver +#define NETSTACK_CONF_MAC nullmac_driver + +//#define NETSTACK_CONF_MAC csma_driver +//#define NETSTACK_CONF_RDC contikimac_driver +//#define NETSTACK_CONF_FRAMER framer_802154 +//#define NETSTACK_CONF_RADIO rf230_driver + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/avr-rss2/ipv6/rpl-udp-report/report.c b/examples/avr-rss2/ipv6/rpl-udp-report/report.c new file mode 100644 index 000000000..7915dff2f --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-udp-report/report.c @@ -0,0 +1,240 @@ +/* + * 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" +#include "lib/random.h" +#include "sys/ctimer.h" +#include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" +#include "net/ip/uip-udp-packet.h" +#include "sys/ctimer.h" +#include "dev/leds.h" +#include "dev/battery-sensor.h" +#include "dev/temp_mcu-sensor.h" +#include "dev/light-sensor.h" +#ifdef CO2 +#include "dev/co2_sa_kxx-sensor.h" +#endif +#ifdef WITH_COMPOWER +#include "powertrace.h" +#endif +#include +#include + +#define UDP_CLIENT_PORT 8765 +#define UDP_SERVER_PORT 5678 + +#define UDP_EXAMPLE_ID 190 + +#define DEBUG DEBUG_PRINT +#include "net/ip/uip-debug.h" + +#ifndef PERIOD +#define PERIOD 10 +#endif + +#define START_INTERVAL (15 * CLOCK_SECOND) +#define SEND_INTERVAL (PERIOD * CLOCK_SECOND) +#define SEND_TIME (random_rand() % (SEND_INTERVAL)) +#define MAX_PAYLOAD_LEN 50 + +static struct uip_udp_conn *client_conn; +static uip_ipaddr_t server_ipaddr; + +extern uint16_t node_id; /* Can be set by cooja */ + +/*---------------------------------------------------------------------------*/ +PROCESS(udp_client_process, "UDP client process"); +AUTOSTART_PROCESSES(&udp_client_process); +/*---------------------------------------------------------------------------*/ +static void +tcpip_handler(void) +{ + char *str; + + if(uip_newdata()) { + str = uip_appdata; + str[uip_datalen()] = '\0'; + printf("DATA recv '%s'\n", str); + } +} +/*---------------------------------------------------------------------------*/ +static void +send_packet(void *ptr) +{ + static int seq_id; + char buf[MAX_PAYLOAD_LEN]; + int len = 0; + + seq_id++; + + len += snprintf((char *) &buf[len], sizeof(buf), "&: "); + len += snprintf((char *) &buf[len], sizeof(buf), "V_MCU=%-d ", battery_sensor.value(0)); + + /* + * Cooja needs to set a node_id. So we can skip sensor reading in case of simulation. + */ + + if(node_id == 0) { + len += snprintf((char *) &buf[len], sizeof(buf), "T_MCU=%-d ", temp_mcu_sensor.value(0)); + len += snprintf((char *) &buf[len], sizeof(buf), "LIGHT=%-d ", light_sensor.value(0)); +#ifdef CO2 + len += snprintf((char *) &buf[len], sizeof(buf), "CO2=%-d ", co2_sa_kxx_sensor.value(value)); +#endif + } + PRINTF("TX %d to %d %s\n", + server_ipaddr.u8[sizeof(server_ipaddr.u8) - 1], seq_id, buf); + + leds_on(LEDS_YELLOW); + + uip_udp_packet_sendto(client_conn, buf, strlen(buf), + &server_ipaddr, UIP_HTONS(UDP_SERVER_PORT)); +} +/*---------------------------------------------------------------------------*/ +static void +print_local_addresses(void) +{ + int i; + uint8_t state; + + PRINTF("Client IPv6 addresses: "); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && + (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n"); + /* hack to make address "final" */ + if (state == ADDR_TENTATIVE) { + uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; + } + } + } +} +/*---------------------------------------------------------------------------*/ +static void +set_global_address(void) +{ + uip_ipaddr_t ipaddr; + + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + +/* The choice of server address determines its 6LoPAN header compression. + * (Our address will be compressed Mode 3 since it is derived from our link-local address) + * Obviously the choice made here must also be selected in udp-server.c. + * + * For correct Wireshark decoding using a sniffer, add the /64 prefix to the 6LowPAN protocol preferences, + * e.g. set Context 0 to aaaa::. At present Wireshark copies Context/128 and then overwrites it. + * (Setting Context 0 to aaaa::1111:2222:3333:4444 will report a 16 bit compressed address of aaaa::1111:22ff:fe33:xxxx) + * + * Note the IPCMV6 checksum verification depends on the correct uncompressed addresses. + */ + +#if 0 +/* Mode 1 - 64 bits inline */ + uip_ip6addr(&server_ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 1); +#elif 1 +/* Mode 2 - 16 bits inline */ + uip_ip6addr(&server_ipaddr, 0xaaaa, 0, 0, 0, 0, 0x00ff, 0xfe00, 1); +#else +/* Mode 3 - derived from server link-local (MAC) address */ + uip_ip6addr(&server_ipaddr, 0xaaaa, 0, 0, 0, 0x0250, 0xc2ff, 0xfea8, 0xcd1a); //redbee-econotag +#endif +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(udp_client_process, ev, data) +{ + static struct etimer periodic; + static struct ctimer backoff_timer; +#if WITH_COMPOWER + static int print = 0; +#endif + + PROCESS_BEGIN(); + + PROCESS_PAUSE(); + + SENSORS_ACTIVATE(battery_sensor); + SENSORS_ACTIVATE(temp_mcu_sensor); + SENSORS_ACTIVATE(light_sensor); +#ifdef CO2 + SENSORS_ACTIVATE(co2_sa_kxx_sensor); +#endif + set_global_address(); + leds_init(); + + PRINTF("UDP client process started\n"); + + print_local_addresses(); + + /* new connection with remote host */ + client_conn = udp_new(NULL, UIP_HTONS(UDP_SERVER_PORT), NULL); + if(client_conn == NULL) { + PRINTF("No UDP connection available, exiting the process!\n"); + PROCESS_EXIT(); + } + udp_bind(client_conn, UIP_HTONS(UDP_CLIENT_PORT)); + + PRINTF("Created a connection with the server "); + PRINT6ADDR(&client_conn->ripaddr); + PRINTF(" local/remote port %u/%u\n", + UIP_HTONS(client_conn->lport), UIP_HTONS(client_conn->rport)); + +#if WITH_COMPOWER + powertrace_sniff(POWERTRACE_ON); +#endif + + etimer_set(&periodic, SEND_INTERVAL); + while(1) { + PROCESS_YIELD(); + if(ev == tcpip_event) { + tcpip_handler(); + } + + if(etimer_expired(&periodic)) { + etimer_reset(&periodic); + ctimer_set(&backoff_timer, SEND_TIME, send_packet, NULL); + +#if WITH_COMPOWER + if (print == 0) { + powertrace_print("#P"); + } + if (++print == 3) { + print = 0; + } +#endif + + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/avr-rss2/ipv6/rpl-udp-report/rss2-rpl-udp.csc b/examples/avr-rss2/ipv6/rpl-udp-report/rss2-rpl-udp.csc new file mode 100644 index 000000000..b2d599577 --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-udp-report/rss2-rpl-udp.csc @@ -0,0 +1,167 @@ + + + [CONTIKI_DIR]/tools/cooja/apps/mrm + [CONTIKI_DIR]/tools/cooja/apps/mspsim + [CONTIKI_DIR]/tools/cooja/apps/avrora + [CONTIKI_DIR]/tools/cooja/apps/native_gateway + [CONTIKI_DIR]/tools/cooja/apps/serial_socket + /home/user/contikiprojects/sics.se/mobility + [CONTIKI_DIR]/tools/cooja/apps/collect-view + /home/user/contikiprojects/sics.se/powertracker + + UDP sink/report simulation + 123456 + 1000000 + + se.sics.cooja.radiomediums.UDGM + 50.0 + 100.0 + 1.0 + 1.0 + + + 40000 + + + se.sics.cooja.avrmote.RSS2MoteType + mote1 + Mote1 + [CONTIKI_DIR]/platform/avr-rss2/examples/ipv6/rpl-udp-report/report.c + make report.avr-rss2 TARGET=avr-rss2 MCU=atmega128rfr2 + [CONTIKI_DIR]/platform/avr-rss2/examples/ipv6/rpl-udp-report/report.avr-rss2 + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.RimeAddress + se.sics.cooja.interfaces.IPAddress + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + se.sics.cooja.avrmote.interfaces.AvroraClock + se.sics.cooja.avrmote.interfaces.AvroraMoteID + se.sics.cooja.avrmote.interfaces.AvroraUsart0 + se.sics.cooja.avrmote.interfaces.AvroraUsart1 + se.sics.cooja.avrmote.interfaces.RFR2Radio + se.sics.cooja.avrmote.interfaces.AvroraADC + se.sics.cooja.avrmote.interfaces.AvroraLED + + + se.sics.cooja.avrmote.RSS2MoteType + mote2 + Mote2 + [CONTIKI_DIR]/platform/avr-rss2/examples/ipv6/rpl-udp-report/sink.c + make sink.avr-rss2 TARGET=avr-rss2 MCU=atmega128rfr2 + [CONTIKI_DIR]/platform/avr-rss2/examples/ipv6/rpl-udp-report/sink.avr-rss2 + se.sics.cooja.interfaces.Position + se.sics.cooja.interfaces.RimeAddress + se.sics.cooja.interfaces.IPAddress + se.sics.cooja.interfaces.Mote2MoteRelations + se.sics.cooja.interfaces.MoteAttributes + se.sics.cooja.avrmote.interfaces.AvroraClock + se.sics.cooja.avrmote.interfaces.AvroraMoteID + se.sics.cooja.avrmote.interfaces.AvroraUsart0 + se.sics.cooja.avrmote.interfaces.AvroraUsart1 + se.sics.cooja.avrmote.interfaces.RFR2Radio + se.sics.cooja.avrmote.interfaces.AvroraADC + se.sics.cooja.avrmote.interfaces.AvroraLED + + + + + se.sics.cooja.interfaces.Position + 100.0 + 100.0 + 0.0 + + + se.sics.cooja.avrmote.interfaces.AvroraMoteID + 1 + + mote1 + + + + + se.sics.cooja.interfaces.Position + 110.0 + 100.0 + 0.0 + + + se.sics.cooja.avrmote.interfaces.AvroraMoteID + 2 + + mote2 + + + + se.sics.cooja.plugins.SimControl + 280 + 9 + 160 + 400 + 0 + + + se.sics.cooja.plugins.Visualizer + + true + se.sics.cooja.plugins.skins.IDVisualizerSkin + se.sics.cooja.plugins.skins.GridVisualizerSkin + 3.908924509090908 0.0 0.0 3.908924509090908 -216.43707345454544 -217.89245090909074 + + 400 + 5 + 400 + 1 + 1 + + + se.sics.cooja.plugins.LogListener + + + + + + 1269 + 8 + 240 + 400 + 160 + + + se.sics.cooja.plugins.Notes + + Enter notes here + true + + 989 + 6 + 160 + 680 + 0 + + + se.sics.cooja.plugins.MoteInterfaceViewer + 0 + + Serial port + 0,0 + + 508 + 4 + 389 + 13 + 413 + + + se.sics.cooja.plugins.MoteInterfaceViewer + 1 + + Serial port + 0,0 + + 545 + 3 + 392 + 531 + 413 + + diff --git a/examples/avr-rss2/ipv6/rpl-udp-report/sink.c b/examples/avr-rss2/ipv6/rpl-udp-report/sink.c new file mode 100644 index 000000000..cb8421943 --- /dev/null +++ b/examples/avr-rss2/ipv6/rpl-udp-report/sink.c @@ -0,0 +1,184 @@ +/* + * 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" +#include "contiki-lib.h" +#include "contiki-net.h" +#include "net/ip/uip.h" +#include "net/rpl/rpl.h" + +#include "net/netstack.h" +#include "dev/button-sensor.h" +#include "dev/leds.h" +#include +#include +#include +#include + +#define DEBUG DEBUG_PRINT +#include "net/ip/uip-debug.h" + +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) + +#define UDP_CLIENT_PORT 8765 +#define UDP_SERVER_PORT 5678 + +#define UDP_EXAMPLE_ID 190 + +static struct uip_udp_conn *server_conn; + +PROCESS(udp_server_process, "UDP server process"); +AUTOSTART_PROCESSES(&udp_server_process); +/*---------------------------------------------------------------------------*/ +static void +tcpip_handler(void) +{ + char *appdata; + + if(uip_newdata()) { + + leds_on(LEDS_RED); + + appdata = (char *)uip_appdata; + appdata[uip_datalen()] = 0; + PRINTF("Report RX '%s' from ", appdata); + PRINTF("%d", + UIP_IP_BUF->srcipaddr.u8[sizeof(UIP_IP_BUF->srcipaddr.u8) - 1]); + PRINTF("\n"); +#if SERVER_REPLY + PRINTF("DATA sending reply\n"); + uip_ipaddr_copy(&server_conn->ripaddr, &UIP_IP_BUF->srcipaddr); + uip_udp_packet_send(server_conn, "Reply", sizeof("Reply")); + uip_create_unspecified(&server_conn->ripaddr); +#endif + } +} +/*---------------------------------------------------------------------------*/ +static void +print_local_addresses(void) +{ + int i; + uint8_t state; + + PRINTF("Server IPv6 addresses: "); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(state == ADDR_TENTATIVE || state == ADDR_PREFERRED) { + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n"); + /* hack to make address "final" */ + if (state == ADDR_TENTATIVE) { + uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; + } + } + } +} + +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(udp_server_process, ev, data) +{ + uip_ipaddr_t ipaddr; + struct uip_ds6_addr *root_if; + + PROCESS_BEGIN(); + + PROCESS_PAUSE(); + + SENSORS_ACTIVATE(button_sensor); + + leds_init(); + PRINTF("UDP server started\n"); + + +#if UIP_CONF_ROUTER +/* The choice of server address determines its 6LoPAN header compression. + * Obviously the choice made here must also be selected in udp-client.c. + * + * For correct Wireshark decoding using a sniffer, add the /64 prefix to the 6LowPAN protocol preferences, + * e.g. set Context 0 to aaaa::. At present Wireshark copies Context/128 and then overwrites it. + * (Setting Context 0 to aaaa::1111:2222:3333:4444 will report a 16 bit compressed address of aaaa::1111:22ff:fe33:xxxx) + * Note Wireshark's IPCMV6 checksum verification depends on the correct uncompressed addresses. + */ + +#if 0 +/* Mode 1 - 64 bits inline */ + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 1); +#elif 1 +/* Mode 2 - 16 bits inline */ + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0x00ff, 0xfe00, 1); +#else +/* Mode 3 - derived from link local (MAC) address */ + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); +#endif + + uip_ds6_addr_add(&ipaddr, 0, ADDR_MANUAL); + root_if = uip_ds6_addr_lookup(&ipaddr); + if(root_if != NULL) { + rpl_dag_t *dag; + dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr); + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + rpl_set_prefix(dag, &ipaddr, 64); + PRINTF("created a new RPL dag\n"); + } else { + PRINTF("failed to create a new RPL DAG\n"); + } +#endif /* UIP_CONF_ROUTER */ + + print_local_addresses(); + + /* The data sink runs with a 100% duty cycle in order to ensure high + packet reception rates. */ + //NETSTACK_MAC.off(1); + + server_conn = udp_new(NULL, UIP_HTONS(UDP_CLIENT_PORT), NULL); + if(server_conn == NULL) { + PRINTF("No UDP connection available, exiting the process!\n"); + PROCESS_EXIT(); + } + udp_bind(server_conn, UIP_HTONS(UDP_SERVER_PORT)); + + PRINTF("Created a server connection with remote address "); + PRINT6ADDR(&server_conn->ripaddr); + PRINTF(" local/remote port %u/%u\n", UIP_HTONS(server_conn->lport), + UIP_HTONS(server_conn->rport)); + + while(1) { + PROCESS_YIELD(); + if(ev == tcpip_event) { + tcpip_handler(); + } else if (ev == sensors_event && data == &button_sensor) { + PRINTF("Initiaing global repair\n"); + rpl_repair_root(RPL_DEFAULT_INSTANCE); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/avr-rss2/ipv6/sensd_client/Makefile b/examples/avr-rss2/ipv6/sensd_client/Makefile new file mode 100644 index 000000000..f1b0d7d48 --- /dev/null +++ b/examples/avr-rss2/ipv6/sensd_client/Makefile @@ -0,0 +1,12 @@ + +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" + +all: sensd_client server +CONTIKI=../../../.. + +ifdef PERIOD +CFLAGS+=-DPERIOD=$(PERIOD) +endif + +CONTIKI_WITH_IPV6 = 1 +include $(CONTIKI)/Makefile.include diff --git a/examples/avr-rss2/ipv6/sensd_client/README.md b/examples/avr-rss2/ipv6/sensd_client/README.md new file mode 100644 index 000000000..17beb02f3 --- /dev/null +++ b/examples/avr-rss2/ipv6/sensd_client/README.md @@ -0,0 +1,222 @@ +Contiki client for sensd +======================== + +Sensd README describes the concept. sensd code is on github. + + +sensd - A WSN Internet GW, hub, agent, proxy & cloud +==================================================== + +Authors +-------- +Robert Olsson +Jens Laas + +Contributors +------------ + +Abstract +-------- +We've outlined, designed and implemented and very simple concept for WSN +data sharing, including data collection, storage and retrieval using +standard text tools. The concept restricts Internet access to WSN +motes and acts agent not to expose motes directly for robustness and +security reasons. Low level, physical or link WSN protocol can be used. +including 6lowpan, RIME etc and any type of Radio Duty Cycling (RDC). +sensd works on the application layer. A TCP connection initiates an +implicit "subscribe". The M2P model is currently supported. + +Key concepts +------------ + +* Agent. sensd works as an agent and does not allow direct Internet + access to motes. Recall motes are constrained in most aspects and + can not support many connections, has weak security etc. + +* Hub. Share the data from the root or sink node over TCP. In effect sensor + data can be sent over Internet to be shared over among TCP active listeners. + The TCP connection initiates an implicit "subscribe". + +* Proxy. The support proxy functions over ipv4 and well as ipv6. Sensd can + forward to a proxy on a public IP. The typical case is when GW is behind + a NAT. + +* WSN RP "rendez-vous point". A concepts where data from various WSN nets + are merged. This models a "cloud service" functionality for WSN networks. + sensd can be used both to forward data to RP. It can also work as the RP. + RP receiving WSN data and allowing multiple TCP listeners. + +* All programs are written C, script in Java and bash. Designed for small + footprint and with minimal dependencies. sensd runs on Raspberry Pi and + Openwrt. + +* This work introduces a simple tag format for sensor data. The overall + idea is that data tagging is an "agreement" between producers and consumer. + Tags are simple are description of the data. Example T=25.2. where T= + is the tag 25.2 the value. Most likely this a temperature. But we + can't be sure since we don't know since this is an agreement between + the producer and the consumer. Tags are also used for identification. + Example tags, E64= Where globally unique ID can used. Another more + relaxed example is TXT= a user description. See docs. + +* Geotagging and timestamping is supported via tags. + +* Ecosystem support. There are telphone apps to for data monitoring and + and plotting. Android app can act as WSN-agent and forward to proxy/RP. + +* The concept also includes a mapping to URI (Unified Resource Identifier) + to form a WSN caching server similar to CoAP using http-proxy. + +* Copyright. Open-Source via GPL. Projecet used github.com + + +Introduction +------------ + +This is collection of software to implement data monitoring and data collection +from WSN Wireless Sensor Networks. The goal is to have a very simple, +straight-forward and robust framework. + +The scenario: One or several motes is connected to USB or serial port to gather +received information from connected WSN motes. Data can be visualized in +several ways. + +* Sensor data report can be transmitted and propagated throughout the + Internet. sensd acts as server and sends incoming report to active + listeners. + +* Data is kept in ASCII with tagging and ID information. Data is conveniently + handled, copied and viewed with standard text utilities of your OS. + +* Last mote report is cached into the file system suitable for URI use. The + Format is SID/TAG. Typical tags are EUI64 and unique serial numbers. The + different TAGS are left for mote user to define. Although the TAGS used in + our example setup are included in this draft for example purposes. + + +Both formats can easily be stored or linked directly in web tree to form a +URI to format WSN logging/datafile or caching service. + +A daemon that reads WSN mote reports from USB/serial and stores data in a ASCII +data file. Default is located at _/var/log/sensors.dat_ + +Addtional components +-------------------- + +* seltag [More info] (https://github.com/herjulf/sensd/blob/master/seltag/README.md) + +* js A set of Java-scripts can plot, print and visualize sensor data from + sensd directly in your web-browser. + +* documentation and sample files. [More info] (https://github.com/herjulf/sensd/blob/master/seltag/README.md) + +* Read Sensors Android app. [Source Code] (https://github.com/herjulf/Read-Sensors) + + +Datafile logging +---------------- + +Below is and example of the anatomy of a sensors.dat file we are currently using in our WSN +data collection networks. + + 2012-05-22 14:07:46 UT=1337688466 ID=283c0cdd030000d7 PS=0 T=30.56 T_MCU=34.6 V_MCU=3.08 UP=2C15C V_IN=4.66 + + 2012-05-22 14:11:41 UT=1337688701 ID=28a9d5dc030000af PS=0 T=36.00 V_MCU=2.92 UP=12C8A0 RH=42.0 V_IN=4.13 V_A1=3.43 [ADDR=0.175 SEQ=33 RSSI=21 LQI=255 DRP=1.00] + +Each line is a mote report. They start with date and time and are followed by a set of +tags. The tags is different for different motes. In other words they can +send different data. Essential is the ID which should be unique for each mote. + +The information with brackets is information generated by the receiving mote +and is not a part the motes data. Typically RSSI (Receiver Signal Strength +Indicator) and LQI (Link Quality Indicator) + + +Internet sensor data +-------------------- + +Start sensd with the `-report` option. This enables reports to be transmitted +over IP to remote listeners. Default TCP port 1234. + +Server side example: + + sensd -report -p 1234 -D /dev/ttyUSB0 + +Client side. Example using netcat: + + nc server-ip 1234 + +URI format +---------- + +URI (Unified Resource Identifier) displays the node ID and the tags in a file tree. +It is easy to export this into a web tree to form a URI similar to a CoAP gateway. + +Example: In our case we have a unique sensor ID followed by the different data +fields represented by "tags". + + /tmp/WSN1-GW1/281a98d20200004a: + DRP ID LQI PS RH RSSI SEQ T V_IN V_MCU ADDR + + /tmp/WSN1-GW1/28be51ce02000031: + DRP ID LQI PS RH RSSI SEQ T UP V_IN V_MCU ADDR + +Read Temp from a sensor: + + cat /tmp/WSN1-GW1/281a98d20200004a/T + 19.44 + +And it's very easy to link this tree into a web-server. + +GPS support +----------- + +Positioning support has been added via GPS device connected to serial +or USB port. Tags added when enabled GWGPS_LON & GWGPS_LAT. +GPS code from. https://github.com/herjulf/gps_simple + +Getting the source and building +------------------------------- + +Code is stored in github. Typically procedure below is the very straight- +forward unix way: + + git clone http://github.com/herjulf/sensd + cd sensd + make + +Put your binaries after your preference: + +Pre-built binary versions +-------------------------- + +For x86: +Sensd and friends are available in Bifrost/Linux packages. Those packages are +statically linked and can be used on most x86 Linuxes. 32-bit compiled. + +http://ftp.sunet.se/pub/Linux/distributions/bifrost/download/opt/opt-sensd-2.3-1.tar.gz + + +Use +--- + +The WSN data logging and caching concept is in actual use with Contiki, RIME +broadcast application. + +Tips +---- + +One can use netcat to listen to reports: + +Example: + + nc radio-sensors.com 1235 + +To save in file use nohup: + + nohup nc radio-sensors.com 1235 > /var/log/sensors.dat + +As sensd used TCP and ASCII encoding. tetlnet and web-browsers can be used +as well. + + diff --git a/examples/avr-rss2/ipv6/sensd_client/project-conf.h b/examples/avr-rss2/ipv6/sensd_client/project-conf.h new file mode 100644 index 000000000..b004c6335 --- /dev/null +++ b/examples/avr-rss2/ipv6/sensd_client/project-conf.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015, RAdio Sensors AB, Uppsala Sweden + * 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 + * Project specific configuration defines for example + * + * \author + * Robert Olsson + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define NETSTACK_CONF_RDC nullrdc_driver +#define NETSTACK_CONF_MAC nullmac_driver + +//#define NETSTACK_CONF_MAC csma_driver +//#define NETSTACK_CONF_RDC contikimac_driver +//#define NETSTACK_CONF_FRAMER framer_802154 +//#define NETSTACK_CONF_RADIO rf230_driver + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/avr-rss2/ipv6/sensd_client/sensd_client.c b/examples/avr-rss2/ipv6/sensd_client/sensd_client.c new file mode 100644 index 000000000..df6494031 --- /dev/null +++ b/examples/avr-rss2/ipv6/sensd_client/sensd_client.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2015, Copyright Robert Olsson / Radio Sensors AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the 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. + * + * + * Author : Robert Olsson robert@radio-sensors.com + * Created : 2015-12-28 + */ + +/** + * \file + * A simple application reporting sensor data. Can be sensd + */ + +#include +#include "contiki-net.h" +#include "leds.h" +#include "dev/leds.h" +#include "dev/battery-sensor.h" +#include "dev/temp-sensor.h" +#include "dev/temp_mcu-sensor.h" +#include "dev/light-sensor.h" +#include "dev/pulse-sensor.h" +#ifdef CO2 +#include "dev/co2_sa_kxx-sensor.h" +#endif + +#ifndef PERIOD +#define PERIOD 10 +#endif + +#define REPORT_INTERVAL (PERIOD * CLOCK_SECOND) + +#define DEBUG DEBUG_PRINT +#include "uip-debug.h" + +#define PORT 1234 +#define MAX_PAYLOAD_LEN 80 + +static struct psock ps; +static uint8_t out_buf[MAX_PAYLOAD_LEN]; +static char in_buffer[MAX_PAYLOAD_LEN]; +static int i; +static int send_now; +static clock_time_t report_interval = REPORT_INTERVAL; +static uint8_t state; +static uip_ipaddr_t addr; +static struct timer t, t1; +static struct etimer et, et1; + +PROCESS(sensd_client_process, "sensd TCP client process"); +PROCESS(report_timer_process, "report pacemaker"); +AUTOSTART_PROCESSES +(&sensd_client_process,&report_timer_process); + +static int +do_report(void) +{ + static int seq_id; + int len = 0; + + seq_id++; + len += snprintf((char *) &out_buf[len], sizeof(out_buf), "&: "); + len += snprintf((char *) &out_buf[len], sizeof(out_buf), "TXT=ERICSON-6LOWPAN "); + len += snprintf((char *) &out_buf[len], sizeof(out_buf), "TARGET=avr-rss2 "); + len += snprintf((char *) &out_buf[len], sizeof(out_buf), "V_MCU=%-d ", battery_sensor.value(0)); + len += snprintf((char *) &out_buf[len], sizeof(out_buf), "T_MCU=%-d ", temp_mcu_sensor.value(0)); + len += snprintf((char *) &out_buf[len], sizeof(out_buf), "LIGHT=%-d ", light_sensor.value(0)); +#ifdef CO2 + len += snprintf((char *) &out_buf[len], sizeof(out_buf), "CO2=%-d ", co2_sa_kxx_sensor.value(CO2_SA_KXX_CO2)); +#endif + len += snprintf((char *) &out_buf[len], sizeof(out_buf), "\n\r"); + + return len; +} + +static void +print_local_addresses(void) +{ + PRINTF("Server IPv6 addresses:\n\r"); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && + (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n\r"); + } + } +} + +static void +set_global_address(void) +{ + uip_ipaddr_t ipaddr; + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); +} + +static int handle_connection(struct psock *p, long ts) { + PSOCK_BEGIN(p); + if(send_now) { + do_report(); + leds_on(LEDS_YELLOW); + PSOCK_SEND(p, (const uint8_t *) out_buf, strlen((const char *) out_buf)); + send_now = 0; + } + PSOCK_END(p); +} + +PROCESS_THREAD(report_timer_process, ev, data) { + PROCESS_BEGIN(); + while(1) { + timer_set(&t1, report_interval); + etimer_set(&et1, timer_remaining(&t1)); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et1)); + send_now = 1; + leds_on(LEDS_RED); + } + PROCESS_END(); +} + +PROCESS_THREAD(sensd_client_process, ev, data) { + PROCESS_BEGIN(); + + set_global_address(); + print_local_addresses(); + + SENSORS_ACTIVATE(temp_sensor); + SENSORS_ACTIVATE(battery_sensor); + SENSORS_ACTIVATE(temp_mcu_sensor); + SENSORS_ACTIVATE(light_sensor); + SENSORS_ACTIVATE(pulse_sensor); +#ifdef CO2 + SENSORS_ACTIVATE(co2_sa_kxx_sensor); +#endif + leds_init(); + leds_on(LEDS_RED); + leds_on(LEDS_YELLOW); + + printf("Starting TCP client on port=%d\n", PORT); + + /* Set server address. typically sensd */ + //uip_ip6addr(&addr, 0xfe80, 0, 0, 0, 0xfec2, 0x3d00, 1, 0x63ae); + //uip_ip6addr(&addr, 0x0000, 0, 0, 0, 0, 0xffff, 0xc0a8, 0x0201); + //uip_ip6addr(&addr, 0x0000, 0, 0, 0, 0, 0xffff, 0xc0a8, 0x0255); + uip_ip6addr(&addr, 0x0000, 0, 0, 0, 0, 0xffff, 0xc010, 0x7dea); //192.16.125.234 + + random_init(50); + + while(1) { + + /* Delay connection attempts */ + timer_set(&t, 2*CLOCK_SECOND); + etimer_set(&et, timer_remaining(&t)); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + /* Time out teh actual connection attempt */ + timer_set(&t, 10*CLOCK_SECOND); + printf("Connecting"); + tcp_connect(&addr, UIP_HTONS(PORT), NULL); + PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event); + + if(uip_aborted() || uip_timedout() || uip_closed()) { + printf(" Failed\n"); + } else if(uip_connected()) { + printf(" Success\n"); + PSOCK_INIT(&ps, (uint8_t *)in_buffer, sizeof(in_buffer)); + do { + handle_connection(&ps, clock_seconds()); + PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event); + } while(!(uip_closed() || uip_aborted() || uip_timedout())); + printf("Disconnected\n"); + } + } + PROCESS_END(); +} diff --git a/examples/avr-rss2/ipv6/sensd_client/server.c b/examples/avr-rss2/ipv6/sensd_client/server.c new file mode 100644 index 000000000..c2dea4514 --- /dev/null +++ b/examples/avr-rss2/ipv6/sensd_client/server.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2015, Copyright Robert Olsson / Radio Sensors AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the 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. + * + * + * Author : Robert Olsson robert@radio-sensors.com + * Created : 2015-12-28 + */ + +/** + * \file + * A simple TCP server for client app. + */ + +#include +#include "contiki-net.h" +#include "leds.h" + +#define DEBUG DEBUG_PRINT +#include "uip-debug.h" + +#define PORT 1236 + +static struct psock ps; +static uint8_t buf[120]; +static int i; +static uint8_t state; + +static void +print_local_addresses(void) +{ + PRINTF("Server IPv6 addresses:\n\r"); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && + (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n\r"); + } + } +} + +static void +set_global_address(void) +{ + uip_ipaddr_t ipaddr; + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); +} + +static +PT_THREAD(handle_connection(struct psock *p)) +{ + PSOCK_BEGIN(p); + //PSOCK_SEND_STR(p, "Type something!\n"); + leds_on(LEDS_RED); + PSOCK_READTO(p, '\n'); + printf("RX=%s", buf); + //PSOCK_SEND_STR(p, "Got: "); + //PSOCK_SEND(p, buf, PSOCK_DATALEN(p)); + //PSOCK_SEND_STR(p, "EOL\r\n"); + //PSOCK_CLOSE(p); + PSOCK_END(p); +} + +PROCESS(server_process, "Server"); +AUTOSTART_PROCESSES(&server_process); + +PROCESS_THREAD(server_process, ev, data) +{ + PROCESS_BEGIN(); + + set_global_address(); + leds_init(); + print_local_addresses(); + printf("Starting TCP server on port=%d\n", PORT); + tcp_listen(UIP_HTONS(PORT)); + + while(1) { + PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event); + + if(uip_aborted() ) + printf("TCP aborted\n"); + if(uip_timedout() ) + printf("TCP timeoutn\n"); + if(uip_closed() ) + printf("TCP closed\n"); + + if(uip_connected()) { + printf("TCP Connected\n\r"); + PSOCK_INIT(&ps, buf, sizeof(buf)); + + while(!(uip_aborted() || uip_closed() || uip_timedout())) { + PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event); + handle_connection(&ps); + } + } + } + PROCESS_END(); +} + diff --git a/examples/cc2530dk/border-router/README.md b/examples/cc2530dk/border-router/README.md index ebb9545a2..8c5025c4d 100644 --- a/examples/cc2530dk/border-router/README.md +++ b/examples/cc2530dk/border-router/README.md @@ -15,6 +15,6 @@ The node will use this address to obtain the network prefix For example: - sudo ./tunslip6 aaaa::1/64 + sudo ./tunslip6 fd00::1/64 -This will use aaaa:: / 64 as the prefix for the 15.4 network. +This will use fd00:: / 64 as the prefix for the 15.4 network. diff --git a/examples/cc2530dk/udp-ipv6/client.c b/examples/cc2530dk/udp-ipv6/client.c index 77d50b0df..065c07089 100644 --- a/examples/cc2530dk/udp-ipv6/client.c +++ b/examples/cc2530dk/udp-ipv6/client.c @@ -130,7 +130,7 @@ PROCESS_THREAD(udp_client_process, ev, data) PRINTF(" local/remote port %u/%u\n", UIP_HTONS(l_conn->lport), UIP_HTONS(l_conn->rport)); - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0x0215, 0x2000, 0x0002, 0x2145); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0x0215, 0x2000, 0x0002, 0x2145); g_conn = udp_new(&ipaddr, UIP_HTONS(3000), NULL); if(!g_conn) { PRINTF("udp_new g_conn error.\n"); diff --git a/examples/cc2530dk/udp-ipv6/ping6.c b/examples/cc2530dk/udp-ipv6/ping6.c index e19a36895..3f6fce89b 100644 --- a/examples/cc2530dk/udp-ipv6/ping6.c +++ b/examples/cc2530dk/udp-ipv6/ping6.c @@ -105,7 +105,7 @@ PROCESS_THREAD(ping6_process, ev, data) PRINTF("ping6 running.\n"); PRINTF("Button 1: 5 pings 16 byte payload.\n"); - uip_ip6addr(&dest_addr, 0xaaaa, 0, 0, 0, 0x0215, 0x2000, 0x0002, 0x2145); + uip_ip6addr(&dest_addr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0x0215, 0x2000, 0x0002, 0x2145); count = 0; icmp6_new(NULL); diff --git a/examples/cc2530dk/udp-ipv6/server.c b/examples/cc2530dk/udp-ipv6/server.c index 0b61194aa..ab381ccf5 100644 --- a/examples/cc2530dk/udp-ipv6/server.c +++ b/examples/cc2530dk/udp-ipv6/server.c @@ -126,7 +126,7 @@ create_dag() { rpl_dag_t *dag; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); @@ -135,7 +135,7 @@ create_dag() dag = rpl_set_root(RPL_DEFAULT_INSTANCE, &uip_ds6_get_global(ADDR_PREFERRED)->ipaddr); if(dag != NULL) { - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &ipaddr, 64); PRINTF("Created a new RPL dag with ID: "); PRINT6ADDR(&dag->dag_id); diff --git a/examples/cc2538-common/mqtt-demo/project-conf.h b/examples/cc2538-common/mqtt-demo/project-conf.h index 0aaef655d..bcdabff20 100644 --- a/examples/cc2538-common/mqtt-demo/project-conf.h +++ b/examples/cc2538-common/mqtt-demo/project-conf.h @@ -45,7 +45,7 @@ #define MQTT_DEMO_PUBLISH_TRIGGER &button_right_sensor /* If undefined, the demo will attempt to connect to IBM's quickstart */ -#define MQTT_DEMO_BROKER_IP_ADDR "aaaa::1" +#define MQTT_DEMO_BROKER_IP_ADDR "fd00::1" /*---------------------------------------------------------------------------*/ #endif /* PROJECT_CONF_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/examples/cc26xx/cc26xx-demo.c b/examples/cc26xx/cc26xx-demo.c index 544ae4dd8..50d2190d3 100644 --- a/examples/cc26xx/cc26xx-demo.c +++ b/examples/cc26xx/cc26xx-demo.c @@ -44,6 +44,7 @@ * This example will work for the following boards: * - srf06-cc26xx: SmartRF06EB + CC26XX EM * - sensortag-cc26xx: CC26XX sensortag + * - The CC2650 LaunchPad * * By default, the example will build for the srf06-cc26xx board. To switch * between platforms: @@ -114,6 +115,10 @@ #define CC26XX_DEMO_SENSOR_3 CC26XX_DEMO_SENSOR_NONE #define CC26XX_DEMO_SENSOR_4 CC26XX_DEMO_SENSOR_NONE #define CC26XX_DEMO_SENSOR_5 &reed_relay_sensor +#elif BOARD_LAUNCHPAD +#define CC26XX_DEMO_SENSOR_3 CC26XX_DEMO_SENSOR_NONE +#define CC26XX_DEMO_SENSOR_4 CC26XX_DEMO_SENSOR_NONE +#define CC26XX_DEMO_SENSOR_5 CC26XX_DEMO_SENSOR_NONE #else #define CC26XX_DEMO_SENSOR_3 &button_up_sensor #define CC26XX_DEMO_SENSOR_4 &button_down_sensor @@ -332,6 +337,15 @@ get_sync_sensor_readings(void) value = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT); printf("Bat: Volt=%d mV\n", (value * 125) >> 5); +#if BOARD_SMARTRF06EB + SENSORS_ACTIVATE(als_sensor); + + value = als_sensor.value(0); + printf("ALS: %d raw\n", value); + + SENSORS_DEACTIVATE(als_sensor); +#endif + return; } /*---------------------------------------------------------------------------*/ @@ -423,7 +437,7 @@ PROCESS_THREAD(cc26xx_demo_process, ev, data) get_tmp_reading(); } else if(ev == sensors_event && data == &mpu_9250_sensor) { get_mpu_reading(); -#else +#elif BOARD_SMARTRF06EB printf("Sel: Pin %d, press duration %d clock ticks\n", button_select_sensor.value(BUTTON_SENSOR_VALUE_STATE), button_select_sensor.value(BUTTON_SENSOR_VALUE_DURATION)); diff --git a/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c index 1eaf35648..a363c31d5 100644 --- a/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c +++ b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c @@ -175,7 +175,7 @@ static void save_config() { /* Dump current running config to flash */ -#if BOARD_SENSORTAG +#if BOARD_SENSORTAG || BOARD_LAUNCHPAD int rv; cc26xx_web_demo_sensor_reading_t *reading = NULL; @@ -218,7 +218,7 @@ save_config() static void load_config() { -#if BOARD_SENSORTAG +#if BOARD_SENSORTAG || BOARD_LAUNCHPAD /* Read from flash into a temp buffer */ cc26xx_web_demo_config_t tmp_cfg; cc26xx_web_demo_sensor_reading_t *reading = NULL; diff --git a/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h index 026461f32..14bf3150c 100644 --- a/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h +++ b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h @@ -100,6 +100,8 @@ #if BOARD_SENSORTAG /* Force an MQTT publish on sensor event */ #define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER &reed_relay_sensor +#elif BOARD_LAUNCHPAD +#define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER &button_left_sensor #else #define CC26XX_WEB_DEMO_MQTT_PUBLISH_TRIGGER &button_down_sensor #endif diff --git a/examples/cc26xx/cc26xx-web-demo/coap-server.c b/examples/cc26xx/cc26xx-web-demo/coap-server.c index 9b4155d00..518065f6e 100644 --- a/examples/cc26xx/cc26xx-web-demo/coap-server.c +++ b/examples/cc26xx/cc26xx-web-demo/coap-server.c @@ -63,6 +63,9 @@ extern resource_t res_parent_ip; extern resource_t res_ble_advd; #endif +extern resource_t res_toggle_red; +extern resource_t res_toggle_green; + /* Board-specific resources */ #if BOARD_SENSORTAG extern resource_t res_bmp280_temp; @@ -78,11 +81,7 @@ extern resource_t res_mpu_acc_z; extern resource_t res_mpu_gyro_x; extern resource_t res_mpu_gyro_y; extern resource_t res_mpu_gyro_z; -extern resource_t res_toggle_red; -extern resource_t res_toggle_green; #else -extern resource_t res_toggle_red; -extern resource_t res_toggle_green; extern resource_t res_toggle_orange; extern resource_t res_toggle_yellow; #endif @@ -96,6 +95,11 @@ const char *coap_server_supported_msg = "Supported:" static void start_board_resources(void) { + + rest_activate_resource(&res_toggle_green, "lt/g"); + rest_activate_resource(&res_toggle_red, "lt/r"); + rest_activate_resource(&res_leds, "lt"); + #if BOARD_SENSORTAG rest_activate_resource(&res_bmp280_temp, "sen/bar/temp"); rest_activate_resource(&res_bmp280_press, "sen/bar/pres"); @@ -110,14 +114,8 @@ start_board_resources(void) rest_activate_resource(&res_mpu_gyro_x, "sen/mpu/gyro/x"); rest_activate_resource(&res_mpu_gyro_y, "sen/mpu/gyro/y"); rest_activate_resource(&res_mpu_gyro_z, "sen/mpu/gyro/z"); - rest_activate_resource(&res_leds, "lt"); - rest_activate_resource(&res_toggle_green, "lt/g"); - rest_activate_resource(&res_toggle_red, "lt/r"); #elif BOARD_SMARTRF06EB - rest_activate_resource(&res_leds, "lt"); - rest_activate_resource(&res_toggle_red, "lt/r"); rest_activate_resource(&res_toggle_yellow, "lt/y"); - rest_activate_resource(&res_toggle_green, "lt/g"); rest_activate_resource(&res_toggle_orange, "lt/o"); #endif } diff --git a/examples/cc26xx/cc26xx-web-demo/resources/res-leds.c b/examples/cc26xx/cc26xx-web-demo/resources/res-leds.c index 2a86ad25b..85ce353b5 100644 --- a/examples/cc26xx/cc26xx-web-demo/resources/res-leds.c +++ b/examples/cc26xx/cc26xx-web-demo/resources/res-leds.c @@ -94,7 +94,7 @@ res_post_put_handler(void *request, void *response, uint8_t *buffer, * A simple actuator example, depending on the color query parameter and post * variable mode, corresponding led is activated or deactivated */ -#if BOARD_SENSORTAG +#if BOARD_SENSORTAG || BOARD_LAUNCHPAD #define RESOURCE_PARAMS "r|g" #elif BOARD_SMARTRF06EB #define RESOURCE_PARAMS "r|g|y|o" diff --git a/examples/cfs-coffee/Makefile b/examples/cfs-coffee/Makefile new file mode 100644 index 000000000..0e1fe1b13 --- /dev/null +++ b/examples/cfs-coffee/Makefile @@ -0,0 +1,12 @@ +DEFINES+=PROJECT_CONF_H=\"project-conf.h\" +CONTIKI = ../.. + +all: test-cfs test-coffee example-coffee + +CONTIKI_WITH_RIME = 1 + +ifeq ($(TARGET),avr-raven) + COFFEE_FILES = 4 +endif + +include $(CONTIKI)/Makefile.include diff --git a/examples/cfs-coffee/README.md b/examples/cfs-coffee/README.md new file mode 100644 index 000000000..991e9583b --- /dev/null +++ b/examples/cfs-coffee/README.md @@ -0,0 +1,29 @@ +Contiki File System (CFS) and Coffee Examples +============================================= + +Coffee is a very simple, relatively small and easy to use file system that you +are most likely going to be very familiar with if you have done any C file +access in the past. The notion is the same as on a normal PC: you open a file, +read and write to it and close it. Contiki will take care of the underlying +flash memory, giving you more time to focus on the real issues. + +Coffee is a full implementation of the CFS API. + +An extended explanation on CFS and Coffee internals and how they work can be +found at the [CFS](https://github.com/contiki-os/contiki/wiki/File-systems) and +[Coffee](https://github.com/contiki-os/contiki/wiki/Coffee-filesystem-example) +wiki pages. + +Supported Hardware (tested or known to work) +-------------------------------------------- +* sky +* z1 +* wismote +* avr-raven +* cc2538dk +* openmote-cc2538 +* zoul + +The examples are known to build for the 'avr-raven' platform. However, +some of them currently fail at runtime due to file system overflow. +Tweaking the file sizes in the examples is necessary. diff --git a/examples/sky/example-coffee.c b/examples/cfs-coffee/example-coffee.c similarity index 89% rename from examples/sky/example-coffee.c rename to examples/cfs-coffee/example-coffee.c index ee77849e4..7adc8d62c 100644 --- a/examples/sky/example-coffee.c +++ b/examples/cfs-coffee/example-coffee.c @@ -28,31 +28,31 @@ * * This file is part of the Contiki operating system. */ - +/*---------------------------------------------------------------------------*/ /** * \file * Example on how to use CFS/Coffee. * \author * Nicolas Tsiftes */ - +/*---------------------------------------------------------------------------*/ #include - +#include #include "contiki.h" #include "cfs/cfs.h" #include "cfs/cfs-coffee.h" - +/*---------------------------------------------------------------------------*/ PROCESS(example_coffee_process, "Coffee example"); AUTOSTART_PROCESSES(&example_coffee_process); - +/*---------------------------------------------------------------------------*/ #define FILENAME "test" -/* Formatting is needed if the storage device is in an unknown state; +/* Formatting is needed if the storage device is in an unknown state; e.g., when using Coffee on the storage device for the first time. */ #ifndef NEED_FORMATTING #define NEED_FORMATTING 0 #endif - +/*---------------------------------------------------------------------------*/ static int file_test(const char *filename, char *msg) { @@ -65,12 +65,12 @@ file_test(const char *filename, char *msg) } record; /* - * Coffee determines the file length by finding the last non-zero byte - * of the file. This I/O semantic requires that each record should end - * with a non-zero, if we are writing multiple records and closing the + * Coffee determines the file length by finding the last non-zero byte + * of the file. This I/O semantic requires that each record should end + * with a non-zero, if we are writing multiple records and closing the * file descriptor in between. * - * In this example, in which the file_test function can be called + * In this example, in which the file_test function can be called * multiple times, we ensure that the sequence counter starts at 1. */ @@ -84,7 +84,7 @@ file_test(const char *filename, char *msg) record.message[sizeof(record.message) - 1] = '\0'; record.sequence = sequence; - /* Obtain a file descriptor for the file, capable of handling both + /* Obtain a file descriptor for the file, capable of handling both reads and writes. */ fd = cfs_open(FILENAME, CFS_WRITE | CFS_APPEND | CFS_READ); if(fd < 0) { @@ -103,7 +103,7 @@ file_test(const char *filename, char *msg) printf("Wrote message \"%s\", sequence %u\n", record.message, record.sequence); - /* To read back the message, we need to move the file pointer to the + /* To read back the message, we need to move the file pointer to the beginning of the file. */ if(cfs_seek(fd, 0, CFS_SEEK_SET) != 0) { printf("seek failed\n"); @@ -133,7 +133,7 @@ file_test(const char *filename, char *msg) return 1; } - +/*---------------------------------------------------------------------------*/ static int dir_test(void) { @@ -156,7 +156,7 @@ dir_test(void) return 1; } - +/*---------------------------------------------------------------------------*/ PROCESS_THREAD(example_coffee_process, ev, data) { PROCESS_BEGIN(); diff --git a/examples/cfs-coffee/project-conf.h b/examples/cfs-coffee/project-conf.h new file mode 100644 index 000000000..4dd98edcb --- /dev/null +++ b/examples/cfs-coffee/project-conf.h @@ -0,0 +1,40 @@ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ +/*---------------------------------------------------------------------------*/ +#if CONTIKI_TARGET_CC2538DK || CONTIKI_TARGET_OPENMOTE_CC2538 || \ + CONTIKI_TARGET_ZOUL +#define COFFEE_CONF_SIZE (CC2538_DEV_FLASH_SIZE / 2) +#define COFFEE_CONF_MICRO_LOGS 1 +#define COFFEE_CONF_APPEND_ONLY 0 +#endif /* CONTIKI_TARGET_CC2538DK || CONTIKI_TARGET_ZOUL */ + +#endif /* PROJECT_CONF_H_ */ +/*---------------------------------------------------------------------------*/ diff --git a/examples/sky/test-cfs.c b/examples/cfs-coffee/test-cfs.c similarity index 94% rename from examples/sky/test-cfs.c rename to examples/cfs-coffee/test-cfs.c index 68c91e720..2d44b6696 100644 --- a/examples/sky/test-cfs.c +++ b/examples/cfs-coffee/test-cfs.c @@ -29,19 +29,18 @@ * This file is part of the Contiki operating system. * */ - +/*---------------------------------------------------------------------------*/ /** * \file * A quick program for testing the CFS xmem driver * \author * Adam Dunkels */ - +/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "cfs/cfs.h" - #include - +/*---------------------------------------------------------------------------*/ PROCESS(cfs_process, "Test CFS process"); AUTOSTART_PROCESSES(&cfs_process); /*---------------------------------------------------------------------------*/ @@ -55,6 +54,7 @@ PROCESS_THREAD(cfs_process, ev, data) uint16_t filesize = 65000; #define CHUNKSIZE 128 + cfs_remove("hej"); fd = cfs_open("hej", CFS_WRITE); if(fd < 0) { printf("could not open file for writing, aborting\n"); diff --git a/examples/sky/test-coffee.c b/examples/cfs-coffee/test-coffee.c similarity index 84% rename from examples/sky/test-coffee.c rename to examples/cfs-coffee/test-coffee.c index b4152b2a8..3fcc40cfd 100644 --- a/examples/sky/test-coffee.c +++ b/examples/cfs-coffee/test-coffee.c @@ -29,14 +29,14 @@ * This file is part of the Contiki operating system. * */ - +/*---------------------------------------------------------------------------*/ /** * \file * Basic test for CFS/Coffee. * \author * Nicolas Tsiftes */ - +/*---------------------------------------------------------------------------*/ #include "contiki.h" #include "cfs/cfs.h" #include "cfs/cfs-coffee.h" @@ -45,14 +45,12 @@ #include #include - +/*---------------------------------------------------------------------------*/ PROCESS(testcoffee_process, "Test CFS/Coffee process"); AUTOSTART_PROCESSES(&testcoffee_process); - -#define FAIL(x) error = (x); goto end; - +/*---------------------------------------------------------------------------*/ +#define TEST_FAIL(x) error = (x); goto end; #define FILE_SIZE 4096 - /*---------------------------------------------------------------------------*/ static int coffee_test_basic(void) @@ -62,8 +60,6 @@ coffee_test_basic(void) unsigned char buf[256]; int r; - cfs_remove("T1"); - wfd = rfd = afd = -1; for(r = 0; r < sizeof(buf); r++) { @@ -73,64 +69,64 @@ coffee_test_basic(void) /* Test 1: Open for writing. */ wfd = cfs_open("T1", CFS_WRITE); if(wfd < 0) { - FAIL(1); + TEST_FAIL(1); } /* Test 2 and 3: Write buffer. */ r = cfs_write(wfd, buf, sizeof(buf)); if(r < 0) { - FAIL(2); + TEST_FAIL(2); } else if(r < sizeof(buf)) { - FAIL(3); + TEST_FAIL(3); } /* Test 4: Deny reading. */ r = cfs_read(wfd, buf, sizeof(buf)); if(r >= 0) { - FAIL(4); + TEST_FAIL(4); } /* Test 5: Open for reading. */ rfd = cfs_open("T1", CFS_READ); if(rfd < 0) { - FAIL(5); + TEST_FAIL(5); } /* Test 6: Write to read-only file. */ r = cfs_write(rfd, buf, sizeof(buf)); if(r >= 0) { - FAIL(6); + TEST_FAIL(6); } /* Test 7 and 8: Read the buffer written in Test 2. */ memset(buf, 0, sizeof(buf)); r = cfs_read(rfd, buf, sizeof(buf)); if(r < 0) { - FAIL(7); + TEST_FAIL(7); } else if(r < sizeof(buf)) { printf("r=%d\n", r); - FAIL(8); + TEST_FAIL(8); } /* Test 9: Verify that the buffer is correct. */ for(r = 0; r < sizeof(buf); r++) { if(buf[r] != r) { printf("r=%d. buf[r]=%d\n", r, buf[r]); - FAIL(9); + TEST_FAIL(9); } } /* Test 10: Seek to beginning. */ if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) { - FAIL(10); + TEST_FAIL(10); } /* Test 11 and 12: Write to the log. */ r = cfs_write(wfd, buf, sizeof(buf)); if(r < 0) { - FAIL(11); + TEST_FAIL(11); } else if(r < sizeof(buf)) { - FAIL(12); + TEST_FAIL(12); } /* Test 13 and 14: Read the data from the log. */ @@ -138,15 +134,15 @@ coffee_test_basic(void) memset(buf, 0, sizeof(buf)); r = cfs_read(rfd, buf, sizeof(buf)); if(r < 0) { - FAIL(14); + TEST_FAIL(13); } else if(r < sizeof(buf)) { - FAIL(15); + TEST_FAIL(14); } /* Test 16: Verify that the data is correct. */ for(r = 0; r < sizeof(buf); r++) { if(buf[r] != r) { - FAIL(16); + TEST_FAIL(15); } } @@ -155,16 +151,16 @@ coffee_test_basic(void) buf[r] = sizeof(buf) - r - 1; } if(cfs_seek(wfd, 0, CFS_SEEK_SET) != 0) { - FAIL(17); + TEST_FAIL(16); } r = cfs_write(wfd, buf, sizeof(buf)); if(r < 0) { - FAIL(18); + TEST_FAIL(17); } else if(r < sizeof(buf)) { - FAIL(19); + TEST_FAIL(18); } if(cfs_seek(rfd, 0, CFS_SEEK_SET) != 0) { - FAIL(20); + TEST_FAIL(19); } /* Test 21 and 22: Read the reversed buffer. */ @@ -172,16 +168,16 @@ coffee_test_basic(void) memset(buf, 0, sizeof(buf)); r = cfs_read(rfd, buf, sizeof(buf)); if(r < 0) { - FAIL(21); + TEST_FAIL(20); } else if(r < sizeof(buf)) { printf("r = %d\n", r); - FAIL(22); + TEST_FAIL(21); } /* Test 23: Verify that the data is correct. */ for(r = 0; r < sizeof(buf); r++) { if(buf[r] != sizeof(buf) - r - 1) { - FAIL(23); + TEST_FAIL(22); } } @@ -189,6 +185,7 @@ coffee_test_basic(void) end: cfs_close(wfd); cfs_close(rfd); + cfs_remove("T1"); return error; } /*---------------------------------------------------------------------------*/ @@ -202,50 +199,49 @@ coffee_test_append(void) #define APPEND_BYTES 1000 #define BULK_SIZE 10 - cfs_remove("T2"); - /* Test 1 and 2: Append data to the same file many times. */ for(i = 0; i < APPEND_BYTES; i += BULK_SIZE) { - afd = cfs_open("T3", CFS_WRITE | CFS_APPEND); + afd = cfs_open("T2", CFS_WRITE | CFS_APPEND); if(afd < 0) { - FAIL(1); + TEST_FAIL(1); } for(j = 0; j < BULK_SIZE; j++) { buf[j] = 1 + ((i + j) & 0x7f); } if((r = cfs_write(afd, buf, BULK_SIZE)) != BULK_SIZE) { printf("r=%d\n", r); - FAIL(2); + TEST_FAIL(2); } cfs_close(afd); } - /* Test 3-6: Read back the data written previously and verify that it + /* Test 3-6: Read back the data written previously and verify that it is correct. */ - afd = cfs_open("T3", CFS_READ); + afd = cfs_open("T2", CFS_READ); if(afd < 0) { - FAIL(3); + TEST_FAIL(3); } total_read = 0; while((r = cfs_read(afd, buf2, sizeof(buf2))) > 0) { for(j = 0; j < r; j++) { if(buf2[j] != 1 + ((total_read + j) & 0x7f)) { - FAIL(4); + TEST_FAIL(4); } } total_read += r; } if(r < 0) { - FAIL(5); + TEST_FAIL(5); } if(total_read != APPEND_BYTES) { - FAIL(6); + TEST_FAIL(6); } cfs_close(afd); error = 0; end: cfs_close(afd); + cfs_remove("T2"); return error; } /*---------------------------------------------------------------------------*/ @@ -258,58 +254,60 @@ coffee_test_modify(void) int r, i; unsigned offset; - cfs_remove("T3"); wfd = -1; if(cfs_coffee_reserve("T3", FILE_SIZE) < 0) { - FAIL(1); + TEST_FAIL(1); } if(cfs_coffee_configure_log("T3", FILE_SIZE / 2, 11) < 0) { - FAIL(2); + TEST_FAIL(2); } /* Test 16: Test multiple writes at random offset. */ for(r = 0; r < 100; r++) { - wfd = cfs_open("T2", CFS_WRITE | CFS_READ); + wfd = cfs_open("T3", CFS_WRITE | CFS_READ); if(wfd < 0) { - FAIL(3); + TEST_FAIL(3); } offset = random_rand() % FILE_SIZE; - for(r = 0; r < sizeof(buf); r++) { - buf[r] = r; + for(i = 0; i < sizeof(buf); i++) { + buf[i] = i; } if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) { - FAIL(4); + TEST_FAIL(4); } if(cfs_write(wfd, buf, sizeof(buf)) != sizeof(buf)) { - FAIL(5); + TEST_FAIL(5); } if(cfs_seek(wfd, offset, CFS_SEEK_SET) != offset) { - FAIL(6); + TEST_FAIL(6); } memset(buf, 0, sizeof(buf)); if(cfs_read(wfd, buf, sizeof(buf)) != sizeof(buf)) { - FAIL(7); + TEST_FAIL(7); } for(i = 0; i < sizeof(buf); i++) { if(buf[i] != i) { printf("buf[%d] != %d\n", i, buf[i]); - FAIL(8); + TEST_FAIL(8); } } + + cfs_close(wfd); } error = 0; end: cfs_close(wfd); + cfs_remove("T3"); return error; } /*---------------------------------------------------------------------------*/ @@ -318,21 +316,17 @@ coffee_test_gc(void) { int i; - cfs_remove("alpha"); - cfs_remove("beta"); - - for (i = 0; i < 100; i++) { if (i & 1) { - if(cfs_coffee_reserve("alpha", random_rand() & 0xffff) < 0) { - return i; - } - cfs_remove("beta"); - } else { - if(cfs_coffee_reserve("beta", 93171) < 0) { + if(cfs_coffee_reserve("beta", random_rand() & 0xffff) < 0) { return i; } cfs_remove("alpha"); + } else { + if(cfs_coffee_reserve("alpha", 93171) < 0) { + return i; + } + cfs_remove("beta"); } } @@ -376,7 +370,7 @@ PROCESS_THREAD(testcoffee_process, ev, data) result = coffee_test_gc(); print_result("Garbage collection", result); - printf("Coffee test finished. Duration: %d seconds\n", + printf("Coffee test finished. Duration: %d seconds\n", (int)(clock_seconds() - start)); PROCESS_END(); diff --git a/examples/er-rest-example/Makefile b/examples/er-rest-example/Makefile index a20d814ee..817a83b9d 100644 --- a/examples/er-rest-example/Makefile +++ b/examples/er-rest-example/Makefile @@ -57,13 +57,13 @@ $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) connect-router: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64 + sudo $(CONTIKI)/tools/tunslip6 fd00::1/64 connect-router-cooja: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 -p 60001 aaaa::1/64 + sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 -p 60001 fd00::1/64 connect-router-native: $(CONTIKI)/examples/ipv6/native-border-router/border-router.native - sudo $(CONTIKI)/exmples/ipv6/native-border-router/border-router.native -a 127.0.0.1 -p 60001 aaaa::1/64 + sudo $(CONTIKI)/exmples/ipv6/native-border-router/border-router.native -a 127.0.0.1 -p 60001 fd00::1/64 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 diff --git a/examples/er-rest-example/README.md b/examples/er-rest-example/README.md index fe82ed9b5..25abd60e4 100644 --- a/examples/er-rest-example/README.md +++ b/examples/er-rest-example/README.md @@ -23,8 +23,8 @@ PRELIMINARIES #define NETSTACK_CONF_RDC nullrdc_driver - Alternatively, you can use the native-border-router together with the slip-radio. - For convenience, define the Cooja addresses in /etc/hosts - aaaa::0212:7401:0001:0101 cooja1 - aaaa::0212:7402:0002:0202 cooja2 + fd00::0212:7401:0001:0101 cooja1 + fd00::0212:7402:0002:0202 cooja2 ... - Get the Copper (Cu) CoAP user-agent from [https://addons.mozilla.org/en-US/firefox/addon/copper-270430](https://addons.mozilla.org/en-US/firefox/addon/copper-270430) @@ -82,11 +82,11 @@ TMOTES HOWTO 3. Start Copper and discover resources at: - coap://[aaaa::____:____:____:____]:5683/ + coap://[fd00::____:____:____:____]:5683/ ### Add a client: -1. Change the hard-coded server address in er-example-client.c to aaaa::____:____:____:____ +1. Change the hard-coded server address in er-example-client.c to fd00::____:____:____:____ 2. Connect a third Tmote Sky make TARGET=sky er-example-client.upload MOTE=3 diff --git a/examples/er-rest-example/project-conf.h b/examples/er-rest-example/project-conf.h index 53662619a..adcb75ee1 100644 --- a/examples/er-rest-example/project-conf.h +++ b/examples/er-rest-example/project-conf.h @@ -60,6 +60,9 @@ #undef NETSTACK_CONF_RDC #define NETSTACK_CONF_RDC nullrdc_driver +#undef RPL_CONF_MAX_DAG_PER_INSTANCE +#define RPL_CONF_MAX_DAG_PER_INSTANCE 1 + /* Disabling TCP on CoAP nodes. */ #undef UIP_CONF_TCP #define UIP_CONF_TCP 0 @@ -93,6 +96,13 @@ #undef COAP_PROXY_OPTION_PROCESSING #define COAP_PROXY_OPTION_PROCESSING 0 +/* Turn of DAO ACK to make code smaller */ +#undef RPL_CONF_WITH_DAO_ACK +#define RPL_CONF_WITH_DAO_ACK 0 + +#undef RPL_CONF_OF +#define RPL_CONF_OF rpl_of0 + /* Enable client-side support for COAP observe */ #define COAP_OBSERVE_CLIENT 1 #endif /* __PROJECT_ERBIUM_CONF_H__ */ diff --git a/examples/er-rest-example/resources/res-event.c b/examples/er-rest-example/resources/res-event.c index d20f0caa9..7524d2ad2 100644 --- a/examples/er-rest-example/resources/res-event.c +++ b/examples/er-rest-example/resources/res-event.c @@ -53,7 +53,7 @@ #endif static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); -static void res_event_handler(); +static void res_event_handler(void); /* * Example for an event resource. @@ -86,7 +86,7 @@ res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferr * It is called through .trigger(), usually from the server process. */ static void -res_event_handler() +res_event_handler(void) { /* Do the update triggered by the event here, e.g., sampling a sensor. */ ++event_counter; diff --git a/examples/galileo/Makefile b/examples/galileo/Makefile index 19a29f78a..0852fe085 100644 --- a/examples/galileo/Makefile +++ b/examples/galileo/Makefile @@ -1,18 +1,26 @@ TARGET=galileo -KNOWN_EXAMPLES = gpio-input gpio-output gpio-interrupt i2c-LSM9DS0 +KNOWN_EXAMPLES = gpio-input gpio-output gpio-interrupt i2c-LSM9DS0 i2c-callbacks print-imr prot-domain-switch-latency -ifneq ($(filter $(EXAMPLE),$(KNOWN_EXAMPLES)),) - CONTIKI_PROJECT = $(EXAMPLE) -else - CONTIKI_PROJECT = help +ifeq ($(filter $(EXAMPLE),$(KNOWN_EXAMPLES)),) + $(info Set the variable EXAMPLE to one of the following Galileo-specific examples:) + $(foreach EXAMPLE,$(KNOWN_EXAMPLES),$(info - $(EXAMPLE))) + $(error Unable to proceed) endif +ifeq ($(EXAMPLE),print-imr) + CFLAGS += -DDBG_IMRS +endif + +ifeq ($(EXAMPLE),prot-domain-switch-latency) +ifeq ($(SAMPLE_METADATA),1) +CFLAGS += -DSAMPLE_METADATA=1 +endif +endif + +CONTIKI_PROJECT = $(EXAMPLE) + all: $(CONTIKI_PROJECT) CONTIKI = ../.. include $(CONTIKI)/Makefile.include - -help: - @echo -e "\nSet the variable EXAMPLE to one of the following Galileo-specific examples:" - @for EXAMPLE in $(KNOWN_EXAMPLES); do echo $$EXAMPLE; done diff --git a/examples/galileo/README b/examples/galileo/README deleted file mode 100644 index 643a2e418..000000000 --- a/examples/galileo/README +++ /dev/null @@ -1,73 +0,0 @@ -Galileo Specific Examples -======================= - -This directory contains galileo-specific example applications to illustrate -how to use galileo APIs. - -In order to build a application, you should set the EXAMPLE environment -variable to the name of the application you want to build. For instance, if -you want to build gpio-output application, run the following command: -$ make TARGET=galileo EXAMPLE=gpio-output - -============ -= GPIO = -============ - -GPIO Output -=========== - -This application shows how to use the GPIO driver APIs to manipulate output -pins. This application sets the GPIO 4 pin as output pin and toggles its -state at every half second. - -For a visual effect, you should wire shield pin IO1 to a led in a protoboard. -Once the application is running, you should see a blinking LED. - -GPIO Input -========== - -This application shows how to use the GPIO driver APIs to manipulate input -pins. This application uses default galileo pinmux initialization and sets -the GPIO 5 (IO2) as output pin and GPIO 6 (IO3) as input. It toggles the -output pin state at every half second and checks the value on input pin. - -GPIO Interrupt -============== - -This application shows how to use the GPIO driver APIs to manipulate interrupt -pins. This application uses default galileo pinmux initialization and sets -the GPIO 5 (IO2) as output pin and GPIO 6 (IO3) as interrupt. It toggles the -output pin stat at every half second in order to emulate an interrupt. This -triggers an interrupt and the application callback is called. You can confirm -that though the UART output. - -======= -= I2C = -======= - -I2C LSM9DS0 -=========== -This application shows how to use I2C driver APIs to configure I2C Master -controller and communicate with LSM9DS0 sensor. At every 5 seconds, the -application reads the "who am I" register from gyroscope sensor and prints if -the register value matches the expected value described in the spec [1]. - -According to the sensor spec, to read the value in "who am I" register, we -should first perform an i2c write operation to select the register we want -to read from and then we perform the i2c read operation to actually read -the register contents. - -The wiring setup is as follows (left column from Galileo and right column from LSM9DS0): -- 3.3v and Vin -- GND and GND -- GND and SDOG -- 3.3v and CSG -- SDA and SDA -- SCL and SCL - -============== -= References = -============== - -[1] http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00087365.pdf - diff --git a/examples/galileo/README.md b/examples/galileo/README.md new file mode 100644 index 000000000..8f3217f05 --- /dev/null +++ b/examples/galileo/README.md @@ -0,0 +1,111 @@ +Galileo Specific Examples +========================= + +This directory contains galileo-specific example applications to illustrate +how to use galileo APIs. + +In order to build a application, you should set the EXAMPLE environment +variable to the name of the application you want to build. For instance, if +you want to build gpio-output application, run the following command: + +``` +$ make TARGET=galileo EXAMPLE=gpio-output +``` + +The corresponding EXAMPLE variable setting for each application is +listed to the right of its heading. + +GPIO +---- + +### GPIO Output (EXAMPLE=gpio-output) + +This application shows how to use the GPIO driver APIs to manipulate output +pins. This application sets the GPIO 5 pin as output pin and toggles its +state at every half second. + +For a visual effect, you should wire shield pin IO2 to a led in a protoboard. +Once the application is running, you should see a blinking LED. + +### GPIO Input (EXAMPLE=gpio-input) + +This application shows how to use the GPIO driver APIs to manipulate +input pins. This application uses default galileo pinmux +initialization and sets the GPIO 5 (shield pin IO2) as output pin and +GPIO 6 (shield pin IO3) as input. A jumper should be used to connect +the two pins. The application toggles the output pin state at every +half second and checks the value on input pin. + +### GPIO Interrupt (EXAMPLE=gpio-interrupt) + +This application shows how to use the GPIO driver APIs to manipulate +interrupt pins. This application uses default galileo pinmux +initialization and sets the GPIO 5 (shield pin IO2) as output pin and +GPIO 6 (shield pin IO3) as interrupt. A jumper should be used to +connect the two pins. It toggles the output pin stat at every half +second in order to emulate an interrupt. This triggers an interrupt +and the application callback is called. You can confirm that though +the UART output. + +I2C +--- + +### I2C LSM9DS0 (EXAMPLE=i2c-LSM9DS0) + +This application shows how to use I2C driver APIs to configure I2C +Master controller and communicate with an LSM9DS0 sensor if one has +been connected as described below. At every 5 seconds, the application +reads the "who am I" register from gyroscope sensor and prints if the +register value matches the expected value described in the spec [1]. + +According to the sensor spec, to read the value in "who am I" register, we +should first perform an i2c write operation to select the register we want +to read from and then we perform the i2c read operation to actually read +the register contents. + +The wiring setup is as follows (left column from Galileo and right column from LSM9DS0): +- 3.3v and Vin +- GND and GND +- GND and SDOG +- 3.3v and CSG +- SDA and SDA +- SCL and SCL + +### I2C Callbacks (EXAMPLE=i2c-callbacks) + +This application is very similar to the previous one in that it also +shows how to use I2C callback functionality, but it can be run without +attaching any additional sensors to the platform since it simply +communicates with a built-in PWM controller. + +Every five seconds, the application reads the current value of the +MODE1 register, which should have previously been initialized to the +value 0x20. The test verifies that this expected value is returned by +the read. + +Isolated Memory Regions +----------------------- + +### Print IMR info (EXAMPLE=print-imr) + +This application prints out information about the configuration of the +Intel Quark X1000 SoC Isolated Memory Regions (IMRs), the Host System +Management Mode Controls register, and the Host Memory I/O Boundary +register. + +Protection Domains +------------------ + +### Protection Domain Switch Latency (EXAMPLE=prot-domain-switch-latency) + +This application measures and prints the average latency of repeatedly +switching from one protection domain to another and back, in ping-pong +fashion. It can optionally perform memory accesses to metadata +associated with the destination protection domain. This feature can +be enabled by specifying SAMPLE_METADATA=1 on the build command line. + +References +---------- + +[1] http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00087365.pdf + diff --git a/examples/galileo/gpio-input.c b/examples/galileo/gpio-input.c index 8728d5088..196ea9193 100644 --- a/examples/galileo/gpio-input.c +++ b/examples/galileo/gpio-input.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,16 +33,13 @@ #include "contiki.h" #include "sys/ctimer.h" -#include "galileo-pinmux.h" #include "gpio.h" -#include "i2c.h" #define PIN_OUTPUT 5 #define PIN_INPUT 6 static uint32_t value; static struct ctimer timer; -static struct quarkX1000_i2c_config i2c_config; PROCESS(gpio_input_process, "GPIO Input Process"); AUTOSTART_PROCESSES(&gpio_input_process); @@ -70,16 +67,6 @@ PROCESS_THREAD(gpio_input_process, ev, data) { PROCESS_BEGIN(); - i2c_config.speed = QUARKX1000_I2C_SPEED_STANDARD; - i2c_config.addressing_mode = QUARKX1000_I2C_ADDR_MODE_7BIT; - - quarkX1000_i2c_init(); - quarkX1000_i2c_configure(&i2c_config); - - /* use default pinmux configuration */ - galileo_pinmux_initialize(); - - quarkX1000_gpio_init(); quarkX1000_gpio_config(PIN_OUTPUT, QUARKX1000_GPIO_OUT); quarkX1000_gpio_config(PIN_INPUT, QUARKX1000_GPIO_IN); diff --git a/examples/galileo/gpio-interrupt.c b/examples/galileo/gpio-interrupt.c index 149279f6f..04fb4cc1b 100644 --- a/examples/galileo/gpio-interrupt.c +++ b/examples/galileo/gpio-interrupt.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,14 +34,11 @@ #include "sys/ctimer.h" #include "gpio.h" -#include "i2c.h" -#include "galileo-pinmux.h" #define PIN_OUTPUT 5 #define PIN_INTR 6 static struct ctimer timer; -static struct quarkX1000_i2c_config i2c_config; PROCESS(gpio_interrupt_process, "GPIO Interrupt Process"); AUTOSTART_PROCESSES(&gpio_interrupt_process); @@ -66,16 +63,6 @@ PROCESS_THREAD(gpio_interrupt_process, ev, data) { PROCESS_BEGIN(); - i2c_config.speed = QUARKX1000_I2C_SPEED_STANDARD; - i2c_config.addressing_mode = QUARKX1000_I2C_ADDR_MODE_7BIT; - - quarkX1000_i2c_init(); - quarkX1000_i2c_configure(&i2c_config); - - /* use default pinmux configuration */ - galileo_pinmux_initialize(); - - quarkX1000_gpio_init(); quarkX1000_gpio_config(PIN_OUTPUT, QUARKX1000_GPIO_OUT); quarkX1000_gpio_config(PIN_INTR, QUARKX1000_GPIO_INT | QUARKX1000_GPIO_ACTIVE_HIGH | QUARKX1000_GPIO_EDGE); diff --git a/examples/galileo/gpio-output.c b/examples/galileo/gpio-output.c index 39a92516f..4dad7d684 100644 --- a/examples/galileo/gpio-output.c +++ b/examples/galileo/gpio-output.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -35,7 +35,7 @@ #include "gpio.h" -#define PIN 4 /* IO1 */ +#define PIN 5 /* IO2 */ static uint32_t value; static struct ctimer timer; @@ -57,7 +57,6 @@ PROCESS_THREAD(gpio_output_process, ev, data) { PROCESS_BEGIN(); - quarkX1000_gpio_init(); quarkX1000_gpio_config(PIN, QUARKX1000_GPIO_OUT); quarkX1000_gpio_clock_enable(); diff --git a/examples/galileo/i2c-LSM9DS0.c b/examples/galileo/i2c-LSM9DS0.c index e5a47c458..03d61a2a4 100644 --- a/examples/galileo/i2c-LSM9DS0.c +++ b/examples/galileo/i2c-LSM9DS0.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -34,7 +34,6 @@ #include "contiki.h" #include "sys/ctimer.h" -#include "galileo-pinmux.h" #include "i2c.h" #define LSM9DS0_I2C_ADDR 0x6A @@ -44,7 +43,6 @@ static uint8_t tx_data = WHO_AM_I_ADDR; static uint8_t rx_data = 0; static struct ctimer timer; -static struct quarkX1000_i2c_config cfg; PROCESS(i2c_lsm9ds0_process, "I2C LSM9DS0 Who Am I Process"); AUTOSTART_PROCESSES(&i2c_lsm9ds0_process); @@ -84,19 +82,7 @@ PROCESS_THREAD(i2c_lsm9ds0_process, ev, data) { PROCESS_BEGIN(); - cfg.speed = QUARKX1000_I2C_SPEED_STANDARD; - cfg.addressing_mode = QUARKX1000_I2C_ADDR_MODE_7BIT; - - quarkX1000_i2c_init(); - quarkX1000_i2c_configure(&cfg); - - galileo_pinmux_initialize(); - - cfg.cb_rx = rx; - cfg.cb_tx = tx; - cfg.cb_err = err; - - quarkX1000_i2c_configure(&cfg); + quarkX1000_i2c_set_callbacks(rx, tx, err); ctimer_set(&timer, CLOCK_SECOND * 5, timeout, NULL); diff --git a/examples/galileo/i2c-callbacks.c b/examples/galileo/i2c-callbacks.c new file mode 100644 index 000000000..d97c6b448 --- /dev/null +++ b/examples/galileo/i2c-callbacks.c @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +#include "contiki.h" +#include "sys/ctimer.h" + +#include "i2c.h" + +#define PWM_PCA9685_0_I2C_ADDR 0x47 +#define MODE1_ADDR 0x00 + +static uint8_t tx_data = MODE1_ADDR; +static uint8_t rx_data = 0; +static struct ctimer timer; + +PROCESS(i2c_callbacks_process, "I2C Callbacks Example Process"); +AUTOSTART_PROCESSES(&i2c_callbacks_process); +/*---------------------------------------------------------------------------*/ +static void +rx(void) +{ + /* The value below is programmed into this register in pwm_pca9685_init(). */ + printf("%s expected value: %x\n", + (rx_data == (1 << 5)) ? "Received" : "Did not receive", + (unsigned)rx_data); +} +/*---------------------------------------------------------------------------*/ +static void +tx(void) +{ + rx_data = 0; + + quarkX1000_i2c_read(&rx_data, sizeof(rx_data), PWM_PCA9685_0_I2C_ADDR); +} +/*---------------------------------------------------------------------------*/ +static void +err(void) +{ + printf("Something went wrong. err() callback has been called.\n"); +} +/*---------------------------------------------------------------------------*/ +static void +timeout(void *data) +{ + quarkX1000_i2c_write(&tx_data, sizeof(tx_data), PWM_PCA9685_0_I2C_ADDR); + + ctimer_reset(&timer); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(i2c_callbacks_process, ev, data) +{ + PROCESS_BEGIN(); + + quarkX1000_i2c_set_callbacks(rx, tx, err); + + ctimer_set(&timer, CLOCK_SECOND * 5, timeout, NULL); + + printf("I2C callbacks example is running\n"); + + PROCESS_YIELD(); + + PROCESS_END(); +} diff --git a/examples/galileo/print-imr.c b/examples/galileo/print-imr.c new file mode 100644 index 000000000..07cd89fed --- /dev/null +++ b/examples/galileo/print-imr.c @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "contiki.h" + +#include "imr.h" +#include "msg-bus.h" + +#define HOST_BRIGE_PORT 3 + +#define HSMMCTL_OFFSET 4 + +#define HMBOUND_OFFSET 8 + +/* Refer to Intel Quark SoC X1000 Datasheet, Section 12.7.2.2 for more details + * on the Host System Management Mode Controls register. + */ +typedef union hsmmctl { + struct { + uint32_t lock : 1; + uint32_t rd_open : 1; + uint32_t wr_open : 1; + uint32_t : 1; + uint32_t start : 12; + uint32_t : 1; + uint32_t non_host_rd_open : 1; + uint32_t non_host_wr_open : 1; + uint32_t : 1; + uint32_t end : 12; + }; + uint32_t raw; +} hsmmctl_t; + +/* Amount to shift hsmmctl.start/end left to obtain the bound address */ +#define HSMMCTL_SHAMT 20 + +/* Refer to Intel Quark SoC X1000 Datasheet, Section 12.7.2.3 for more details + * on the Host Memory I/O Boundary register. + */ +typedef union hmbound { + struct { + uint32_t lock : 1; + uint32_t io_dis : 1; + uint32_t : 10; + uint32_t io_bnd : 20; + }; + uint32_t raw; +} hmbound_t; + +/* Amount to shift hmbound.io_bnd left to obtain the bound address */ +#define HMBOUND_SHAMT 12 + +PROCESS(imr_process, "IMR Process"); +AUTOSTART_PROCESSES(&imr_process); +/*---------------------------------------------------------------------------*/ +static hsmmctl_t +hsmmctl_read(void) +{ + hsmmctl_t hsmm; + + quarkX1000_msg_bus_read(HOST_BRIGE_PORT, HSMMCTL_OFFSET, &hsmm.raw); + + return hsmm; +} +/*---------------------------------------------------------------------------*/ +static void +hsmmctl_print(hsmmctl_t hsmm) +{ + printf("[%08x, %08x) %slocked, non-SMM host: %c%c, non-host: %c%c", + hsmm.start << HSMMCTL_SHAMT, hsmm.end << HSMMCTL_SHAMT, + hsmm.lock ? "" : "un", + hsmm.rd_open ? 'R' : '-', hsmm.wr_open ? 'W' : '-', + hsmm.non_host_rd_open ? 'R' : '-', hsmm.non_host_wr_open ? 'W' : '-'); +} +/*---------------------------------------------------------------------------*/ +static hmbound_t +hmbound_read(void) +{ + hmbound_t hmb; + + quarkX1000_msg_bus_read(HOST_BRIGE_PORT, HMBOUND_OFFSET, &hmb.raw); + + return hmb; +} +/*---------------------------------------------------------------------------*/ +static void +hmbound_print(hmbound_t hmb) +{ + printf("%08x %slocked, IO %sabled", + hmb.io_bnd << HMBOUND_SHAMT, + hmb.lock ? "" : "un", + hmb.io_dis ? "dis" : "en"); +} +/*---------------------------------------------------------------------------*/ +static void +imr_print(quarkX1000_imr_t imr) +{ + printf("[%08x, %08x) %slocked, rdmsk: %08x, wrmsk: %08x", + imr.lo.addr << QUARKX1000_IMR_SHAMT, + imr.hi.addr << QUARKX1000_IMR_SHAMT, + imr.lo.lock ? "" : "un", imr.rdmsk.raw, imr.wrmsk.raw); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(imr_process, ev, data) +{ + int i; + quarkX1000_imr_t imr; + hsmmctl_t hsmm; + hmbound_t hmb; + + PROCESS_BEGIN(); + + fputs("Host SMM Controls: ", stdout); + hsmm = hsmmctl_read(); + hsmmctl_print(hsmm); + fputs("\nHost Memory IO Boundary: ", stdout); + hmb = hmbound_read(); + hmbound_print(hmb); + puts("\nIsolated Memory Regions:"); + for(i = 0; i < QUARKX1000_IMR_CNT; i++) { + printf(" - #%d: ", i); + imr = quarkX1000_imr_read(i); + imr_print(imr); + puts(""); + } + + PROCESS_END(); +} diff --git a/examples/galileo/prot-domain-switch-latency.c b/examples/galileo/prot-domain-switch-latency.c new file mode 100644 index 000000000..9b6908a2f --- /dev/null +++ b/examples/galileo/prot-domain-switch-latency.c @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +#include "contiki.h" +#include "prot-domains.h" +#include "startup.h" +#include "syscalls.h" + +#define CPU_FREQ (400 * 1000 * 1000) +/* Run the test for approximately eight seconds. + * + * Duration expressed as shift amount to avoid integer overflow. + */ +#define DURATION_SECONDS_SHAMT 3 + +#ifdef SAMPLE_METADATA +typedef struct sample_meta { + int cnt; + +#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING + /** + * See the comment on the padding in the metadata for the Intel Quark X1000 + * Ethernet driver for an explanation of why it is sized and structured like + * this. + */ + uint8_t pad[MIN_PAGE_SIZE - sizeof(int)]; +#endif +} __attribute__((packed)) sample_meta_t; + +static sample_meta_t ATTR_BSS_META meta = { .cnt = 0 }; +#endif + +PROT_DOMAINS_ALLOC(dom_client_data_t, ping_dcd); +PROT_DOMAINS_ALLOC(dom_client_data_t, pong_dcd); + +PROCESS(prot_domain_latency_process, "Ping-Pong Process"); +AUTOSTART_PROCESSES(&prot_domain_latency_process); +/*---------------------------------------------------------------------------*/ +void pong(uint64_t *mid, int *cnt); +SYSCALLS_DEFINE_SINGLETON(pong, pong_dcd, + uint64_t *mid, int *cnt) +{ +#ifdef SAMPLE_METADATA + sample_meta_t *loc_meta = (sample_meta_t *)PROT_DOMAINS_META(pong_dcd); +#endif + + *mid = _rdtsc(); + +#ifdef SAMPLE_METADATA + META_READL(*cnt, loc_meta->cnt); + META_WRITEL(loc_meta->cnt, *cnt + 1); +#endif +} +/*---------------------------------------------------------------------------*/ +void ping(void); +SYSCALLS_DEFINE_SINGLETON(ping, ping_dcd) +{ + uint64_t start, mid, end; + uint64_t diff1 = 0, diff2 = 0; + double diff1_d, diff2_d; + int i = 0; + int cnt; + + while(((diff1 + diff2) >> DURATION_SECONDS_SHAMT) < CPU_FREQ) { + start = _rdtsc(); + pong(&mid, &cnt); + end = _rdtsc(); + +#ifdef SAMPLE_METADATA + assert(cnt == i); +#endif + + /* exclude the warm-up round */ + if(i != 0) { + diff1 += mid - start; + diff2 += end - mid; + } + + i++; + } + + diff1_d = diff1; + diff2_d = diff2; + + diff1_d /= i - 1; + diff2_d /= i - 1; + + puts( "Sample protection domain ping-pong switching latency measurements:"); + printf(" %u iterations\n", i - 1); + printf(" Avg. # cycles ping -> pong: %.2f\n", diff1_d); + printf(" + Avg. # cycles pong -> ping: %.2f\n", diff2_d); + puts( " ----------------------------------------"); + printf(" Avg. # cycles round-trip: %.2f\n", diff1_d + diff2_d); +} +/*---------------------------------------------------------------------------*/ +KERN_STARTUP_FUNC(sample_domain_init) +{ + PROT_DOMAINS_INIT_ID(ping_dcd); + prot_domains_reg(&ping_dcd, 0, 0, 0, 0, false); + SYSCALLS_INIT(ping); + SYSCALLS_AUTHZ(ping, ping_dcd); + + PROT_DOMAINS_INIT_ID(pong_dcd); + prot_domains_reg(&pong_dcd, 0, 0, +#ifdef SAMPLE_METADATA + (uintptr_t)&meta, sizeof(meta), false); +#else + 0, 0, false); +#endif + SYSCALLS_INIT(pong); + SYSCALLS_AUTHZ(pong, pong_dcd); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(prot_domain_latency_process, ev, data) +{ + PROCESS_BEGIN(); + + /* Run the latency test from the ping domain so that interrupts + * are disabled during the test. + */ + ping(); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/hello-world/README.md b/examples/hello-world/README.md index c4cbd2c6e..a92c242ab 100644 --- a/examples/hello-world/README.md +++ b/examples/hello-world/README.md @@ -34,7 +34,7 @@ For example, using a loopback interface with the minimal-net platform: make UIP_CONF_IPV6=1 TARGET=minimal-net ./hello-world.minimal-net Hello, world - IPV6 Address: [aaaa::206:98ff:fe00:232] + IPV6 Address: [fd00::206:98ff:fe00:232] IPV6 Address: [fe80::206:98ff:fe00:232] ^C diff --git a/examples/ipso-objects/README.md b/examples/ipso-objects/README.md index 6d1eb5871..e9be82dcb 100644 --- a/examples/ipso-objects/README.md +++ b/examples/ipso-objects/README.md @@ -26,10 +26,10 @@ First program a device with the examples/ipso-objects/example-ipso-objects.c >... ``` -After that start up a native-border router or other border router on aaaa::1/64 +After that start up a native-border router or other border router on fd00::1/64 or another prefix - NOTE: if you use another prefix you will need to change LWM2M_SERVER_ADDRESS for which the device will register - in project-conf.h: ``` -#define LWM2M_SERVER_ADDRESS "aaaa::1" +#define LWM2M_SERVER_ADDRESS "fd00::1" ``` Then when everything is setup you can download a Leshan and use that to diff --git a/examples/ipso-objects/example-ipso-objects.c b/examples/ipso-objects/example-ipso-objects.c index 66a31a0bb..bbb7aa464 100644 --- a/examples/ipso-objects/example-ipso-objects.c +++ b/examples/ipso-objects/example-ipso-objects.c @@ -52,7 +52,7 @@ #endif #ifndef LWM2M_SERVER_ADDRESS -#define LWM2M_SERVER_ADDRESS "aaaa::1" +#define LWM2M_SERVER_ADDRESS "fd00::1" #endif PROCESS(example_ipso_objects, "IPSO object example"); diff --git a/examples/ipso-objects/example-server.c b/examples/ipso-objects/example-server.c index 2d48c738b..605e3295a 100644 --- a/examples/ipso-objects/example-server.c +++ b/examples/ipso-objects/example-server.c @@ -229,19 +229,19 @@ setup_network(void) * Obviously the choice made here must also be selected in udp-client.c. * * For correct Wireshark decoding using a sniffer, add the /64 prefix to the 6LowPAN protocol preferences, - * e.g. set Context 0 to aaaa::. At present Wireshark copies Context/128 and then overwrites it. - * (Setting Context 0 to aaaa::1111:2222:3333:4444 will report a 16 bit compressed address of aaaa::1111:22ff:fe33:xxxx) + * e.g. set Context 0 to fd00::. At present Wireshark copies Context/128 and then overwrites it. + * (Setting Context 0 to fd00::1111:2222:3333:4444 will report a 16 bit compressed address of fd00::1111:22ff:fe33:xxxx) * Note Wireshark's IPCMV6 checksum verification depends on the correct uncompressed addresses. */ #if 0 /* Mode 1 - 64 bits inline */ - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 1); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 1); #elif 1 /* Mode 2 - 16 bits inline */ - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0x00ff, 0xfe00, 1); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0x00ff, 0xfe00, 1); #else /* Mode 3 - derived from link local (MAC) address */ - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); #endif @@ -249,7 +249,7 @@ setup_network(void) root_if = uip_ds6_addr_lookup(&ipaddr); if(root_if != NULL) { dag = rpl_set_root(RPL_DEFAULT_INSTANCE, &ipaddr); - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &ipaddr, 64); PRINTF("created a new RPL dag\n"); } else { diff --git a/examples/ipv6/json-ws/json-ws.c b/examples/ipv6/json-ws/json-ws.c index 6c6177f16..6a290a194 100644 --- a/examples/ipv6/json-ws/json-ws.c +++ b/examples/ipv6/json-ws/json-ws.c @@ -78,7 +78,7 @@ static const char http_content_type_json[] = "application/json"; /* Maximum 40 chars in host name?: 5 x 8 */ -static char callback_host[40] = "[aaaa::1]"; +static char callback_host[40] = "[fd00::1]"; static uint16_t callback_port = CALLBACK_PORT; static uint16_t callback_interval = SEND_INTERVAL; static char callback_path[80] = "/debug/"; diff --git a/examples/ipv6/multicast/intermediate.c b/examples/ipv6/multicast/intermediate.c index 5c45aa75d..a17b7393c 100644 --- a/examples/ipv6/multicast/intermediate.c +++ b/examples/ipv6/multicast/intermediate.c @@ -47,7 +47,7 @@ #include "contiki-net.h" #include "net/ipv6/multicast/uip-mcast6.h" -#if !NETSTACK_CONF_WITH_IPV6 || !UIP_CONF_ROUTER || !UIP_CONF_IPV6_MULTICAST || !UIP_CONF_IPV6_RPL +#if !NETSTACK_CONF_WITH_IPV6 || !UIP_CONF_ROUTER || !UIP_IPV6_MULTICAST || !UIP_CONF_IPV6_RPL #error "This example can not work with the current contiki configuration" #error "Check the values of: NETSTACK_CONF_WITH_IPV6, UIP_CONF_ROUTER, UIP_CONF_IPV6_RPL" #endif diff --git a/examples/ipv6/multicast/root.c b/examples/ipv6/multicast/root.c index 0f27e7d17..f10e140d2 100644 --- a/examples/ipv6/multicast/root.c +++ b/examples/ipv6/multicast/root.c @@ -63,7 +63,7 @@ static struct uip_udp_conn * mcast_conn; static char buf[MAX_PAYLOAD_LEN]; static uint32_t seq_id; -#if !NETSTACK_CONF_WITH_IPV6 || !UIP_CONF_ROUTER || !UIP_CONF_IPV6_MULTICAST || !UIP_CONF_IPV6_RPL +#if !NETSTACK_CONF_WITH_IPV6 || !UIP_CONF_ROUTER || !UIP_IPV6_MULTICAST || !UIP_CONF_IPV6_RPL #error "This example can not work with the current contiki configuration" #error "Check the values of: NETSTACK_CONF_WITH_IPV6, UIP_CONF_ROUTER, UIP_CONF_IPV6_RPL" #endif @@ -111,7 +111,7 @@ set_own_addresses(void) rpl_dag_t *dag; uip_ipaddr_t ipaddr; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); diff --git a/examples/ipv6/multicast/sink.c b/examples/ipv6/multicast/sink.c index 4c272869a..4e795e9de 100644 --- a/examples/ipv6/multicast/sink.c +++ b/examples/ipv6/multicast/sink.c @@ -57,7 +57,7 @@ static uint16_t count; #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) -#if !NETSTACK_CONF_WITH_IPV6 || !UIP_CONF_ROUTER || !UIP_CONF_IPV6_MULTICAST || !UIP_CONF_IPV6_RPL +#if !NETSTACK_CONF_WITH_IPV6 || !UIP_CONF_ROUTER || !UIP_IPV6_MULTICAST || !UIP_CONF_IPV6_RPL #error "This example can not work with the current contiki configuration" #error "Check the values of: NETSTACK_CONF_WITH_IPV6, UIP_CONF_ROUTER, UIP_CONF_IPV6_RPL" #endif @@ -84,7 +84,7 @@ join_mcast_group(void) uip_ds6_maddr_t *rv; /* First, set our v6 global */ - uip_ip6addr(&addr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&addr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&addr, &uip_lladdr); uip_ds6_addr_add(&addr, 0, ADDR_AUTOCONF); diff --git a/examples/ipv6/native-border-router/Makefile b/examples/ipv6/native-border-router/Makefile index d781ed35c..dc60e18d9 100644 --- a/examples/ipv6/native-border-router/Makefile +++ b/examples/ipv6/native-border-router/Makefile @@ -24,4 +24,4 @@ CONTIKI_WITH_IPV6 = 1 include $(CONTIKI)/Makefile.include connect-router: border-router.native - sudo ./border-router.native aaaa::1/64 + sudo ./border-router.native fd00::1/64 diff --git a/examples/ipv6/native-border-router/slip-config.c b/examples/ipv6/native-border-router/slip-config.c index 84d256127..d6b6e0660 100644 --- a/examples/ipv6/native-border-router/slip-config.c +++ b/examples/ipv6/native-border-router/slip-config.c @@ -67,7 +67,7 @@ int slip_config_handle_arguments(int argc, char **argv) { const char *prog; - char c; + int c; int baudrate = 115200; slip_config_verbose = 0; @@ -125,7 +125,7 @@ slip_config_handle_arguments(int argc, char **argv) case 'h': default: fprintf(stderr,"usage: %s [options] ipaddress\n", prog); -fprintf(stderr,"example: border-router.native -L -v2 -s ttyUSB1 aaaa::1/64\n"); +fprintf(stderr,"example: border-router.native -L -v2 -s ttyUSB1 fd00::1/64\n"); fprintf(stderr,"Options are:\n"); #ifdef linux fprintf(stderr," -B baudrate 9600,19200,38400,57600,115200,921600 (default 115200)\n"); diff --git a/examples/ipv6/rpl-border-router/Makefile b/examples/ipv6/rpl-border-router/Makefile index ce90a4eac..d325918ec 100644 --- a/examples/ipv6/rpl-border-router/Makefile +++ b/examples/ipv6/rpl-border-router/Makefile @@ -21,6 +21,10 @@ PROJECT_SOURCEFILES += slip-bridge.c #of the slip connection. Large MSS together with low baud rates without flow #control will overrun the transmit buffer when the style sheet is requested. +ifeq ($(MAKE_WITH_NON_STORING),1) +CFLAGS += -DWITH_NON_STORING=1 +endif + WITH_WEBSERVER=1 ifeq ($(WITH_WEBSERVER),1) CFLAGS += -DUIP_CONF_TCP=1 @@ -33,7 +37,7 @@ CFLAGS += -DWEBSERVER=2 endif ifeq ($(PREFIX),) - PREFIX = aaaa::1/64 + PREFIX = fd00::1/64 endif CONTIKI_WITH_IPV6 = 1 diff --git a/examples/ipv6/rpl-border-router/project-conf.h b/examples/ipv6/rpl-border-router/project-conf.h index 9d9116795..ec3eb3f00 100644 --- a/examples/ipv6/rpl-border-router/project-conf.h +++ b/examples/ipv6/rpl-border-router/project-conf.h @@ -31,6 +31,19 @@ #ifndef PROJECT_ROUTER_CONF_H_ #define PROJECT_ROUTER_CONF_H_ +#ifndef WITH_NON_STORING +#define WITH_NON_STORING 0 /* Set this to run with non-storing mode */ +#endif /* WITH_NON_STORING */ + +#if WITH_NON_STORING +#undef RPL_NS_CONF_LINK_NUM +#define RPL_NS_CONF_LINK_NUM 40 /* Number of links maintained at the root */ +#undef UIP_CONF_MAX_ROUTES +#define UIP_CONF_MAX_ROUTES 0 /* No need for routes */ +#undef RPL_CONF_MOP +#define RPL_CONF_MOP RPL_MOP_NON_STORING /* Mode of operation*/ +#endif /* WITH_NON_STORING */ + #ifndef UIP_FALLBACK_INTERFACE #define UIP_FALLBACK_INTERFACE rpl_interface #endif diff --git a/examples/ipv6/rpl-collect/Makefile b/examples/ipv6/rpl-collect/Makefile index ce20c79e2..13813ed44 100644 --- a/examples/ipv6/rpl-collect/Makefile +++ b/examples/ipv6/rpl-collect/Makefile @@ -3,6 +3,12 @@ APPS = powertrace collect-view CONTIKI_PROJECT = udp-sender udp-sink PROJECT_SOURCEFILES += collect-common.c +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" + +ifeq ($(MAKE_WITH_NON_STORING),1) +CFLAGS += -DWITH_NON_STORING=1 +endif + ifdef PERIOD CFLAGS=-DPERIOD=$(PERIOD) endif diff --git a/examples/ipv6/rpl-collect/project-conf.h b/examples/ipv6/rpl-collect/project-conf.h new file mode 100644 index 000000000..a143b07cd --- /dev/null +++ b/examples/ipv6/rpl-collect/project-conf.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#ifndef WITH_NON_STORING +#define WITH_NON_STORING 0 /* Set this to run with non-storing mode */ +#endif /* WITH_NON_STORING */ + +#undef NBR_TABLE_CONF_MAX_NEIGHBORS +#undef UIP_CONF_MAX_ROUTES + +#ifdef TEST_MORE_ROUTES +/* configure number of neighbors and routes */ +#define NBR_TABLE_CONF_MAX_NEIGHBORS 10 +#define UIP_CONF_MAX_ROUTES 30 +#else +/* configure number of neighbors and routes */ +#define NBR_TABLE_CONF_MAX_NEIGHBORS 10 +#define UIP_CONF_MAX_ROUTES 10 +#endif /* TEST_MORE_ROUTES */ + +#undef NETSTACK_CONF_RDC +#define NETSTACK_CONF_RDC nullrdc_driver +#undef NULLRDC_CONF_802154_AUTOACK +#define NULLRDC_CONF_802154_AUTOACK 1 + +/* Define as minutes */ +#define RPL_CONF_DEFAULT_LIFETIME_UNIT 60 + +/* 10 minutes lifetime of routes */ +#define RPL_CONF_DEFAULT_LIFETIME 10 + +#define RPL_CONF_DEFAULT_ROUTE_INFINITE_LIFETIME 1 + +/* Save some ROM */ +#undef UIP_CONF_TCP +#define UIP_CONF_TCP 0 + +#undef SICSLOWPAN_CONF_FRAG +#define SICSLOWPAN_CONF_FRAG 0 + +#if WITH_NON_STORING +#undef RPL_NS_CONF_LINK_NUM +#define RPL_NS_CONF_LINK_NUM 40 /* Number of links maintained at the root. Can be set to 0 at non-root nodes. */ +#undef UIP_CONF_MAX_ROUTES +#define UIP_CONF_MAX_ROUTES 0 /* No need for routes */ +#undef RPL_CONF_MOP +#define RPL_CONF_MOP RPL_MOP_NON_STORING /* Mode of operation*/ +#endif /* WITH_NON_STORING */ + +#endif /* PROJECT_CONF_H_ */ diff --git a/examples/ipv6/rpl-collect/udp-sender.c b/examples/ipv6/rpl-collect/udp-sender.c index dd279cc7f..469d5e6f0 100644 --- a/examples/ipv6/rpl-collect/udp-sender.c +++ b/examples/ipv6/rpl-collect/udp-sender.c @@ -195,12 +195,12 @@ set_global_address(void) { uip_ipaddr_t ipaddr; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); /* set server address */ - uip_ip6addr(&server_ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 1); + uip_ip6addr(&server_ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 1); } /*---------------------------------------------------------------------------*/ diff --git a/examples/ipv6/rpl-collect/udp-sink.c b/examples/ipv6/rpl-collect/udp-sink.c index dbdde2d01..7834c7cbc 100644 --- a/examples/ipv6/rpl-collect/udp-sink.c +++ b/examples/ipv6/rpl-collect/udp-sink.c @@ -145,14 +145,14 @@ PROCESS_THREAD(udp_server_process, ev, data) PRINTF("UDP server started\n"); #if UIP_CONF_ROUTER - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 1); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 1); /* uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); */ uip_ds6_addr_add(&ipaddr, 0, ADDR_MANUAL); root_if = uip_ds6_addr_lookup(&ipaddr); if(root_if != NULL) { rpl_dag_t *dag; dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr); - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &ipaddr, 64); PRINTF("created a new RPL dag\n"); } else { diff --git a/examples/ipv6/rpl-tsch/node.c b/examples/ipv6/rpl-tsch/node.c index 2aee41d81..35852b608 100644 --- a/examples/ipv6/rpl-tsch/node.c +++ b/examples/ipv6/rpl-tsch/node.c @@ -71,7 +71,7 @@ print_network_status(void) uip_ds6_route_t *route; PRINTA("--- Network status ---\n"); - + /* Our IPv6 addresses */ PRINTA("- Server IPv6 addresses:\n"); for(i = 0; i < UIP_DS6_ADDR_NB; i++) { @@ -83,13 +83,13 @@ print_network_status(void) PRINTA("\n"); } } - + /* Our default route */ PRINTA("- Default route:\n"); default_route = uip_ds6_defrt_lookup(uip_ds6_defrt_choose()); if(default_route != NULL) { PRINTA("-- "); - uip_debug_ipaddr_print(&default_route->ipaddr);; + uip_debug_ipaddr_print(&default_route->ipaddr); PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)default_route->lifetime.interval); } else { PRINTA("-- None\n"); @@ -104,9 +104,9 @@ print_network_status(void) PRINTA(" via "); uip_debug_ipaddr_print(uip_ds6_route_nexthop(route)); PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)route->state.lifetime); - route = uip_ds6_route_next(route); + route = uip_ds6_route_next(route); } - + PRINTA("----------------------\n"); } /*---------------------------------------------------------------------------*/ @@ -134,17 +134,24 @@ PROCESS_THREAD(node_process, ev, data) PROCESS_BEGIN(); /* 3 possible roles: - * - role_6ln: simple node, will join any network, secured or not - * - role_6dr: DAG root, will advertise (unsecured) beacons - * - role_6dr_sec: DAG root, will advertise secured beacons - * */ + * - role_6ln: simple node, will join any network, secured or not + * - role_6dr: DAG root, will advertise (unsecured) beacons + * - role_6dr_sec: DAG root, will advertise secured beacons + * */ static int is_coordinator = 0; static enum { role_6ln, role_6dr, role_6dr_sec } node_role; node_role = role_6ln; - - /* Set node with ID == 1 as coordinator, convenient in Cooja. */ - if(node_id == 1) { - if(LLSEC802154_CONF_SECURITY_LEVEL) { + + /* Set node with MAC address c1:0c:00:00:00:00:01 as coordinator, + * convenient in cooja for regression tests using z1 nodes + * */ + +#ifdef CONTIKI_TARGET_Z1 + extern unsigned char node_mac[8]; + unsigned char coordinator_mac[8] = { 0xc1, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; + + if(memcmp(node_mac, coordinator_mac, 8) == 0) { + if(LLSEC802154_ENABLED) { node_role = role_6dr_sec; } else { node_role = role_6dr; @@ -152,6 +159,7 @@ PROCESS_THREAD(node_process, ev, data) } else { node_role = role_6ln; } +#endif #if CONFIG_VIA_BUTTON { @@ -162,14 +170,14 @@ PROCESS_THREAD(node_process, ev, data) while(!etimer_expired(&et)) { printf("Init: current role: %s. Will start in %u seconds. Press user button to toggle mode.\n", - node_role == role_6ln ? "6ln" : (node_role == role_6dr) ? "6dr" : "6dr-sec", - CONFIG_WAIT_TIME); + node_role == role_6ln ? "6ln" : (node_role == role_6dr) ? "6dr" : "6dr-sec", + CONFIG_WAIT_TIME); PROCESS_WAIT_EVENT_UNTIL(((ev == sensors_event) && (data == &button_sensor) && button_sensor.value(0) > 0) || etimer_expired(&et)); if(ev == sensors_event && data == &button_sensor && button_sensor.value(0) > 0) { node_role = (node_role + 1) % 3; - if(LLSEC802154_CONF_SECURITY_LEVEL == 0 && node_role == role_6dr_sec) { + if(LLSEC802154_ENABLED == 0 && node_role == role_6dr_sec) { node_role = (node_role + 1) % 3; } etimer_restart(&et); @@ -180,31 +188,31 @@ PROCESS_THREAD(node_process, ev, data) #endif /* CONFIG_VIA_BUTTON */ printf("Init: node starting with role %s\n", - node_role == role_6ln ? "6ln" : (node_role == role_6dr) ? "6dr" : "6dr-sec"); + node_role == role_6ln ? "6ln" : (node_role == role_6dr) ? "6dr" : "6dr-sec"); - tsch_set_pan_secured(LLSEC802154_CONF_SECURITY_LEVEL && (node_role == role_6dr_sec)); + tsch_set_pan_secured(LLSEC802154_ENABLED && (node_role == role_6dr_sec)); is_coordinator = node_role > role_6ln; if(is_coordinator) { uip_ipaddr_t prefix; - uip_ip6addr(&prefix, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); net_init(&prefix); } else { net_init(NULL); } - + #if WITH_ORCHESTRA orchestra_init(); #endif /* WITH_ORCHESTRA */ - + /* Print out routing tables every minute */ etimer_set(&et, CLOCK_SECOND * 60); - while(1) { + while(1) { print_network_status(); PROCESS_YIELD_UNTIL(etimer_expired(&et)); etimer_reset(&et); } - + PROCESS_END(); } /*---------------------------------------------------------------------------*/ diff --git a/examples/ipv6/rpl-tsch/project-conf.h b/examples/ipv6/rpl-tsch/project-conf.h index 7ecfb74c1..8ac0a93b6 100644 --- a/examples/ipv6/rpl-tsch/project-conf.h +++ b/examples/ipv6/rpl-tsch/project-conf.h @@ -67,13 +67,19 @@ #define TSCH_CALLBACK_JOINING_NETWORK tsch_rpl_callback_joining_network #define TSCH_CALLBACK_LEAVING_NETWORK tsch_rpl_callback_leaving_network +/* Needed for CC2538 platforms only */ +/* For TSCH we have to use the more accurate crystal oscillator + * by default the RC oscillator is activated */ +#undef SYS_CTRL_CONF_OSC32K_USE_XTAL +#define SYS_CTRL_CONF_OSC32K_USE_XTAL 1 + /* Needed for cc2420 platforms only */ /* Disable DCO calibration (uses timerB) */ #undef DCOSYNCH_CONF_ENABLED -#define DCOSYNCH_CONF_ENABLED 0 +#define DCOSYNCH_CONF_ENABLED 0 /* Enable SFD timestamps (uses timerB) */ #undef CC2420_CONF_SFD_TIMESTAMPS -#define CC2420_CONF_SFD_TIMESTAMPS 1 +#define CC2420_CONF_SFD_TIMESTAMPS 1 /*******************************************************/ /******************* Configure TSCH ********************/ @@ -100,8 +106,8 @@ #if WITH_SECURITY /* Enable security */ -#undef LLSEC802154_CONF_SECURITY_LEVEL -#define LLSEC802154_CONF_SECURITY_LEVEL 1 +#undef LLSEC802154_CONF_ENABLED +#define LLSEC802154_CONF_ENABLED 1 /* TSCH uses explicit keys to identify k1 and k2 */ #undef LLSEC802154_CONF_USES_EXPLICIT_KEYS #define LLSEC802154_CONF_USES_EXPLICIT_KEYS 1 @@ -133,7 +139,7 @@ #undef UIP_CONF_TCP #define UIP_CONF_TCP 0 #undef QUEUEBUF_CONF_NUM -#define QUEUEBUF_CONF_NUM 4 +#define QUEUEBUF_CONF_NUM 3 #undef UIP_CONF_MAX_ROUTES #define UIP_CONF_MAX_ROUTES 8 #undef NBR_TABLE_CONF_MAX_NEIGHBORS @@ -153,7 +159,7 @@ #define TSCH_SCHEDULE_CONF_DEFAULT_LENGTH 2 /* Reduce log level to make space for security on z1 */ #undef TSCH_LOG_CONF_LEVEL -#define TSCH_LOG_CONF_LEVEL 1 +#define TSCH_LOG_CONF_LEVEL 0 #endif /* WITH_SECURITY */ #endif /* CONTIKI_TARGET_Z1 */ diff --git a/examples/ipv6/rpl-udp/Makefile b/examples/ipv6/rpl-udp/Makefile index 9670d71e3..d7330821a 100644 --- a/examples/ipv6/rpl-udp/Makefile +++ b/examples/ipv6/rpl-udp/Makefile @@ -1,7 +1,8 @@ all: udp-client udp-server -APPS=servreg-hack CONTIKI=../../.. +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" + ifdef WITH_COMPOWER APPS+=powertrace CFLAGS+= -DCONTIKIMAC_CONF_COMPOWER=1 -DWITH_COMPOWER=1 -DQUEUEBUF_CONF_NUM=4 @@ -14,5 +15,9 @@ ifdef PERIOD CFLAGS+=-DPERIOD=$(PERIOD) endif +ifeq ($(MAKE_WITH_NON_STORING),1) +CFLAGS += -DWITH_NON_STORING=1 +endif + CONTIKI_WITH_IPV6 = 1 include $(CONTIKI)/Makefile.include diff --git a/examples/ipv6/rpl-udp/project-conf.h b/examples/ipv6/rpl-udp/project-conf.h new file mode 100644 index 000000000..794897a46 --- /dev/null +++ b/examples/ipv6/rpl-udp/project-conf.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#ifndef WITH_NON_STORING +#define WITH_NON_STORING 0 /* Set this to run with non-storing mode */ +#endif /* WITH_NON_STORING */ + +#undef NBR_TABLE_CONF_MAX_NEIGHBORS +#undef UIP_CONF_MAX_ROUTES + +#ifdef TEST_MORE_ROUTES +/* configure number of neighbors and routes */ +#define NBR_TABLE_CONF_MAX_NEIGHBORS 10 +#define UIP_CONF_MAX_ROUTES 30 +#else +/* configure number of neighbors and routes */ +#define NBR_TABLE_CONF_MAX_NEIGHBORS 10 +#define UIP_CONF_MAX_ROUTES 10 +#endif /* TEST_MORE_ROUTES */ + +#undef NETSTACK_CONF_RDC +#define NETSTACK_CONF_RDC nullrdc_driver +#undef NULLRDC_CONF_802154_AUTOACK +#define NULLRDC_CONF_802154_AUTOACK 1 + +/* Define as minutes */ +#define RPL_CONF_DEFAULT_LIFETIME_UNIT 60 + +/* 10 minutes lifetime of routes */ +#define RPL_CONF_DEFAULT_LIFETIME 10 + +#define RPL_CONF_DEFAULT_ROUTE_INFINITE_LIFETIME 1 + +#ifndef RPL_CONF_WITH_NON_STORING +#define RPL_CONF_WITH_NON_STORING 0 /* Set this to run with non-storing mode */ +#endif /* RPL_CONF_WITH_NON_STORING */ + +#if WITH_NON_STORING +#undef RPL_NS_CONF_LINK_NUM +#define RPL_NS_CONF_LINK_NUM 40 /* Number of links maintained at the root. Can be set to 0 at non-root nodes. */ +#undef UIP_CONF_MAX_ROUTES +#define UIP_CONF_MAX_ROUTES 0 /* No need for routes */ +#undef RPL_CONF_MOP +#define RPL_CONF_MOP RPL_MOP_NON_STORING /* Mode of operation*/ +#endif /* WITH_NON_STORING */ + +#endif diff --git a/examples/ipv6/rpl-udp/rpl-udp-scale-wismote.csc b/examples/ipv6/rpl-udp/rpl-udp-scale-wismote.csc new file mode 100644 index 000000000..3aea07ab0 --- /dev/null +++ b/examples/ipv6/rpl-udp/rpl-udp-scale-wismote.csc @@ -0,0 +1,721 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + RPL up and downstream scaleability test network using IPv6 and RPL + generated + 5000000 + + org.contikios.cooja.radiomediums.UDGM + 150.0 + 150.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.mspmote.WismoteMoteType + sky1 + WisMote Type #sky1 + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-server.c + make SERVER_REPLY=1 clean udp-server.wismote TARGET=wismote DEFINES=TEST_MORE_ROUTES=1 + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-server.wismote + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.interfaces.IPAddress + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + org.contikios.cooja.mspmote.interfaces.MspClock + org.contikios.cooja.mspmote.interfaces.MspMoteID + org.contikios.cooja.mspmote.interfaces.MspButton + org.contikios.cooja.mspmote.interfaces.Msp802154Radio + org.contikios.cooja.mspmote.interfaces.MspDefaultSerial + org.contikios.cooja.mspmote.interfaces.MspLED + org.contikios.cooja.mspmote.interfaces.MspDebugOutput + + + org.contikios.cooja.mspmote.WismoteMoteType + sky2 + WisMote Type #sky2 + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-client.c + make SERVER_REPLY=1 clean udp-client.wismote TARGET=wismote + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-client.wismote + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.interfaces.IPAddress + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + org.contikios.cooja.mspmote.interfaces.MspClock + org.contikios.cooja.mspmote.interfaces.MspMoteID + org.contikios.cooja.mspmote.interfaces.MspButton + org.contikios.cooja.mspmote.interfaces.Msp802154Radio + org.contikios.cooja.mspmote.interfaces.MspDefaultSerial + org.contikios.cooja.mspmote.interfaces.MspLED + org.contikios.cooja.mspmote.interfaces.MspDebugOutput + + + + + org.contikios.cooja.interfaces.Position + 48.435974731198804 + -66.16503914182063 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 1 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + -65.3176930733124 + 17.4304162608286 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 2 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 127.9689727848476 + 91.71883780610729 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 3 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 154.92605604103275 + 40.97896551774433 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 4 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 47.34887596588397 + -30.341495695501195 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 5 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 47.13486576528276 + 32.944481932122315 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 6 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -11.42091423859419 + 17.879870626121914 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 7 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 118.92746659954325 + 57.05973076244069 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 8 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 56.66768196114595 + 74.35652008990945 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 9 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 16.45706316609417 + 23.9075414163248 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 10 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -13.423161364506493 + -38.483037144768275 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 11 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -9.034961217472201 + 44.411389162165406 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 12 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 35.60049910164592 + 87.95154356223047 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 13 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 66.93880603404335 + -42.39683727590697 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 14 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 94.81678343873172 + 26.921376811426246 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 15 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -49.449656689283934 + 57.924813144367945 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 16 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -34.02467970185502 + -24.313824905298304 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 17 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -28.750467760427494 + 48.01822457713635 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 18 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 124.95513738974614 + 20.140247172447996 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 19 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 14.85247487703553 + -34.478542892943686 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 20 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 154.43072661267115 + -3.279765376986134 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 21 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 99.90960713878738 + -21.76043658444847 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 22 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 88.4612185198951 + -49.763990463932714 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 23 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 24.745110502623138 + -1.7100594420374744 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 24 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 94.06332458995635 + -2.4635182908128352 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 25 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -4.639784599615941 + -10.849236218849724 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 26 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 2.4901685804620115 + -60.89843789583528 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 27 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 100.55144245441083 + 97.41861446767646 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 28 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -12.355761328741393 + 82.72616691655692 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 29 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 57.79962925723111 + 0.6828700499064966 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 30 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 76.5550413097159 + 77.33875258624342 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 31 + + sky2 + + + + org.contikios.cooja.plugins.SimControl + 289 + 4 + 184 + 31 + 41 + + + org.contikios.cooja.plugins.Visualizer + + true + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.AttributeVisualizerSkin + 2.349818846983307 0.0 0.0 2.349818846983307 187.19773526533345 190.95275613586946 + + 659 + 2 + 622 + 296 + 11 + + + org.contikios.cooja.plugins.LogListener + + ID:22.*DAO + + + + 937 + 3 + 442 + 20 + 297 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 600 + 5 + 700 + 946 + 6 + + + org.contikios.cooja.plugins.MoteInterfaceViewer + 3 + + Position + 0,0 + + 350 + 6 + 300 + 976 + 36 + + + diff --git a/examples/ipv6/rpl-udp/rpl-udp-scale.csc b/examples/ipv6/rpl-udp/rpl-udp-scale.csc new file mode 100644 index 000000000..292e442c1 --- /dev/null +++ b/examples/ipv6/rpl-udp/rpl-udp-scale.csc @@ -0,0 +1,729 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + RPL up and downstream scaleability test network using IPv6 and RPL + generated + 5000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.mspmote.SkyMoteType + sky1 + Sky Mote Type #sky1 + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-server.c + make SERVER_REPLY=1 clean udp-server.sky TARGET=sky DEFINES=TEST_MORE_ROUTES=1 + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-server.sky + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.interfaces.IPAddress + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + org.contikios.cooja.mspmote.interfaces.MspClock + org.contikios.cooja.mspmote.interfaces.MspMoteID + org.contikios.cooja.mspmote.interfaces.SkyButton + org.contikios.cooja.mspmote.interfaces.SkyFlash + org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem + org.contikios.cooja.mspmote.interfaces.Msp802154Radio + org.contikios.cooja.mspmote.interfaces.MspSerial + org.contikios.cooja.mspmote.interfaces.SkyLED + org.contikios.cooja.mspmote.interfaces.MspDebugOutput + org.contikios.cooja.mspmote.interfaces.SkyTemperature + + + org.contikios.cooja.mspmote.SkyMoteType + sky2 + Sky Mote Type #sky2 + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-client.c + make SERVER_REPLY=1 clean udp-client.sky TARGET=sky + [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-client.sky + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.interfaces.IPAddress + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + org.contikios.cooja.mspmote.interfaces.MspClock + org.contikios.cooja.mspmote.interfaces.MspMoteID + org.contikios.cooja.mspmote.interfaces.SkyButton + org.contikios.cooja.mspmote.interfaces.SkyFlash + org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem + org.contikios.cooja.mspmote.interfaces.Msp802154Radio + org.contikios.cooja.mspmote.interfaces.MspSerial + org.contikios.cooja.mspmote.interfaces.SkyLED + org.contikios.cooja.mspmote.interfaces.MspDebugOutput + org.contikios.cooja.mspmote.interfaces.SkyTemperature + + + + + org.contikios.cooja.interfaces.Position + 48.435974731198804 + -66.16503914182063 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 1 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + -39.78380986481406 + -48.10655064098382 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 2 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 127.9689727848476 + 91.71883780610729 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 3 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 154.92605604103275 + 40.97896551774433 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 4 + + + org.contikios.cooja.mspmote.interfaces.MspSerial + r~; + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 47.34887596588397 + -30.341495695501195 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 5 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 47.13486576528276 + 32.944481932122315 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 6 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -11.42091423859419 + 17.879870626121914 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 7 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 118.92746659954325 + 57.05973076244069 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 8 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 53.68872892015448 + 59.887319605093715 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 9 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 16.45706316609417 + 23.9075414163248 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 10 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -13.423161364506493 + -38.483037144768275 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 11 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -9.034961217472201 + 44.411389162165406 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 12 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -39.298891643282545 + -3.9704359883635574 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 13 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 66.93880603404335 + -42.39683727590697 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 14 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 94.81678343873172 + 26.921376811426246 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 15 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -43.06618588715935 + 30.68867105530305 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 16 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -34.02467970185502 + -24.313824905298304 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 17 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -28.750467760427494 + 48.01822457713635 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 18 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 124.95513738974614 + 20.140247172447996 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 19 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 15.703604317318808 + -47.6710492173345 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 20 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 154.43072661267115 + -3.279765376986134 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 21 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 121.18784314586934 + -24.313824905298304 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 22 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 88.4612185198951 + -49.763990463932714 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 23 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 24.745110502623138 + -1.7100594420374744 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 24 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 94.06332458995635 + -2.4635182908128352 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 25 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + -4.639784599615941 + -9.998106778566445 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 26 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 2.4901685804620115 + -60.89843789583528 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 27 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 103.10483077526068 + 96.99304974753483 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 28 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 8.922474678340558 + 59.320107308766765 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 29 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 58.650758697514384 + 2.8106936506146916 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 30 + + sky2 + + + + + org.contikios.cooja.interfaces.Position + 90.59867707439 + 67.97632874312737 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 31 + + sky2 + + + + org.contikios.cooja.plugins.SimControl + 289 + 1 + 184 + 31 + 41 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.AttributeVisualizerSkin + 2.349818846983307 0.0 0.0 2.349818846983307 187.19773526533345 190.95275613586946 + + 659 + 3 + 523 + 296 + 11 + + + org.contikios.cooja.plugins.LogListener + + + + + + 937 + 4 + 349 + 21 + 464 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 600 + 0 + 700 + 946 + 6 + + + org.contikios.cooja.plugins.MoteInterfaceViewer + 3 + + Serial port + 0,0 + + 350 + 2 + 300 + 976 + 36 + + diff --git a/examples/ipv6/rpl-udp/rpl-udp.csc b/examples/ipv6/rpl-udp/rpl-udp.csc index cf7c049f1..3aa9b270e 100644 --- a/examples/ipv6/rpl-udp/rpl-udp.csc +++ b/examples/ipv6/rpl-udp/rpl-udp.csc @@ -1,12 +1,13 @@ - [CONTIKI_DIR]/tools/cooja/apps/mrm - [CONTIKI_DIR]/tools/cooja/apps/mspsim - [CONTIKI_DIR]/tools/cooja/apps/avrora - [CONTIKI_DIR]/tools/cooja/apps/mobility + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker Data collection network using IPv6 and RPL - 0 generated 5000000 @@ -24,7 +25,7 @@ sky1 Sky Mote Type #sky1 [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-server.c - make udp-server.sky TARGET=sky + make clean udp-server.sky TARGET=sky DEFINES=TEST_MORE_ROUTES=1 [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-server.sky org.contikios.cooja.interfaces.Position org.contikios.cooja.interfaces.RimeAddress @@ -47,7 +48,7 @@ sky2 Sky Mote Type #sky2 [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-client.c - make udp-client.sky TARGET=sky + make clean udp-client.sky TARGET=sky [CONTIKI_DIR]/examples/ipv6/rpl-udp/udp-client.sky org.contikios.cooja.interfaces.Position org.contikios.cooja.interfaces.RimeAddress @@ -73,6 +74,10 @@ -66.16503914182063 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 1 @@ -87,6 +92,10 @@ 98.28771308774003 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 2 @@ -101,6 +110,10 @@ 91.71883780610729 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 3 @@ -115,6 +128,10 @@ 92.47229665488265 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 4 @@ -129,6 +146,10 @@ -30.341495695501195 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 5 @@ -143,6 +164,10 @@ 32.944481932122315 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 6 @@ -157,6 +182,10 @@ 17.879870626121914 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 7 @@ -171,6 +200,10 @@ 57.05973076244069 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 8 @@ -185,6 +218,10 @@ 59.887319605093715 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 9 @@ -199,6 +236,10 @@ 23.9075414163248 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 10 @@ -213,6 +254,10 @@ 75.14274313304935 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 11 @@ -227,6 +272,10 @@ 85.6911670159044 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 12 @@ -241,6 +290,10 @@ -3.9704359883635574 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 13 @@ -255,6 +308,10 @@ -42.39683727590697 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 14 @@ -269,6 +326,10 @@ 26.921376811426246 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 15 @@ -283,6 +344,10 @@ 30.68867105530305 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 16 @@ -297,6 +362,10 @@ -24.313824905298304 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 17 @@ -311,6 +380,10 @@ 48.01822457713635 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 18 @@ -325,6 +398,10 @@ 20.140247172447996 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 19 @@ -339,6 +416,10 @@ -47.6710492173345 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 20 @@ -353,6 +434,10 @@ 92.47229665488265 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 21 @@ -367,6 +452,10 @@ -24.313824905298304 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 22 @@ -381,6 +470,10 @@ -44.657213822233054 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 23 @@ -395,6 +488,10 @@ -1.7100594420374744 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 24 @@ -409,6 +506,10 @@ -2.4635182908128352 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 25 @@ -423,6 +524,10 @@ -9.998106778566445 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 26 @@ -437,6 +542,10 @@ -50.684884612435944 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 27 @@ -451,6 +560,10 @@ 96.99304974753483 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 28 @@ -465,6 +578,10 @@ 59.320107308766765 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 29 @@ -479,6 +596,10 @@ 2.8106936506146916 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 30 @@ -493,6 +614,10 @@ 67.97632874312737 0.0 + + org.contikios.cooja.mspmote.interfaces.MspClock + 1.0 + org.contikios.cooja.mspmote.interfaces.MspMoteID 31 @@ -503,10 +628,10 @@ org.contikios.cooja.plugins.SimControl 259 - 1 + 3 184 - 0 - 0 + 3 + 15 org.contikios.cooja.plugins.Visualizer @@ -517,21 +642,23 @@ 2.349818846983307 0.0 0.0 2.349818846983307 150.19773526533348 176.95275613586946 520 - 3 + 2 523 - 269 - 14 + 14 + 210 org.contikios.cooja.plugins.LogListener + + 937 0 213 - 21 - 464 + 265 + 16 org.contikios.cooja.plugins.ScriptRunner @@ -574,11 +701,11 @@ while(1) { } true - 600 - 2 - 700 - 665 - 6 + 651 + 1 + 550 + 547 + 181 diff --git a/examples/ipv6/rpl-udp/udp-client.c b/examples/ipv6/rpl-udp/udp-client.c index c16b0ba48..e5339fc3d 100644 --- a/examples/ipv6/rpl-udp/udp-client.c +++ b/examples/ipv6/rpl-udp/udp-client.c @@ -40,12 +40,17 @@ #include #include +/* Only for TMOTE Sky? */ +#include "dev/serial-line.h" +#include "dev/uart1.h" +#include "net/ipv6/uip-ds6-route.h" + #define UDP_CLIENT_PORT 8765 #define UDP_SERVER_PORT 5678 #define UDP_EXAMPLE_ID 190 -#define DEBUG DEBUG_PRINT +#define DEBUG DEBUG_FULL #include "net/ip/uip-debug.h" #ifndef PERIOD @@ -64,6 +69,9 @@ static uip_ipaddr_t server_ipaddr; PROCESS(udp_client_process, "UDP client process"); AUTOSTART_PROCESSES(&udp_client_process); /*---------------------------------------------------------------------------*/ +static int seq_id; +static int reply; + static void tcpip_handler(void) { @@ -72,16 +80,32 @@ tcpip_handler(void) if(uip_newdata()) { str = uip_appdata; str[uip_datalen()] = '\0'; - printf("DATA recv '%s'\n", str); + reply++; + printf("DATA recv '%s' (s:%d, r:%d)\n", str, seq_id, reply); } } /*---------------------------------------------------------------------------*/ static void send_packet(void *ptr) { - static int seq_id; char buf[MAX_PAYLOAD_LEN]; +#ifdef SERVER_REPLY + uint8_t num_used = 0; + uip_ds6_nbr_t *nbr; + + nbr = nbr_table_head(ds6_neighbors); + while(nbr != NULL) { + nbr = nbr_table_next(ds6_neighbors, nbr); + num_used++; + } + + if(seq_id > 0) { + ANNOTATE("#A r=%d/%d,color=%s,n=%d %d\n", reply, seq_id, + reply == seq_id ? "GREEN" : "RED", uip_ds6_route_num_routes(), num_used); + } +#endif /* SERVER_REPLY */ + seq_id++; PRINTF("DATA send to %d 'Hello %d'\n", server_ipaddr.u8[sizeof(server_ipaddr.u8) - 1], seq_id); @@ -116,7 +140,7 @@ set_global_address(void) { uip_ipaddr_t ipaddr; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); @@ -125,21 +149,21 @@ set_global_address(void) * Obviously the choice made here must also be selected in udp-server.c. * * For correct Wireshark decoding using a sniffer, add the /64 prefix to the 6LowPAN protocol preferences, - * e.g. set Context 0 to aaaa::. At present Wireshark copies Context/128 and then overwrites it. - * (Setting Context 0 to aaaa::1111:2222:3333:4444 will report a 16 bit compressed address of aaaa::1111:22ff:fe33:xxxx) + * e.g. set Context 0 to fd00::. At present Wireshark copies Context/128 and then overwrites it. + * (Setting Context 0 to fd00::1111:2222:3333:4444 will report a 16 bit compressed address of fd00::1111:22ff:fe33:xxxx) * * Note the IPCMV6 checksum verification depends on the correct uncompressed addresses. */ #if 0 /* Mode 1 - 64 bits inline */ - uip_ip6addr(&server_ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 1); + uip_ip6addr(&server_ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 1); #elif 1 /* Mode 2 - 16 bits inline */ - uip_ip6addr(&server_ipaddr, 0xaaaa, 0, 0, 0, 0, 0x00ff, 0xfe00, 1); + uip_ip6addr(&server_ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0x00ff, 0xfe00, 1); #else /* Mode 3 - derived from server link-local (MAC) address */ - uip_ip6addr(&server_ipaddr, 0xaaaa, 0, 0, 0, 0x0250, 0xc2ff, 0xfea8, 0xcd1a); //redbee-econotag + uip_ip6addr(&server_ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0x0250, 0xc2ff, 0xfea8, 0xcd1a); //redbee-econotag #endif } /*---------------------------------------------------------------------------*/ @@ -156,8 +180,9 @@ PROCESS_THREAD(udp_client_process, ev, data) PROCESS_PAUSE(); set_global_address(); - - PRINTF("UDP client process started\n"); + + PRINTF("UDP client process started nbr:%d routes:%d\n", + NBR_TABLE_CONF_MAX_NEIGHBORS, UIP_CONF_MAX_ROUTES); print_local_addresses(); @@ -174,6 +199,11 @@ PROCESS_THREAD(udp_client_process, ev, data) PRINTF(" local/remote port %u/%u\n", UIP_HTONS(client_conn->lport), UIP_HTONS(client_conn->rport)); + /* initialize serial line */ + uart1_set_input(serial_line_input_byte); + serial_line_init(); + + #if WITH_COMPOWER powertrace_sniff(POWERTRACE_ON); #endif @@ -184,7 +214,41 @@ PROCESS_THREAD(udp_client_process, ev, data) if(ev == tcpip_event) { tcpip_handler(); } - + + if(ev == serial_line_event_message && data != NULL) { + char *str; + str = data; + if(str[0] == 'r') { + uip_ds6_route_t *r; + uip_ipaddr_t *nexthop; + uip_ds6_defrt_t *defrt; + uip_ipaddr_t *ipaddr; + defrt = NULL; + if((ipaddr = uip_ds6_defrt_choose()) != NULL) { + defrt = uip_ds6_defrt_lookup(ipaddr); + } + if(defrt != NULL) { + PRINTF("DefRT: :: -> %02d", defrt->ipaddr.u8[15]); + PRINTF(" lt:%lu inf:%d\n", stimer_remaining(&defrt->lifetime), + defrt->isinfinite); + } else { + PRINTF("DefRT: :: -> NULL\n"); + } + + for(r = uip_ds6_route_head(); + r != NULL; + r = uip_ds6_route_next(r)) { + nexthop = uip_ds6_route_nexthop(r); + PRINTF("Route: %02d -> %02d", r->ipaddr.u8[15], nexthop->u8[15]); + /* PRINT6ADDR(&r->ipaddr); */ + /* PRINTF(" -> "); */ + /* PRINT6ADDR(nexthop); */ + PRINTF(" lt:%lu\n", r->state.lifetime); + + } + } + } + if(etimer_expired(&periodic)) { etimer_reset(&periodic); ctimer_set(&backoff_timer, SEND_TIME, send_packet, NULL); diff --git a/examples/ipv6/rpl-udp/udp-server.c b/examples/ipv6/rpl-udp/udp-server.c index b735d3bb2..ce87d3b8f 100644 --- a/examples/ipv6/rpl-udp/udp-server.c +++ b/examples/ipv6/rpl-udp/udp-server.c @@ -107,27 +107,28 @@ PROCESS_THREAD(udp_server_process, ev, data) SENSORS_ACTIVATE(button_sensor); - PRINTF("UDP server started\n"); + PRINTF("UDP server started. nbr:%d routes:%d\n", + NBR_TABLE_CONF_MAX_NEIGHBORS, UIP_CONF_MAX_ROUTES); #if UIP_CONF_ROUTER /* The choice of server address determines its 6LoPAN header compression. * Obviously the choice made here must also be selected in udp-client.c. * * For correct Wireshark decoding using a sniffer, add the /64 prefix to the 6LowPAN protocol preferences, - * e.g. set Context 0 to aaaa::. At present Wireshark copies Context/128 and then overwrites it. - * (Setting Context 0 to aaaa::1111:2222:3333:4444 will report a 16 bit compressed address of aaaa::1111:22ff:fe33:xxxx) + * e.g. set Context 0 to fd00::. At present Wireshark copies Context/128 and then overwrites it. + * (Setting Context 0 to fd00::1111:2222:3333:4444 will report a 16 bit compressed address of fd00::1111:22ff:fe33:xxxx) * Note Wireshark's IPCMV6 checksum verification depends on the correct uncompressed addresses. */ #if 0 /* Mode 1 - 64 bits inline */ - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 1); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 1); #elif 1 /* Mode 2 - 16 bits inline */ - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0x00ff, 0xfe00, 1); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0x00ff, 0xfe00, 1); #else /* Mode 3 - derived from link local (MAC) address */ - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); #endif @@ -136,7 +137,7 @@ PROCESS_THREAD(udp_server_process, ev, data) if(root_if != NULL) { rpl_dag_t *dag; dag = rpl_set_root(RPL_DEFAULT_INSTANCE,(uip_ip6addr_t *)&ipaddr); - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &ipaddr, 64); PRINTF("created a new RPL dag\n"); } else { diff --git a/examples/ipv6/simple-udp-rpl/unicast-receiver.c b/examples/ipv6/simple-udp-rpl/unicast-receiver.c index 1100886b4..7c6205dab 100644 --- a/examples/ipv6/simple-udp-rpl/unicast-receiver.c +++ b/examples/ipv6/simple-udp-rpl/unicast-receiver.c @@ -80,7 +80,7 @@ set_global_address(void) int i; uint8_t state; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); @@ -109,7 +109,7 @@ create_rpl_dag(uip_ipaddr_t *ipaddr) rpl_set_root(RPL_DEFAULT_INSTANCE, ipaddr); dag = rpl_get_any_dag(); - uip_ip6addr(&prefix, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &prefix, 64); PRINTF("created a new RPL dag\n"); } else { diff --git a/examples/ipv6/simple-udp-rpl/unicast-sender.c b/examples/ipv6/simple-udp-rpl/unicast-sender.c index 60cb91204..f441ec728 100644 --- a/examples/ipv6/simple-udp-rpl/unicast-sender.c +++ b/examples/ipv6/simple-udp-rpl/unicast-sender.c @@ -78,7 +78,7 @@ set_global_address(void) int i; uint8_t state; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); diff --git a/examples/ipv6/sky-websense/Makefile b/examples/ipv6/sky-websense/Makefile index 17385c016..7096128a4 100644 --- a/examples/ipv6/sky-websense/Makefile +++ b/examples/ipv6/sky-websense/Makefile @@ -16,7 +16,7 @@ $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) connect-router: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64 + sudo $(CONTIKI)/tools/tunslip6 fd00::1/64 connect-router-cooja: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 aaaa::1/64 + sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 fd00::1/64 diff --git a/examples/ipv6/sky-websense/README.md b/examples/ipv6/sky-websense/README.md index 64e566b17..ab644f887 100644 --- a/examples/ipv6/sky-websense/README.md +++ b/examples/ipv6/sky-websense/README.md @@ -17,8 +17,8 @@ To test the example in COOJA under Linux make connect-router-cooja 3. You should now be able to browse to the nodes using your web browser: - Router: http://[aaaa::0212:7401:0001:0101]/ - Node 2: http://[aaaa::0212:7402:0002:0202]/ + Router: http://[fd00::0212:7401:0001:0101]/ + Node 2: http://[fd00::0212:7402:0002:0202]/ To run the example on real nodes under Linux diff --git a/examples/ipv6/sky-websense/websense-remote.c b/examples/ipv6/sky-websense/websense-remote.c index 75737b484..76fc7d0a7 100644 --- a/examples/ipv6/sky-websense/websense-remote.c +++ b/examples/ipv6/sky-websense/websense-remote.c @@ -44,13 +44,13 @@ #include /* The address of the server to register the services for this node */ -#define SERVER "[aaaa::1]" +#define SERVER "[fd00::1]" /* This command registers two services (/0 and /1) to turn the leds on or off */ #define REGISTER_COMMAND "/r?p=0&d=Turn%20off%20leds&p=1&d=Turn%20on%20leds" /* The address of the other node to control */ -#define OTHER_NODE "[aaaa::1]" +#define OTHER_NODE "[fd00::1]" /* The commands to send to the other node */ #define SET_LEDS_ON "/1" diff --git a/examples/jn516x/rpl/README.md b/examples/jn516x/rpl/README.md index 39a213268..fb8cd49b4 100644 --- a/examples/jn516x/rpl/README.md +++ b/examples/jn516x/rpl/README.md @@ -28,7 +28,7 @@ From a Linux terminal, go to `contiki/examples/jn516x/rpl/border-router` and do or `make connect-router-sw` if you have **SW flow control** This will start a tunnel interface (tun0) on the host machine. -All traffic towards our network (prefix aaaa::1/64) will now be routed to the border router. +All traffic towards our network (prefix fd00::1/64) will now be routed to the border router. ## RPL Node diff --git a/examples/jn516x/rpl/border-router/Makefile b/examples/jn516x/rpl/border-router/Makefile index de68ecde8..1904e5ce8 100644 --- a/examples/jn516x/rpl/border-router/Makefile +++ b/examples/jn516x/rpl/border-router/Makefile @@ -14,7 +14,7 @@ CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" PROJECT_SOURCEFILES += slip-bridge.c slip.c ifeq ($(PREFIX),) - PREFIX = aaaa::1/64 + PREFIX = fd00::1/64 endif include $(CONTIKI)/Makefile.include diff --git a/examples/jn516x/rpl/coap-dongle-node/dongle-node.c b/examples/jn516x/rpl/coap-dongle-node/dongle-node.c index ab5845dff..233834610 100644 --- a/examples/jn516x/rpl/coap-dongle-node/dongle-node.c +++ b/examples/jn516x/rpl/coap-dongle-node/dongle-node.c @@ -33,6 +33,7 @@ */ #include "contiki.h" #include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" #include "tools/rpl-tools.h" #include "rest-engine.h" #include "sys/ctimer.h" @@ -130,7 +131,7 @@ PROCESS_THREAD(start_app, ev, data) /* Start net stack */ if(is_coordinator) { uip_ipaddr_t prefix; - uip_ip6addr(&prefix, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_tools_init(&prefix); } else { rpl_tools_init(NULL); diff --git a/examples/jn516x/rpl/coap-dr1175-node/dr1175-node.c b/examples/jn516x/rpl/coap-dr1175-node/dr1175-node.c index f377dc3b3..641f3eca5 100644 --- a/examples/jn516x/rpl/coap-dr1175-node/dr1175-node.c +++ b/examples/jn516x/rpl/coap-dr1175-node/dr1175-node.c @@ -34,6 +34,7 @@ #include "contiki.h" #include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" #include "tools/rpl-tools.h" #include "rest-engine.h" #include "light-sensor.h" @@ -350,7 +351,7 @@ PROCESS_THREAD(start_app, ev, data) /* Start net stack */ if(is_coordinator) { uip_ipaddr_t prefix; - uip_ip6addr(&prefix, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_tools_init(&prefix); } else { rpl_tools_init(NULL); diff --git a/examples/jn516x/rpl/coap-dr1199-node/dr1199-node.c b/examples/jn516x/rpl/coap-dr1199-node/dr1199-node.c index 373922e58..933b247d6 100644 --- a/examples/jn516x/rpl/coap-dr1199-node/dr1199-node.c +++ b/examples/jn516x/rpl/coap-dr1199-node/dr1199-node.c @@ -33,6 +33,7 @@ */ #include "contiki.h" #include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" #include "tools/rpl-tools.h" #include "rest-engine.h" #include "dev/leds.h" @@ -351,7 +352,7 @@ PROCESS_THREAD(start_app, ev, data) /* Start net stack */ if(is_coordinator) { uip_ipaddr_t prefix; - uip_ip6addr(&prefix, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_tools_init(&prefix); } else { rpl_tools_init(NULL); diff --git a/examples/jn516x/rpl/node/node.c b/examples/jn516x/rpl/node/node.c index 59b812357..b6a6f3096 100644 --- a/examples/jn516x/rpl/node/node.c +++ b/examples/jn516x/rpl/node/node.c @@ -36,6 +36,7 @@ */ #include "contiki.h" +#include "net/ipv6/uip-ds6.h" #include "net/rpl/rpl.h" #include "tools/rpl-tools.h" @@ -98,7 +99,7 @@ PROCESS_THREAD(node_process, ev, data) if(is_coordinator) { uip_ipaddr_t prefix; - uip_ip6addr(&prefix, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_tools_init(&prefix); } else { rpl_tools_init(NULL); diff --git a/examples/jn516x/tsch/common-conf.h b/examples/jn516x/tsch/common-conf.h index b42e6c810..91037c794 100644 --- a/examples/jn516x/tsch/common-conf.h +++ b/examples/jn516x/tsch/common-conf.h @@ -142,7 +142,7 @@ #if WITH_TSCH_SECURITY /* Set security level to the maximum, even if unused, to all crypto code */ -#define LLSEC802154_CONF_SECURITY_LEVEL 7 +#define LLSEC802154_CONF_ENABLED 1 /* Attempt to associate from both secured and non-secured EBs */ #define TSCH_CONF_JOIN_SECURED_ONLY 0 /* We need explicit keys to identify k1 and k2 */ diff --git a/examples/jn516x/tsch/simple-sensor-network/node/node.c b/examples/jn516x/tsch/simple-sensor-network/node/node.c index 48b7c4ff5..561df6a47 100644 --- a/examples/jn516x/tsch/simple-sensor-network/node/node.c +++ b/examples/jn516x/tsch/simple-sensor-network/node/node.c @@ -152,7 +152,7 @@ PROCESS_THREAD(node_process, ev, data) /* Set node with ID == 1 as coordinator, handy in Cooja. */ if(node_id == 1) { - if(LLSEC802154_CONF_SECURITY_LEVEL) { + if(LLSEC802154_ENABLED) { node_role = role_6dr_sec; } else { node_role = role_6dr; @@ -165,7 +165,7 @@ PROCESS_THREAD(node_process, ev, data) node_role == role_6ln ? "6ln" : (node_role == role_6dr) ? "6dr" : "6dr-sec"); #if WITH_TSCH - tsch_set_pan_secured(LLSEC802154_CONF_SECURITY_LEVEL && (node_role == role_6dr_sec)); + tsch_set_pan_secured(LLSEC802154_ENABLED && (node_role == role_6dr_sec)); #endif /* WITH_TSCH */ is_coordinator = node_role > role_6ln; diff --git a/examples/jn516x/tsch/tx-power-verification/node/node.c b/examples/jn516x/tsch/tx-power-verification/node/node.c index 1e77d3a2e..85b19fa10 100644 --- a/examples/jn516x/tsch/tx-power-verification/node/node.c +++ b/examples/jn516x/tsch/tx-power-verification/node/node.c @@ -32,6 +32,7 @@ * */ #include "contiki.h" +#include "net/ipv6/uip-ds6.h" #include "net/netstack.h" #include "net/ip/uip.h" #include "net/linkaddr.h" @@ -105,7 +106,7 @@ PROCESS_THREAD(start_app, ev, data) /* Start network stack */ if(is_coordinator) { uip_ipaddr_t prefix; - uip_ip6addr(&prefix, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_tools_init(&prefix); } else { rpl_tools_init(NULL); diff --git a/examples/jn516x/tsch/uart1-test-node/uart1-test-node.c b/examples/jn516x/tsch/uart1-test-node/uart1-test-node.c index 0a4259f95..4accd3dc4 100644 --- a/examples/jn516x/tsch/uart1-test-node/uart1-test-node.c +++ b/examples/jn516x/tsch/uart1-test-node/uart1-test-node.c @@ -31,6 +31,8 @@ * Author: Theo van Daele * */ +#include "contiki.h" +#include "net/ipv6/uip-ds6.h" #include "net/ip/uip.h" #include "net/linkaddr.h" #include "rpl-tools.h" @@ -145,7 +147,7 @@ PROCESS_THREAD(start_app, ev, data) /* Start network stack */ if(is_coordinator) { uip_ipaddr_t prefix; - uip_ip6addr(&prefix, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_tools_init(&prefix); } else { rpl_tools_init(NULL); diff --git a/examples/llsec/ccm-star-tests/encryption/project-conf.h b/examples/llsec/ccm-star-tests/encryption/project-conf.h index 613619373..55e4e35d4 100644 --- a/examples/llsec/ccm-star-tests/encryption/project-conf.h +++ b/examples/llsec/ccm-star-tests/encryption/project-conf.h @@ -37,4 +37,4 @@ * Konrad Krentz */ -#define LLSEC802154_CONF_SECURITY_LEVEL 6 +#define LLSEC802154_CONF_ENABLED 1 diff --git a/examples/llsec/ccm-star-tests/encryption/tests.c b/examples/llsec/ccm-star-tests/encryption/tests.c index b5c296799..0ef158960 100644 --- a/examples/llsec/ccm-star-tests/encryption/tests.c +++ b/examples/llsec/ccm-star-tests/encryption/tests.c @@ -47,6 +47,9 @@ #include #include +#define SEC_LVL 6 +#define MIC_LEN LLSEC802154_MIC_LEN(6) + /*---------------------------------------------------------------------------*/ /* Test vector C.2.1.2 from IEEE 802.15.4-2006 */ static void @@ -70,8 +73,8 @@ test_sec_lvl_6() /* Frame Counter */ 0x05 , 0x00 , 0x00 , 0x00 , 0x01 , 0xCE }; - uint8_t oracle[LLSEC802154_MIC_LENGTH] = { 0x4F , 0xDE , 0x52 , 0x90 , - 0x61 , 0xF9 , 0xC6 , 0xF1 }; + uint8_t oracle[MIC_LEN] = { 0x4F , 0xDE , 0x52 , 0x90 , + 0x61 , 0xF9 , 0xC6 , 0xF1 }; uint8_t nonce[13]; frame802154_frame_counter_t counter; @@ -84,7 +87,7 @@ test_sec_lvl_6() counter.u32 = 5; packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, counter.u16[0]); packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, counter.u16[1]); - packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, LLSEC802154_SECURITY_LEVEL); + packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, SEC_LVL); packetbuf_hdrreduce(29); CCM_STAR.set_key(key); @@ -92,10 +95,10 @@ test_sec_lvl_6() CCM_STAR.aead(nonce, packetbuf_dataptr(), packetbuf_datalen(), packetbuf_hdrptr(), packetbuf_hdrlen(), - ((uint8_t *) packetbuf_hdrptr()) + 30, LLSEC802154_MIC_LENGTH, + ((uint8_t *) packetbuf_hdrptr()) + 30, MIC_LEN, 1); - if(memcmp(((uint8_t *) packetbuf_hdrptr()) + 30, oracle, LLSEC802154_MIC_LENGTH) == 0) { + if(memcmp(((uint8_t *) packetbuf_hdrptr()) + 30, oracle, MIC_LEN) == 0) { printf("Success\n"); } else { printf("Failure\n"); @@ -115,7 +118,7 @@ test_sec_lvl_6() CCM_STAR.aead(nonce, packetbuf_dataptr(), packetbuf_datalen(), packetbuf_hdrptr(), packetbuf_hdrlen(), - ((uint8_t *) packetbuf_hdrptr()) + 30, LLSEC802154_MIC_LENGTH, + ((uint8_t *) packetbuf_hdrptr()) + 30, MIC_LEN, 0); if(((uint8_t *) packetbuf_hdrptr())[29] == 0xCE) { printf("Success\n"); diff --git a/examples/llsec/ccm-star-tests/verification/project-conf.h b/examples/llsec/ccm-star-tests/verification/project-conf.h index 9f8776b90..3d7e42488 100644 --- a/examples/llsec/ccm-star-tests/verification/project-conf.h +++ b/examples/llsec/ccm-star-tests/verification/project-conf.h @@ -37,4 +37,4 @@ * Konrad Krentz */ -#define LLSEC802154_CONF_SECURITY_LEVEL 2 +#define LLSEC802154_CONF_ENABLED 1 diff --git a/examples/llsec/ccm-star-tests/verification/tests.c b/examples/llsec/ccm-star-tests/verification/tests.c index 4de463fee..3c981552d 100644 --- a/examples/llsec/ccm-star-tests/verification/tests.c +++ b/examples/llsec/ccm-star-tests/verification/tests.c @@ -48,6 +48,9 @@ #include #include +#define SEC_LVL 2 +#define MIC_LEN LLSEC802154_MIC_LEN(2) + /*---------------------------------------------------------------------------*/ /* Test vector C.1 from FIPS Pub 197 */ static void @@ -97,10 +100,10 @@ test_sec_lvl_2() 0x05 , 0x00 , 0x00 , 0x00 , /* Payload */ 0x55 , 0xCF , 0x00 , 0x00 , 0x51 , 0x52 , 0x53 , 0x54 }; - uint8_t oracle[LLSEC802154_MIC_LENGTH] = { 0x22 , 0x3B , 0xC1 , 0xEC , - 0x84 , 0x1A , 0xB5 , 0x53 }; + uint8_t oracle[MIC_LEN] = { 0x22 , 0x3B , 0xC1 , 0xEC , + 0x84 , 0x1A , 0xB5 , 0x53 }; frame802154_frame_counter_t counter; - uint8_t mic[LLSEC802154_MIC_LENGTH]; + uint8_t mic[MIC_LEN]; uint8_t nonce[13]; printf("Testing verification ... "); @@ -112,7 +115,7 @@ test_sec_lvl_2() counter.u32 = 5; packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, counter.u16[0]); packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, counter.u16[1]); - packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, LLSEC802154_SECURITY_LEVEL); + packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, SEC_LVL); packetbuf_hdrreduce(18); CCM_STAR.set_key(key); @@ -120,10 +123,10 @@ test_sec_lvl_2() CCM_STAR.aead(nonce, NULL, 0, packetbuf_hdrptr(), packetbuf_totlen(), - ((uint8_t *) packetbuf_dataptr()) + packetbuf_datalen(), LLSEC802154_MIC_LENGTH, + ((uint8_t *) packetbuf_dataptr()) + packetbuf_datalen(), MIC_LEN, 1); - if(memcmp(((uint8_t *) packetbuf_dataptr()) + packetbuf_datalen(), oracle, LLSEC802154_MIC_LENGTH) == 0) { + if(memcmp(((uint8_t *) packetbuf_dataptr()) + packetbuf_datalen(), oracle, MIC_LEN) == 0) { printf("Success\n"); } else { printf("Failure\n"); diff --git a/examples/mbxxx/mbxxx-websense/Makefile b/examples/mbxxx/mbxxx-websense/Makefile index 6239a7043..accb4e412 100644 --- a/examples/mbxxx/mbxxx-websense/Makefile +++ b/examples/mbxxx/mbxxx-websense/Makefile @@ -16,7 +16,7 @@ $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) connect-router: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64 + sudo $(CONTIKI)/tools/tunslip6 fd00::1/64 connect-router-cooja: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 aaaa::1/64 + sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 fd00::1/64 diff --git a/examples/mbxxx/udp-ipv6-sleep/udp-client.c b/examples/mbxxx/udp-ipv6-sleep/udp-client.c index 4408a2c19..3c6f7934d 100644 --- a/examples/mbxxx/udp-ipv6-sleep/udp-client.c +++ b/examples/mbxxx/udp-ipv6-sleep/udp-client.c @@ -107,7 +107,7 @@ set_global_address(void) { uip_ipaddr_t ipaddr; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); } @@ -123,7 +123,7 @@ set_connection_address(uip_ipaddr_t *ipaddr) PRINTF("UDP client failed to parse address '%s'\n", QUOTEME(UDP_CONNECTION_ADDR)); } #elif UIP_CONF_ROUTER - uip_ip6addr(ipaddr,0xaaaa,0,0,0,0x0280,0xe102,0x0000,0x008a); + uip_ip6addr(ipaddr,UIP_DS6_DEFAULT_PREFIX,0,0,0,0x0280,0xe102,0x0000,0x008a); #else uip_ip6addr(ipaddr,0xfe80,0,0,0,0x0280,0xe102,0x0000,0x008a); #endif /* UDP_CONNECTION_ADDR */ diff --git a/examples/mbxxx/udp-ipv6-sleep/udp-server.c b/examples/mbxxx/udp-ipv6-sleep/udp-server.c index 68fc1915c..78c6f9d3a 100644 --- a/examples/mbxxx/udp-ipv6-sleep/udp-server.c +++ b/examples/mbxxx/udp-ipv6-sleep/udp-server.c @@ -95,7 +95,7 @@ PROCESS_THREAD(udp_server_process, ev, data) PRINTF("UDP server started\n"); #if UIP_CONF_ROUTER - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); #endif /* UIP_CONF_ROUTER */ diff --git a/examples/nrf52dk/blink-hello/Makefile b/examples/nrf52dk/blink-hello/Makefile new file mode 100644 index 000000000..5b056a518 --- /dev/null +++ b/examples/nrf52dk/blink-hello/Makefile @@ -0,0 +1,9 @@ +CONTIKI_PROJECT = blink-hello + +CONTIKI_WITH_RPL=0 +NRF52_WITHOUT_SOFTDEVICE=1 + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/nrf52dk/blink-hello/README.md b/examples/nrf52dk/blink-hello/README.md new file mode 100644 index 000000000..00064f993 --- /dev/null +++ b/examples/nrf52dk/blink-hello/README.md @@ -0,0 +1,14 @@ +Blink Hello example +=================== +This example shows basic usage of DK's buttons and LEDs. It also shows basic +usage of Contiki's processes. The application autostarts 5 processes: 4 processes +for button and LED control and 1 to display current temperature to the console. + +A process reacts to a press of a respective button (process 1 reacts to button 1, etc.) +and doubles the current blinking frequency. The cycle restarts for beginning when blinking +frequency is greater than 8Hz. + +The example requires one DK and it doesn't use SoftDevice. To compile and flash the +example run: + + make TARGET=nrf52dk blink-hello.flash \ No newline at end of file diff --git a/examples/nrf52dk/blink-hello/blink-hello.c b/examples/nrf52dk/blink-hello/blink-hello.c new file mode 100644 index 000000000..ebc1e451c --- /dev/null +++ b/examples/nrf52dk/blink-hello/blink-hello.c @@ -0,0 +1,182 @@ +/* This is a very simple hello_world program. + * It aims to demonstrate the co-existence of two processes: + * One of them prints a hello world message and the other blinks the LEDs + * + * It is largely based on hello_world in $(CONTIKI)/examples/sensinode + * + * Author: George Oikonomou - + */ + +/** + * \addtogroup nrf52dk nRF52 Development Kit + * @{ + * + * \addtogroup nrf52dk-examples Demo projects for nRF52 DK + * @{ + * + * \defgroup nrf52dk-blink-hello Basic sensors and LEDs demo + * @{ + * + * This demo demonstrates use of Contiki processes, sensors, and LEDs + * on nRF52 DK. Pressing a button will start a timer that blinks a + * respective LED (e.g., button 1 controls LED 1). Each time the button + * is pressed blinking frequency is doubled. On 4th press the LED is + * switched off and the sequence can be started from the beginning. + * + * \file Main file for Basic sensors and LEDs demo. + */ +#include /* For printf() */ +#include +#include "contiki.h" +#include "dev/leds.h" +#include "dev/temperature-sensor.h" +#include "lib/sensors.h" +#include "button-sensor.h" + +/*---------------------------------------------------------------------------*/ +PROCESS(blink_process_1, "LED1 blink process"); +PROCESS(blink_process_2, "LED2 blink process"); +PROCESS(blink_process_3, "LED3 blink process"); +PROCESS(blink_process_4, "LED4 blink process"); +PROCESS(temp, "Temperautre"); + +AUTOSTART_PROCESSES( + &blink_process_1, + &blink_process_2, + &blink_process_3, + &blink_process_4, + &temp +); + +struct blink_process_ctx { + struct etimer et_blink; + unsigned char c; + const struct sensors_sensor *button; + unsigned char led; +}; + +static void handle_event(process_event_t ev, process_data_t data, struct blink_process_ctx *ctx) +{ + if (ev == PROCESS_EVENT_TIMER && etimer_expired(&ctx->et_blink)) { + leds_toggle(ctx->led); + etimer_set(&ctx->et_blink, CLOCK_SECOND / ctx->c); + printf("Blink %d\n", ctx->led); + } else if (ev == sensors_event && data == ctx->button) { + if (ctx->button->value(BUTTON_SENSOR_VALUE_STATE) == 0) { + if (ctx->c == 0) { + ctx->c = 1; + } else if (ctx->c < 8){ + ctx->c <<= 1; + } else { + ctx->c = 0; + leds_off(ctx->led); + } + if (ctx->c) { + etimer_set(&ctx->et_blink, CLOCK_SECOND / ctx->c); + } else { + etimer_stop(&ctx->et_blink); + } + } + } +} + +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(blink_process_1, ev, data) +{ + static struct blink_process_ctx ctx; + + PROCESS_BEGIN(); + + ctx.button = &button_1; + ctx.c = 0; + ctx.led = LEDS_1; + ctx.button->configure(SENSORS_ACTIVE, 1); + + while (1) { + PROCESS_WAIT_EVENT(); + handle_event(ev, data, &ctx); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(blink_process_2, ev, data) +{ + static struct blink_process_ctx ctx; + + PROCESS_BEGIN(); + + ctx.button = &button_2; + ctx.c = 0; + ctx.led = LEDS_2; + ctx.button->configure(SENSORS_ACTIVE, 1); + + while (1) { + PROCESS_WAIT_EVENT(); + handle_event(ev, data, &ctx); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(blink_process_3, ev, data) +{ + static struct blink_process_ctx ctx; + + PROCESS_BEGIN(); + + ctx.button = &button_3; + ctx.c = 0; + ctx.led = LEDS_3; + ctx.button->configure(SENSORS_ACTIVE, 1); + + while (1) { + PROCESS_WAIT_EVENT(); + handle_event(ev, data, &ctx); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(blink_process_4, ev, data) +{ + static struct blink_process_ctx ctx; + + PROCESS_BEGIN(); + + ctx.button = &button_4; + ctx.c = 0; + ctx.led = LEDS_4; + ctx.button->configure(SENSORS_ACTIVE, 1); + + while (1) { + PROCESS_WAIT_EVENT(); + handle_event(ev, data, &ctx); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(temp, ev, data) +{ + static struct etimer tick; + PROCESS_BEGIN(); + + etimer_set(&tick, CLOCK_SECOND); + + while (1) { + PROCESS_WAIT_EVENT(); + if (ev == PROCESS_EVENT_TIMER && etimer_expired(&tick)) { + int32_t temp = temperature_sensor.value(0); + printf("temp: %"PRId32".%02"PRId32"\n", temp >> 2, (temp & 0x03)*25); + etimer_reset(&tick); + } + } + + PROCESS_END(); +} +/** + * @} + * @} + * @} + */ diff --git a/examples/nrf52dk/coap-demo/Makefile b/examples/nrf52dk/coap-demo/Makefile new file mode 100644 index 000000000..077e469be --- /dev/null +++ b/examples/nrf52dk/coap-demo/Makefile @@ -0,0 +1,35 @@ +CONTIKI=../../.. +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" + +ifeq ($(MAKECMDGOALS),) +$(error Please specify whether coap-client or coap-server should be built) +endif + +ifneq ($(filter coap-client coap-client.flash, $(MAKECMDGOALS)),) +ifeq ($(SERVER_IPV6_ADDR),) +$(error Please define SERVER_IPV6_ADDR=) +else +CFLAGS += -DSERVER_IPV6_ADDR=\"$(SERVER_IPV6_ADDR)\" +CFLAGS += -DDEVICE_NAME=\"nRF52_DK_CoAP_Client\" +endif +else +CFLAGS += -DDEVICE_NAME=\"nRF52-DK-CoAP-Server\" +endif + +# automatically build RESTful resources +REST_RESOURCES_DIR = ./resources +REST_RESOURCES_FILES = $(notdir $(shell find $(REST_RESOURCES_DIR) -name '*.c' ! -name 'res-plugtest*')) + +PROJECTDIRS += $(REST_RESOURCES_DIR) +PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) + +# linker optimizations +SMALL=1 + +# REST Engine shall use Erbium CoAP implementation +APPS += er-coap +APPS += rest-engine + +CONTIKI_WITH_RPL = 0 + +include $(CONTIKI)/Makefile.include diff --git a/examples/nrf52dk/coap-demo/README.md b/examples/nrf52dk/coap-demo/README.md new file mode 100644 index 000000000..1262ce114 --- /dev/null +++ b/examples/nrf52dk/coap-demo/README.md @@ -0,0 +1,63 @@ +A CoAP demo for nRF52 DK +======================== +This demo contains two applications: coap-server and coap-client which are similar to +[Coap Observable Server] and [Coap Observer Client] examples provided by the nRF5 IoT SDK. + +Note that before any CoAP requests can be made you'll need to configure an IPv6 connection +to the device and assign a routable IPv6 address. + +For details how to do this please refer to sections 'Establishing an IPv6 connection' +and 'Distributing routable IPv6 prefix' in `platform/nrf52dk/README-BLE-6LoWPAN.md`. + +CoAP Server +=========== +The server exposes the following resources: + + host + |-- .well-known + | `-- core + `-- lights + `-- led3 + +The state of LED 3 can be set and queried via CoAP through the observable resource `lights/led3`. Current +state of LED 3 is returned as a text string in the payload. The value 0 means that LED 3 is off, 1 otherwise. + +Button 1 can be used to toggle state of the LED 3. This will cause a notification to be sent to +any subscriber observing `lights/led3`. The state of the resource can also be changed by using POST/PUT to +the resource with desired state encoded as a text in the payload. Send 1 to switch on and 0 to switch off. + +In order to compile and flash the CoAP server to a DK execute: + + make TARGET=nrf52dk coap-server.flash + +Note, if you haven't previously used a given device with Contiki it is recommended +to erase the device and flash SoftDevice before flashing CoAP application, i.e., + + make TARGET=nrf52dk erase + make TARGET=nrf52dk softdevice.flash + +Please refer to the *Testing* and *Python Example* sections of [Coap Observable Server] tutorial for detailed description how to query the Coap Server using a PC. + +CoAP Client +=========== +CoAP client compliments the CoAP server application. When Button 1 on the DK is pressed the the +client subscribes to `lights/led3` resource. If successful the LED 4 will blink briefly. From this moment +any change of the `lights/led3` resource will be automatically reflected by the client's LED 3. + +Note that the client must know the server's IPv6 address. The address is specified as a make variable +during compliation. + +In order to compile and flash the CoAP client to DK execute: + + make TARGET=nrf52dk SERVER_IPV6_ADDR= coap-client.flash + +Note, that you can use `NRF52_JLINK_SN=` to select a particular devkit in a case when +you have more than one boards connected to PC. Please refer to `platform/README.md` for +details. + +Please refer to the *Testing* and *Python Server Example* sections of [Coap Observer Client] tutorial for detailed description how to use CoAP client demo with a PC. + +Resources +========= +[Coap Observable Server] http://developer.nordicsemi.com/nRF5_IoT_SDK/doc/0.9.0/html/a00054.html +[Coap Observer Client] http://developer.nordicsemi.com/nRF5_IoT_SDK/doc/0.9.0/html/a00051.html diff --git a/examples/nrf52dk/coap-demo/coap-client.c b/examples/nrf52dk/coap-demo/coap-client.c new file mode 100644 index 000000000..2ec1f5ab1 --- /dev/null +++ b/examples/nrf52dk/coap-demo/coap-client.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2014, Daniele Alessandrelli. + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \addtogroup nrf52dk-examples Demo projects for nRF52 DK + * @{ + * + * \defgroup nrf52dk-coap-demo CoAP demo for nRF52 DK + * @{ + * + * \file + * Erbium (Er) CoAP observe client example. + * \author + * Daniele Alessandrelli + * \author + * Wojciech Bober + */ + +#include +#include +#include +#include "contiki.h" +#include "contiki-net.h" +#include "er-coap-engine.h" +#include "dev/button-sensor.h" +#include "dev/leds.h" + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/*----------------------------------------------------------------------------*/ +#define REMOTE_PORT UIP_HTONS(COAP_DEFAULT_PORT) +#define OBS_RESOURCE_URI "lights/led3" +#define SUBS_LED LEDS_4 +#define OBS_LED LEDS_3 + +/*----------------------------------------------------------------------------*/ +static uip_ipaddr_t server_ipaddr[1]; /* holds the server ip address */ +static coap_observee_t *obs; +static struct ctimer ct; +/*----------------------------------------------------------------------------*/ +PROCESS(er_example_observe_client, "nRF52 DK Coap Observer Client"); +AUTOSTART_PROCESSES(&er_example_observe_client); +/*----------------------------------------------------------------------------*/ +static void +observe_led_off(void *d) +{ + leds_off(SUBS_LED); +} +/*----------------------------------------------------------------------------*/ +/* + * Handle the response to the observe request and the following notifications + */ +static void +notification_callback(coap_observee_t *obs, void *notification, + coap_notification_flag_t flag) +{ + int len = 0; + const uint8_t *payload = NULL; + + + PRINTF("Notification handler\n"); + PRINTF("Observee URI: %s\n", obs->url); + + if (notification) { + len = coap_get_payload(notification, &payload); + } + + (void)len; + + switch (flag) { + case NOTIFICATION_OK: + PRINTF("NOTIFICATION OK: %*s\n", len, (char *)payload); + if (*payload == '1') { + leds_on(OBS_LED); + } else { + leds_off(OBS_LED); + } + break; + case OBSERVE_OK: /* server accepeted observation request */ + PRINTF("OBSERVE_OK: %*s\n", len, (char *)payload); + if (*payload == '1') { + leds_on(OBS_LED); + } else { + leds_off(OBS_LED); + } + leds_on(SUBS_LED); + ctimer_set(&ct, CLOCK_SECOND, observe_led_off, NULL); + break; + case OBSERVE_NOT_SUPPORTED: + PRINTF("OBSERVE_NOT_SUPPORTED: %*s\n", len, (char *)payload); + obs = NULL; + break; + case ERROR_RESPONSE_CODE: + PRINTF("ERROR_RESPONSE_CODE: %*s\n", len, (char *)payload); + obs = NULL; + break; + case NO_REPLY_FROM_SERVER: + PRINTF("NO_REPLY_FROM_SERVER: " + "removing observe registration with token %x%x\n", + obs->token[0], obs->token[1]); + obs = NULL; + break; + } +} +/*----------------------------------------------------------------------------*/ +/* + * The main (proto-)thread. It starts/stops the observation of the remote + * resource every time the timer elapses or the button (if available) is + * pressed + */ +PROCESS_THREAD(er_example_observe_client, ev, data) +{ + PROCESS_BEGIN(); + + uiplib_ipaddrconv(SERVER_IPV6_ADDR, server_ipaddr); + + /* receives all CoAP messages */ + coap_init_engine(); + +#if PLATFORM_HAS_BUTTON + SENSORS_ACTIVATE(button_1); + SENSORS_ACTIVATE(button_2); +#endif + + /* toggle observation every time the timer elapses or the button is pressed */ + while (1) { + PROCESS_YIELD(); +#if PLATFORM_HAS_BUTTON + if (ev == sensors_event) { + if (data == &button_1 && button_1.value(BUTTON_SENSOR_VALUE_STATE) == 0) { + PRINTF("Starting observation\n"); + obs = coap_obs_request_registration(server_ipaddr, REMOTE_PORT, + OBS_RESOURCE_URI, notification_callback, + NULL); + } + if (data == &button_2 && button_2.value(BUTTON_SENSOR_VALUE_STATE) == 0) { + PRINTF("Stopping observation\n"); + coap_obs_remove_observee(obs); + obs = NULL; + } + } +#endif + } + PROCESS_END(); +} + +/** + * @} + * @} + */ diff --git a/examples/nrf52dk/coap-demo/coap-server.c b/examples/nrf52dk/coap-demo/coap-server.c new file mode 100644 index 000000000..9bab7e60d --- /dev/null +++ b/examples/nrf52dk/coap-demo/coap-server.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * Copyright (c) 2015, Nordic Semiconductor + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \addtogroup nrf52dk-examples Demo projects for nRF52 DK + * @{ + * + * \defgroup nrf52dk-coap-demo CoAP demo for nRF52dk + * @{ + * + * \file + * Erbium (Er) REST Engine example. + * \author + * Matthias Kovatsch + * \author + * Wojciech Bober + */ + +#include +#include +#include +#include "contiki.h" +#include "contiki-net.h" +#include "rest-engine.h" +#include "uip.h" +#include "dev/button-sensor.h" +#include "dev/leds.h" + +#define DEBUG DEBUG_PRINT +#include "net/ip/uip-debug.h" + +/* + * Resources to be activated need to be imported through the extern keyword. + * The build system automatically compiles the resources in the corresponding sub-directory. + */ +extern resource_t res_led3; + +static void +print_local_addresses(void) +{ + int i; + uint8_t state; + + PRINTF("Server IPv6 addresses:\n"); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && (state == ADDR_TENTATIVE || state + == ADDR_PREFERRED)) { + PRINTF(" "); + PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n"); + if(state == ADDR_TENTATIVE) { + uip_ds6_if.addr_list[i].state = ADDR_PREFERRED; + } + } + } +} + +PROCESS(er_example_server, "nRF52 DK Coap Server"); +AUTOSTART_PROCESSES(&er_example_server); + +PROCESS_THREAD(er_example_server, ev, data) +{ + PROCESS_BEGIN(); + PROCESS_PAUSE(); + + PRINTF("Starting Erbium Example Server\n"); + + PRINTF("uIP buffer: %u\n", UIP_BUFSIZE); + PRINTF("LL header: %u\n", UIP_LLH_LEN); + PRINTF("IP+UDP header: %u\n", UIP_IPUDPH_LEN); + PRINTF("REST max chunk: %u\n", REST_MAX_CHUNK_SIZE); + + print_local_addresses(); + + /* Initialize the REST engine. */ + rest_init_engine(); + rest_activate_resource(&res_led3, "lights/led3"); + + SENSORS_ACTIVATE(button_1); + + /* Define application-specific events here. */ + while (1) { + PROCESS_WAIT_EVENT(); + + if (ev == sensors_event) { + if (data == &button_1 && button_1.value(BUTTON_SENSOR_VALUE_STATE) == 0) { + leds_toggle(LEDS_3); + res_led3.trigger(); + } + } + } + + PROCESS_END(); +} + +/** + * @} + * @} + */ diff --git a/examples/nrf52dk/coap-demo/project-conf.h b/examples/nrf52dk/coap-demo/project-conf.h new file mode 100644 index 000000000..2b097e8a8 --- /dev/null +++ b/examples/nrf52dk/coap-demo/project-conf.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \addtogroup nrf52dk-examples Demo projects for nRF52 DK + * @{ + * + * \defgroup nrf52dk-coap-demo CoAP demo for nRF52dk + * @{ + * + * \file + * Erbium (Er) example project configuration. + * \author + * Matthias Kovatsch + */ + +#ifndef __PROJECT_ERBIUM_CONF_H__ +#define __PROJECT_ERBIUM_CONF_H__ + +/* Disabling TCP on CoAP nodes. */ +#undef UIP_CONF_TCP +#define UIP_CONF_TCP 0 + +/* Increase rpl-border-router IP-buffer when using more than 64. */ +#undef REST_MAX_CHUNK_SIZE +#define REST_MAX_CHUNK_SIZE 48 + +/* Estimate your header size, especially when using Proxy-Uri. */ +/* + #undef COAP_MAX_HEADER_SIZE + #define COAP_MAX_HEADER_SIZE 70 + */ + +/* Multiplies with chunk size, be aware of memory constraints. */ +#undef COAP_MAX_OPEN_TRANSACTIONS +#define COAP_MAX_OPEN_TRANSACTIONS 4 + +/* Must be <= open transactions, default is COAP_MAX_OPEN_TRANSACTIONS-1. */ +/* + #undef COAP_MAX_OBSERVERS + #define COAP_MAX_OBSERVERS 2 + */ + +/* Filtering .well-known/core per query can be disabled to save space. */ +#undef COAP_LINK_FORMAT_FILTERING +#define COAP_LINK_FORMAT_FILTERING 0 +#undef COAP_PROXY_OPTION_PROCESSING +#define COAP_PROXY_OPTION_PROCESSING 0 + +/* Enable client-side support for COAP observe */ +#define COAP_OBSERVE_CLIENT 1 +#endif /* __PROJECT_ERBIUM_CONF_H__ */ + +/** + * @} + * @} + */ diff --git a/examples/nrf52dk/coap-demo/resources/res-leds.c b/examples/nrf52dk/coap-demo/resources/res-leds.c new file mode 100644 index 000000000..468a165bf --- /dev/null +++ b/examples/nrf52dk/coap-demo/resources/res-leds.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Example resource + * \author + * Matthias Kovatsch + * \author + * Wojciech Bober + */ + +#include +#include "contiki.h" +#include "rest-engine.h" +#include "dev/leds.h" + +#define DEBUG DEBUG_NONE +#include "net/ip/uip-debug.h" + +static void +res_post_put_handler(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset); + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset); + +static void +res_event_handler(); + +/*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/ +EVENT_RESOURCE(res_led3, + "title=\"LED3\"; obs", + res_get_handler, + res_post_put_handler, + res_post_put_handler, + NULL, + res_event_handler + ); + +static void +res_post_put_handler(void *request, void *response, uint8_t *buffer, + uint16_t preferred_size, int32_t *offset) +{ + const uint8_t *payload; + REST.get_request_payload(request, &payload); + + if (*payload == '0' || *payload == '1') { + if (*payload == '1') { + leds_on(LEDS_3); + } else { + leds_off(LEDS_3); + } + REST.notify_subscribers(&res_led3); + REST.set_response_status(response, REST.status.CHANGED); + } else { + REST.set_response_status(response, REST.status.BAD_REQUEST); + } +} + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + REST.set_response_payload(response, buffer, snprintf((char *)buffer, preferred_size, "%d", (leds_get() & LEDS_3) ? 1 : 0)); +} + +/* + * Additionally, res_event_handler must be implemented for each EVENT_RESOURCE. + * It is called through .trigger(), usually from the server process. + */ +static void +res_event_handler() +{ + /* Notify the registered observers which will trigger the res_get_handler to create the response. */ + REST.notify_subscribers(&res_led3); +} diff --git a/examples/nrf52dk/mqtt-demo/Makefile b/examples/nrf52dk/mqtt-demo/Makefile new file mode 100644 index 000000000..bfdeccfb7 --- /dev/null +++ b/examples/nrf52dk/mqtt-demo/Makefile @@ -0,0 +1,11 @@ +DEFINES+=PROJECT_CONF_H=\"project-conf.h\" + +all: mqtt-demo + +CONTIKI_WITH_IPV6 = 1 +CONTIKI_WITH_RPL = 0 + +APPS += mqtt + +CONTIKI=../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/nrf52dk/mqtt-demo/README.md b/examples/nrf52dk/mqtt-demo/README.md new file mode 100644 index 000000000..a4a9a6ff1 --- /dev/null +++ b/examples/nrf52dk/mqtt-demo/README.md @@ -0,0 +1,74 @@ +MQTT Demo +========= +The MQTT client can be used to: + +* Publish sensor readings to an MQTT broker. +* Subscribe to a topic and receive commands from an MQTT broker + +The demo will give some visual feedback with the green LED: +* Very fast blinking: Searching for a network +* Fast blinking: Connecting to broker +* Slow, long blinking: Sending a publish message + +Note that before any MQTT messages can be sent or received you'll +need to configure an IPv6 connection to the device and assign a routable +IPv6 address. + +For details how to do this please refer to sections 'Establishing an IPv6 connection' +and 'Distributing routable IPv6 prefix' in `platform/nrf52dk/README-BLE-6LoWPAN.md`. + +Broker setup +------------ +By default the example will attempt to publish readings to an MQTT broker +running on the IPv6 address specified as `MQTT_DEMO_BROKER_IP_ADDR` in +`project-conf.h`. This functionality was tested successfully with +[mosquitto](http://mosquitto.org/). + +On Ubuntu you can install and run mosquitto broker using the following +commands: + + apt-get install mosquitto mosquitto_clients + killall mosquitto + mosquitto -p 1883 -v + +Publishing +---------- +The publish messages include sensor readings but also some other information, +such as device uptime in seconds and a message sequence number. The demo will +publish to topic `iot-2/evt/status/fmt/json`. The device will connect using +client-id `d:quickstart:cc2538:`, where `` gets +constructed from the device's IEEE address. + +Subscribing +----------- +You can also subscribe to topics and receive commands, but this will only +work if you use "Org ID" != 'quickstart'. To achieve this, you will need to +change 'Org ID' (`DEFAULT_ORG_ID`). In this scenario, the device will subscribe +to: + +`iot-2/cmd/+/fmt/json` + +You can then use this to toggle LEDs. To do this, you can for example +use mosquitto client to publish to `iot-2/cmd/leds/fmt/json`. So, to change +the state of an LED, you would do this: + +`mosquitto_pub -h -m "1" -t iot-2/cmd/leds/fmt/json` + +Where `broker IP` should be replaced with the IP address of your mosquitto +broker (the one where you device has subscribed). Replace `-m "1'` with `-m "0"` +to turn the LED back off. + +Bear in mind that, even though the topic suggests that messages are of json +format, they are in fact not. This was done in order to avoid linking a json +parser into the firmware. This comment only applies to parsing incoming +messages, outgoing publish messages use proper json payload. + +IBM Quickstart Service +---------------------- +It is also possible to publish to IBM's quickstart service. To do so, you need +to undefine `MQTT_DEMO_BROKER_IP_ADDR`. + +If you want to use IBM's cloud service with a registered device, change +'Org ID' (`DEFAULT_ORG_ID`) and provide the 'Auth Token' (`DEFAULT_AUTH_TOKEN`), +which acts as a 'password', but bear in mind that it gets transported in clear +text. \ No newline at end of file diff --git a/examples/nrf52dk/mqtt-demo/mqtt-demo.c b/examples/nrf52dk/mqtt-demo/mqtt-demo.c new file mode 100644 index 000000000..6a3482073 --- /dev/null +++ b/examples/nrf52dk/mqtt-demo/mqtt-demo.c @@ -0,0 +1,721 @@ +/* + * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup nrf52dk-examples Demo projects for nRF52 DK + * @{ + * + * \defgroup nrf52dk-mqtt-demo nRF52 DK MQTT Demo Project + * + * Demonstrates MQTT functionality. Works with mosquitto. + * @{ + * + * \file + * An MQTT example for the nrf52dk platform + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "mqtt.h" +#include "net/ip/uip.h" +#include "net/ipv6/uip-icmp6.h" +#include "net/ipv6/sicslowpan.h" +#include "sys/etimer.h" +#include "sys/ctimer.h" +#include "lib/sensors.h" +#include "dev/button-sensor.h" +#include "dev/temperature-sensor.h" +#include "dev/leds.h" + +#include +/*---------------------------------------------------------------------------*/ +/* + * IBM server: quickstart.messaging.internetofthings.ibmcloud.com + * (184.172.124.189) mapped in an NAT64 (prefix 64:ff9b::/96) IPv6 address + * Note: If not able to connect; lookup the IP address again as it may change. + * + * Alternatively, publish to a local MQTT broker (e.g. mosquitto) running on + * the node that hosts your border router + */ +#ifdef MQTT_DEMO_BROKER_IP_ADDR +static const char *broker_ip = MQTT_DEMO_BROKER_IP_ADDR; +#define DEFAULT_ORG_ID "mqtt-demo" +#else +static const char *broker_ip = "0064:ff9b:0000:0000:0000:0000:b8ac:7cbd"; +#define DEFAULT_ORG_ID "quickstart" +#endif +/*---------------------------------------------------------------------------*/ +/* + * A timeout used when waiting for something to happen (e.g. to connect or to + * disconnect) + */ +#define STATE_MACHINE_PERIODIC (CLOCK_SECOND >> 1) +/*---------------------------------------------------------------------------*/ +/* Provide visible feedback via LEDS during various states */ +/* When connecting to broker */ +#define CONNECTING_LED_DURATION (CLOCK_SECOND >> 2) + +/* Each time we try to publish */ +#define PUBLISH_LED_ON_DURATION (CLOCK_SECOND) +/*---------------------------------------------------------------------------*/ +/* Connections and reconnections */ +#define RETRY_FOREVER 0xFF +#define RECONNECT_INTERVAL (CLOCK_SECOND * 2) + +/* + * Number of times to try reconnecting to the broker. + * Can be a limited number (e.g. 3, 10 etc) or can be set to RETRY_FOREVER + */ +#define RECONNECT_ATTEMPTS RETRY_FOREVER +#define CONNECTION_STABLE_TIME (CLOCK_SECOND * 5) +static struct timer connection_life; +static uint8_t connect_attempt; +/*---------------------------------------------------------------------------*/ +/* Various states */ +static uint8_t state; +#define STATE_INIT 0 +#define STATE_REGISTERED 1 +#define STATE_CONNECTING 2 +#define STATE_CONNECTED 3 +#define STATE_PUBLISHING 4 +#define STATE_DISCONNECTED 5 +#define STATE_NEWCONFIG 6 +#define STATE_CONFIG_ERROR 0xFE +#define STATE_ERROR 0xFF +/*---------------------------------------------------------------------------*/ +#define CONFIG_ORG_ID_LEN 32 +#define CONFIG_TYPE_ID_LEN 32 +#define CONFIG_AUTH_TOKEN_LEN 32 +#define CONFIG_EVENT_TYPE_ID_LEN 32 +#define CONFIG_CMD_TYPE_LEN 8 +#define CONFIG_IP_ADDR_STR_LEN 64 +/*---------------------------------------------------------------------------*/ +#define RSSI_MEASURE_INTERVAL_MAX 86400 /* secs: 1 day */ +#define RSSI_MEASURE_INTERVAL_MIN 5 /* secs */ +#define PUBLISH_INTERVAL_MAX 86400 /* secs: 1 day */ +#define PUBLISH_INTERVAL_MIN 5 /* secs */ +/*---------------------------------------------------------------------------*/ +/* A timeout used when waiting to connect to a network */ +#define NET_CONNECT_PERIODIC CLOCK_SECOND +#define NO_NET_LED_DURATION (NET_CONNECT_PERIODIC >> 1) +/*---------------------------------------------------------------------------*/ +/* Default configuration values */ +#define DEFAULT_TYPE_ID "nrf52dk" +#define DEFAULT_AUTH_TOKEN "AUTHZ" +#define DEFAULT_EVENT_TYPE_ID "status" +#define DEFAULT_SUBSCRIBE_CMD_TYPE "+" +#define DEFAULT_BROKER_PORT 1883 +#define DEFAULT_PUBLISH_INTERVAL (30 * CLOCK_SECOND) +#define DEFAULT_KEEP_ALIVE_TIMER 60 +#define DEFAULT_RSSI_MEAS_INTERVAL (CLOCK_SECOND * 30) +/*---------------------------------------------------------------------------*/ +/* Take a sensor reading on button press */ +#define PUBLISH_TRIGGER (&button_sensor) + +/* Payload length of ICMPv6 echo requests used to measure RSSI with def rt */ +#define ECHO_REQ_PAYLOAD_LEN 20 +/*---------------------------------------------------------------------------*/ +PROCESS_NAME(mqtt_demo_process); +AUTOSTART_PROCESSES(&mqtt_demo_process); +/*---------------------------------------------------------------------------*/ +/** + * \brief Data structure declaration for the MQTT client configuration + */ +typedef struct mqtt_client_config { + char org_id[CONFIG_ORG_ID_LEN]; + char type_id[CONFIG_TYPE_ID_LEN]; + char auth_token[CONFIG_AUTH_TOKEN_LEN]; + char event_type_id[CONFIG_EVENT_TYPE_ID_LEN]; + char broker_ip[CONFIG_IP_ADDR_STR_LEN]; + char cmd_type[CONFIG_CMD_TYPE_LEN]; + clock_time_t pub_interval; + int def_rt_ping_interval; + uint16_t broker_port; +} mqtt_client_config_t; +/*---------------------------------------------------------------------------*/ +/* Maximum TCP segment size for outgoing segments of our socket */ +#define MAX_TCP_SEGMENT_SIZE 32 +/*---------------------------------------------------------------------------*/ +#define STATUS_LED LEDS_GREEN +/*---------------------------------------------------------------------------*/ +/* + * Buffers for Client ID and Topic. + * Make sure they are large enough to hold the entire respective string + * + * d:quickstart:status:EUI64 is 32 bytes long + * iot-2/evt/status/fmt/json is 25 bytes + * We also need space for the null termination + */ +#define BUFFER_SIZE 64 +static char client_id[BUFFER_SIZE]; +static char pub_topic[BUFFER_SIZE]; +static char sub_topic[BUFFER_SIZE]; +/*---------------------------------------------------------------------------*/ +/* + * The main MQTT buffers. + * We will need to increase if we start publishing more data. + */ +#define APP_BUFFER_SIZE 128 +static struct mqtt_connection conn; +static char app_buffer[APP_BUFFER_SIZE]; +/*---------------------------------------------------------------------------*/ +#define QUICKSTART "quickstart" +/*---------------------------------------------------------------------------*/ +static struct mqtt_message *msg_ptr = 0; +static struct etimer publish_periodic_timer; +static struct ctimer ct; +static char *buf_ptr; +static uint16_t seq_nr_value = 0; +/*---------------------------------------------------------------------------*/ +/* Parent RSSI functionality */ +static struct uip_icmp6_echo_reply_notification echo_reply_notification; +static struct etimer echo_request_timer; +static int def_rt_rssi = 0; +/*---------------------------------------------------------------------------*/ +static mqtt_client_config_t conf; +/*---------------------------------------------------------------------------*/ +PROCESS(mqtt_demo_process, "MQTT Demo"); +/*---------------------------------------------------------------------------*/ +int +ipaddr_sprintf(char *buf, uint8_t buf_len, const uip_ipaddr_t *addr) +{ + uint16_t a; + uint8_t len = 0; + int i, f; + for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0) { + len += snprintf(&buf[len], buf_len - len, "::"); + } + } else { + if(f > 0) { + f = -1; + } else if(i > 0) { + len += snprintf(&buf[len], buf_len - len, ":"); + } + len += snprintf(&buf[len], buf_len - len, "%x", a); + } + } + + return len; +} +/*---------------------------------------------------------------------------*/ +static void +echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data, + uint16_t datalen) +{ + if(uip_ip6addr_cmp(source, uip_ds6_defrt_choose())) { + def_rt_rssi = sicslowpan_get_last_rssi(); + } +} +/*---------------------------------------------------------------------------*/ +static void +publish_led_off(void *d) +{ + leds_off(STATUS_LED); +} +/*---------------------------------------------------------------------------*/ +static void +pub_handler(const char *topic, uint16_t topic_len, const uint8_t *chunk, + uint16_t chunk_len) +{ + DBG("Pub Handler: topic='%s' (len=%u), chunk_len=%u\n", topic, topic_len, + chunk_len); + + /* If we don't like the length, ignore */ + if(topic_len != 23 || chunk_len != 1) { + printf("Incorrect topic or chunk len. Ignored\n"); + return; + } + + /* If the format != json, ignore */ + if(strncmp(&topic[topic_len - 4], "json", 4) != 0) { + printf("Incorrect format\n"); + } + + if(strncmp(&topic[10], "leds", 4) == 0) { + if(chunk[0] == '1') { + leds_on(LEDS_RED); + } else if(chunk[0] == '0') { + leds_off(LEDS_RED); + } + return; + } +} +/*---------------------------------------------------------------------------*/ +static void +mqtt_event(struct mqtt_connection *m, mqtt_event_t event, void *data) +{ + switch(event) { + case MQTT_EVENT_CONNECTED: { + DBG("APP - Application has a MQTT connection\n"); + timer_set(&connection_life, CONNECTION_STABLE_TIME); + state = STATE_CONNECTED; + break; + } + case MQTT_EVENT_DISCONNECTED: { + DBG("APP - MQTT Disconnect. Reason %u\n", *((mqtt_event_t *)data)); + + state = STATE_DISCONNECTED; + process_poll(&mqtt_demo_process); + break; + } + case MQTT_EVENT_PUBLISH: { + msg_ptr = data; + + /* Implement first_flag in publish message? */ + if(msg_ptr->first_chunk) { + msg_ptr->first_chunk = 0; + DBG("APP - Application received a publish on topic '%s'. Payload " + "size is %i bytes. Content:\n\n", + msg_ptr->topic, msg_ptr->payload_length); + } + + pub_handler(msg_ptr->topic, strlen(msg_ptr->topic), msg_ptr->payload_chunk, + msg_ptr->payload_length); + break; + } + case MQTT_EVENT_SUBACK: { + DBG("APP - Application is subscribed to topic successfully\n"); + break; + } + case MQTT_EVENT_UNSUBACK: { + DBG("APP - Application is unsubscribed to topic successfully\n"); + break; + } + case MQTT_EVENT_PUBACK: { + DBG("APP - Publishing complete\n"); + break; + } + default: + DBG("APP - Application got a unhandled MQTT event: %i\n", event); + break; + } +} +/*---------------------------------------------------------------------------*/ +static int +construct_pub_topic(void) +{ + int len = snprintf(pub_topic, BUFFER_SIZE, "iot-2/evt/%s/fmt/json", + conf.event_type_id); + + /* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */ + if(len < 0 || len >= BUFFER_SIZE) { + printf("Pub Topic: %d, Buffer %d\n", len, BUFFER_SIZE); + return 0; + } + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +construct_sub_topic(void) +{ + int len = snprintf(sub_topic, BUFFER_SIZE, "iot-2/cmd/%s/fmt/json", + conf.cmd_type); + + /* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */ + if(len < 0 || len >= BUFFER_SIZE) { + printf("Sub Topic: %d, Buffer %d\n", len, BUFFER_SIZE); + return 0; + } + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +construct_client_id(void) +{ + int len = snprintf(client_id, BUFFER_SIZE, "d:%s:%s:%02x%02x%02x%02x%02x%02x", + conf.org_id, conf.type_id, + linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1], + linkaddr_node_addr.u8[2], linkaddr_node_addr.u8[5], + linkaddr_node_addr.u8[6], linkaddr_node_addr.u8[7]); + + /* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */ + if(len < 0 || len >= BUFFER_SIZE) { + printf("Client ID: %d, Buffer %d\n", len, BUFFER_SIZE); + return 0; + } + + return 1; +} +/*---------------------------------------------------------------------------*/ +static void +update_config(void) +{ + if(construct_client_id() == 0) { + /* Fatal error. Client ID larger than the buffer */ + state = STATE_CONFIG_ERROR; + return; + } + + if(construct_sub_topic() == 0) { + /* Fatal error. Topic larger than the buffer */ + state = STATE_CONFIG_ERROR; + return; + } + + if(construct_pub_topic() == 0) { + /* Fatal error. Topic larger than the buffer */ + state = STATE_CONFIG_ERROR; + return; + } + + /* Reset the counter */ + seq_nr_value = 0; + + state = STATE_INIT; + + /* + * Schedule next timer event ASAP + * + * If we entered an error state then we won't do anything when it fires. + * + * Since the error at this stage is a config error, we will only exit this + * error state if we get a new config. + */ + etimer_set(&publish_periodic_timer, 0); + + return; +} +/*---------------------------------------------------------------------------*/ +static int +init_config() +{ + /* Populate configuration with default values */ + memset(&conf, 0, sizeof(mqtt_client_config_t)); + + memcpy(conf.org_id, DEFAULT_ORG_ID, strlen(DEFAULT_ORG_ID)); + memcpy(conf.type_id, DEFAULT_TYPE_ID, strlen(DEFAULT_TYPE_ID)); + memcpy(conf.auth_token, DEFAULT_AUTH_TOKEN, strlen(DEFAULT_AUTH_TOKEN)); + memcpy(conf.event_type_id, DEFAULT_EVENT_TYPE_ID, + strlen(DEFAULT_EVENT_TYPE_ID)); + memcpy(conf.broker_ip, broker_ip, strlen(broker_ip)); + memcpy(conf.cmd_type, DEFAULT_SUBSCRIBE_CMD_TYPE, 1); + + conf.broker_port = DEFAULT_BROKER_PORT; + conf.pub_interval = DEFAULT_PUBLISH_INTERVAL; + conf.def_rt_ping_interval = DEFAULT_RSSI_MEAS_INTERVAL; + + return 1; +} +/*---------------------------------------------------------------------------*/ +static void +subscribe(void) +{ + /* Publish MQTT topic in IBM quickstart format */ + mqtt_status_t status; + + status = mqtt_subscribe(&conn, NULL, sub_topic, MQTT_QOS_LEVEL_0); + + DBG("APP - Subscribing!\n"); + if(status == MQTT_STATUS_OUT_QUEUE_FULL) { + DBG("APP - Tried to subscribe but command queue was full!\n"); + } +} +/*---------------------------------------------------------------------------*/ +static void +publish(void) +{ + /* Publish MQTT topic in IBM quickstart format */ + int len; + int remaining = APP_BUFFER_SIZE; + + seq_nr_value++; + + buf_ptr = app_buffer; + + len = snprintf(buf_ptr, remaining, + "{" + "\"d\":{" + "\"Seq #\":%d," + "\"Uptime (sec)\":%lu", seq_nr_value, clock_seconds()); + + if(len < 0 || len >= remaining) { + printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); + return; + } + + remaining -= len; + buf_ptr += len; + + /* Put our Default route's string representation in a buffer */ + char def_rt_str[64]; + memset(def_rt_str, 0, sizeof(def_rt_str)); + ipaddr_sprintf(def_rt_str, sizeof(def_rt_str), uip_ds6_defrt_choose()); + + len = snprintf(buf_ptr, remaining, ",\"Def Route\":\"%s\",\"RSSI (dBm)\":%d", + def_rt_str, def_rt_rssi); + + if(len < 0 || len >= remaining) { + printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); + return; + } + remaining -= len; + buf_ptr += len; + + len = snprintf(buf_ptr, remaining, ",\"On-Chip Temp (deg.C)\":%d", + temperature_sensor.value(0)); + + if(len < 0 || len >= remaining) { + printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); + return; + } + remaining -= len; + buf_ptr += len; + + len = snprintf(buf_ptr, remaining, "}}"); + + if(len < 0 || len >= remaining) { + printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); + return; + } + + mqtt_publish(&conn, NULL, pub_topic, (uint8_t *)app_buffer, + strlen(app_buffer), MQTT_QOS_LEVEL_0, MQTT_RETAIN_OFF); + + DBG("APP - Publish!\n"); +} +/*---------------------------------------------------------------------------*/ +static void +connect_to_broker(void) +{ + /* Connect to MQTT server */ + mqtt_connect(&conn, conf.broker_ip, conf.broker_port, + conf.pub_interval * 3); + + state = STATE_CONNECTING; +} +/*---------------------------------------------------------------------------*/ +static void +ping_parent(void) +{ + if(uip_ds6_get_global(ADDR_PREFERRED) == NULL) { + return; + } + + uip_icmp6_send(uip_ds6_defrt_choose(), ICMP6_ECHO_REQUEST, 0, + ECHO_REQ_PAYLOAD_LEN); +} +/*---------------------------------------------------------------------------*/ +static void +state_machine(void) +{ + switch(state) { + case STATE_INIT: + /* If we have just been configured register MQTT connection */ + mqtt_register(&conn, &mqtt_demo_process, client_id, mqtt_event, + MAX_TCP_SEGMENT_SIZE); + + /* + * If we are not using the quickstart service (thus we are an IBM + * registered device), we need to provide user name and password + */ + if(strncasecmp(conf.org_id, QUICKSTART, strlen(conf.org_id)) != 0) { + if(strlen(conf.auth_token) == 0) { + printf("User name set, but empty auth token\n"); + state = STATE_ERROR; + break; + } else { + mqtt_set_username_password(&conn, "use-token-auth", + conf.auth_token); + } + } + + /* _register() will set auto_reconnect. We don't want that. */ + conn.auto_reconnect = 0; + connect_attempt = 1; + + state = STATE_REGISTERED; + DBG("Init\n"); + /* Continue */ + case STATE_REGISTERED: + if(uip_ds6_get_global(ADDR_PREFERRED) != NULL) { + /* Registered and with a public IP. Connect */ + DBG("Registered. Connect attempt %u\n", connect_attempt); + ping_parent(); + connect_to_broker(); + } else { + leds_on(STATUS_LED); + ctimer_set(&ct, NO_NET_LED_DURATION, publish_led_off, NULL); + } + etimer_set(&publish_periodic_timer, NET_CONNECT_PERIODIC); + return; + break; + case STATE_CONNECTING: + leds_on(STATUS_LED); + ctimer_set(&ct, CONNECTING_LED_DURATION, publish_led_off, NULL); + /* Not connected yet. Wait */ + DBG("Connecting (%u)\n", connect_attempt); + break; + case STATE_CONNECTED: + /* Don't subscribe unless we are a registered device */ + if(strncasecmp(conf.org_id, QUICKSTART, strlen(conf.org_id)) == 0) { + DBG("Using 'quickstart': Skipping subscribe\n"); + state = STATE_PUBLISHING; + } + /* Continue */ + case STATE_PUBLISHING: + /* If the timer expired, the connection is stable. */ + if(timer_expired(&connection_life)) { + /* + * Intentionally using 0 here instead of 1: We want RECONNECT_ATTEMPTS + * attempts if we disconnect after a successful connect + */ + connect_attempt = 0; + } + + if(mqtt_ready(&conn) && conn.out_buffer_sent) { + /* Connected. Publish */ + if(state == STATE_CONNECTED) { + subscribe(); + state = STATE_PUBLISHING; + } else { + leds_on(STATUS_LED); + ctimer_set(&ct, PUBLISH_LED_ON_DURATION, publish_led_off, NULL); + publish(); + } + etimer_set(&publish_periodic_timer, conf.pub_interval); + + DBG("Publishing\n"); + /* Return here so we don't end up rescheduling the timer */ + return; + } else { + /* + * Our publish timer fired, but some MQTT packet is already in flight + * (either not sent at all, or sent but not fully ACKd). + * + * This can mean that we have lost connectivity to our broker or that + * simply there is some network delay. In both cases, we refuse to + * trigger a new message and we wait for TCP to either ACK the entire + * packet after retries, or to timeout and notify us. + */ + DBG("Publishing... (MQTT state=%d, q=%u)\n", conn.state, + conn.out_queue_full); + } + break; + case STATE_DISCONNECTED: + DBG("Disconnected\n"); + if(connect_attempt < RECONNECT_ATTEMPTS || + RECONNECT_ATTEMPTS == RETRY_FOREVER) { + /* Disconnect and backoff */ + clock_time_t interval; + mqtt_disconnect(&conn); + connect_attempt++; + + interval = connect_attempt < 3 ? RECONNECT_INTERVAL << connect_attempt : + RECONNECT_INTERVAL << 3; + + DBG("Disconnected. Attempt %u in %lu ticks\n", connect_attempt, interval); + + etimer_set(&publish_periodic_timer, interval); + + state = STATE_REGISTERED; + return; + } else { + /* Max reconnect attempts reached. Enter error state */ + state = STATE_ERROR; + DBG("Aborting connection after %u attempts\n", connect_attempt - 1); + } + break; + case STATE_CONFIG_ERROR: + /* Idle away. The only way out is a new config */ + printf("Bad configuration\n"); + return; + case STATE_ERROR: + default: + leds_on(STATUS_LED); + /* + * 'default' should never happen. + * + * If we enter here it's because of some error. Stop timers. The only thing + * that can bring us out is a new config event + */ + printf("Default case: State=0x%02x\n", state); + return; + } + + /* If we didn't return so far, reschedule ourselves */ + etimer_set(&publish_periodic_timer, STATE_MACHINE_PERIODIC); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(mqtt_demo_process, ev, data) +{ + + PROCESS_BEGIN(); + + printf("MQTT Demo Process\n"); + + if(init_config() != 1) { + PROCESS_EXIT(); + } + + update_config(); + + def_rt_rssi = 0x8000000; + uip_icmp6_echo_reply_callback_add(&echo_reply_notification, + echo_reply_handler); + etimer_set(&echo_request_timer, conf.def_rt_ping_interval); + + PUBLISH_TRIGGER->configure(SENSORS_ACTIVE, 1); + + /* Main loop */ + while(1) { + + PROCESS_YIELD(); + + if(ev == sensors_event && data == PUBLISH_TRIGGER) { + if(state == STATE_ERROR) { + connect_attempt = 1; + state = STATE_REGISTERED; + } + } + + if((ev == PROCESS_EVENT_TIMER && data == &publish_periodic_timer) || + ev == PROCESS_EVENT_POLL || + (ev == sensors_event && data == PUBLISH_TRIGGER && PUBLISH_TRIGGER->value(BUTTON_SENSOR_VALUE_STATE) == 0)) { + state_machine(); + } + + if(ev == PROCESS_EVENT_TIMER && data == &echo_request_timer) { + ping_parent(); + etimer_set(&echo_request_timer, conf.def_rt_ping_interval); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/examples/nrf52dk/mqtt-demo/project-conf.h b/examples/nrf52dk/mqtt-demo/project-conf.h new file mode 100644 index 000000000..b52e1a48f --- /dev/null +++ b/examples/nrf52dk/mqtt-demo/project-conf.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup cc2538-mqtt-demo + * @{ + * + * \file + * Project specific configuration defines for the MQTT demo + */ +/*---------------------------------------------------------------------------*/ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ +/*---------------------------------------------------------------------------*/ +/* User configuration */ +#define MQTT_DEMO_STATUS_LED LEDS_GREEN + +/* If undefined, the demo will attempt to connect to IBM's quickstart */ +#define MQTT_DEMO_BROKER_IP_ADDR "fd00::215:83ff:fed2:dbd7" +/*---------------------------------------------------------------------------*/ +#endif /* PROJECT_CONF_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/examples/nrf52dk/timer-test/Makefile b/examples/nrf52dk/timer-test/Makefile new file mode 100644 index 000000000..ac89a34a4 --- /dev/null +++ b/examples/nrf52dk/timer-test/Makefile @@ -0,0 +1,9 @@ +CONTIKI_PROJECT = timer-test + +CONTIKI_WITH_RPL=0 +NRF52_WITHOUT_SOFTDEVICE=1 + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/nrf52dk/timer-test/README.md b/examples/nrf52dk/timer-test/README.md new file mode 100644 index 000000000..9ce7cad94 --- /dev/null +++ b/examples/nrf52dk/timer-test/README.md @@ -0,0 +1,20 @@ +Timers test +=========== +Timers test is an application allows for testing clocks implementation for nRF52 DK. +The results of different tests are output to the console. + +There are 4 tests performed: + + 1) TEST clock_delay_usec() - measures duration of a NOP delay using rtimer. It's expected + that difference is close to 0. + + 2) TEST rtimer - schedules an rtimer callback after 1 second. Prints actual time difference + in rtimer and clock ticks. It's expected that both values are close to 0. + + 3) TEST etimer - schedules an event timer and measures time difference. It is expected that + the value is close to 0. + +The example requires one DK and it doesn't use SoftDevice. To compile and flash the +example run: + + make TARGET=nrf52dk timer-test.flash \ No newline at end of file diff --git a/examples/nrf52dk/timer-test/timer-test.c b/examples/nrf52dk/timer-test/timer-test.c new file mode 100644 index 000000000..e0ced7293 --- /dev/null +++ b/examples/nrf52dk/timer-test/timer-test.c @@ -0,0 +1,131 @@ +/** + * \file + * Tests related to clocks and timers + * This is based on clock_test.c from the original sensinode port + * + * \author + * Zach Shelby (Original) + * George Oikonomou - (rtimer code) + * Wojciech Bober (nRF52 DK adaptation) + * + */ + +/** + * \addtogroup nrf52dk-examples Demo projects for nRF52 DK + * @{ + */ +#include "contiki.h" +#include "sys/clock.h" +#include "sys/rtimer.h" +#include "dev/leds.h" + +#include "nrf_delay.h" + +#include +/*---------------------------------------------------------------------------*/ +#define TEST_CLOCK_DELAY_USEC 1 +#define TEST_RTIMER 1 +#define TEST_ETIMER 1 +/*---------------------------------------------------------------------------*/ +static struct etimer et; + +#if TEST_CLOCK_DELAY_USEC +static rtimer_clock_t start_count, end_count, diff; +#endif + +#if TEST_ETIMER +static clock_time_t count; +#endif + +#if TEST_RTIMER +static struct rtimer rt; +static clock_time_t ct_now; +rtimer_clock_t rt_now, rt_until; + +static volatile rtimer_clock_t rt_now_cb; +static volatile clock_time_t ct_cb; +#endif + +static uint8_t i; +/*---------------------------------------------------------------------------*/ +PROCESS(clock_test_process, "Clock test process"); +AUTOSTART_PROCESSES(&clock_test_process); +/*---------------------------------------------------------------------------*/ +#if TEST_RTIMER +void +rt_callback(struct rtimer *t, void *ptr) +{ + rt_now_cb = RTIMER_NOW(); + ct_cb = clock_time(); +} +#endif +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(clock_test_process, ev, data) +{ + + PROCESS_BEGIN(); + etimer_set(&et, 2 * CLOCK_SECOND); + PROCESS_YIELD(); + + printf("RTIMER_SECOND=%d CLOCK_SECOND=%d\n", RTIMER_SECOND, CLOCK_SECOND); + +#if TEST_CLOCK_DELAY_USEC + printf("=======================\n"); + printf("TEST clock_delay_usec()\n"); + printf("=======================\n"); + i = 1; + while(i < 7) { + start_count = RTIMER_NOW(); + clock_delay_usec(10000 * i); + end_count = RTIMER_NOW(); + diff = end_count - start_count; + printf("difference [usec]: %ld\n", 10000 * i - (diff*(1000000/RTIMER_SECOND))); + i++; + } +#endif + +#if TEST_RTIMER + printf("=======================\n"); + printf("TEST rtimer\n"); + printf("=======================\n"); + i = 0; + while(i < 5) { + etimer_set(&et, 2 * CLOCK_SECOND); + rt_now = RTIMER_NOW(); + ct_now = clock_time(); + rt_until = rt_now + RTIMER_SECOND; + printf("now [ticks]: %lu until[ticks]: %lu\n", rt_now, rt_until); + if (rtimer_set(&rt, rt_until, 1, rt_callback, NULL) != RTIMER_OK) { + printf("Error setting\n"); + } + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + printf("rtimer difference [ticks]: %ld\n", RTIMER_SECOND - (rt_now_cb - rt_now)); + printf("clock difference [ticks]: %ld\n", CLOCK_SECOND - (ct_cb - ct_now)); + i++; + } +#endif + +#if TEST_ETIMER + printf("=======================\n"); + printf("TEST etimer\n"); + printf("=======================\n"); + i = 0; + while(i < 5) { + etimer_set(&et, i*CLOCK_SECOND); + count = clock_time(); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + etimer_reset(&et); + printf("difference [ticks]: %lu\n", i*CLOCK_SECOND - (clock_time() - count)); + leds_toggle(LEDS_RED); + i++; + } +#endif + + printf("Done!\n"); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/examples/openmote-cc2538/Makefile b/examples/openmote-cc2538/Makefile new file mode 100644 index 000000000..e5e5eb4f3 --- /dev/null +++ b/examples/openmote-cc2538/Makefile @@ -0,0 +1,9 @@ +DEFINES+=PROJECT_CONF_H=\"project-conf.h\" + +CONTIKI_PROJECT = openmote-demo + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../.. +CONTIKI_WITH_RIME = 1 +include $(CONTIKI)/Makefile.include diff --git a/examples/openmote-cc2538/openmote-demo.c b/examples/openmote-cc2538/openmote-demo.c new file mode 100644 index 000000000..393203a0c --- /dev/null +++ b/examples/openmote-cc2538/openmote-demo.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2014, OpenMote Technologies, S.L. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-cc2538 + * @{ + * + * \defgroup openmote-examples OpenMote-CC2538 Example Projects + * @{ + * + * Example project demonstrating the OpenMote-CC2538 functionality + * + * @{ + * + * \file + * Example demonstrating the OpenMote-CC2538 platform + * \author + * Pere Tuset + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "cpu.h" +#include "sys/etimer.h" +#include "dev/leds.h" +#include "dev/uart.h" +#include "dev/button-sensor.h" +#include "dev/serial-line.h" +#include "dev/sys-ctrl.h" +#include "net/rime/broadcast.h" + +#include "dev/adxl346.h" +#include "dev/max44009.h" +#include "dev/sht21.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +#define BROADCAST_CHANNEL 129 +/*---------------------------------------------------------------------------*/ +PROCESS(openmote_demo_process, "OpenMote-CC2538 demo process"); +AUTOSTART_PROCESSES(&openmote_demo_process); +/*---------------------------------------------------------------------------*/ +static void +broadcast_recv(struct broadcast_conn *c, const linkaddr_t *from) +{ + leds_toggle(LEDS_GREEN); + printf("Received %u bytes: '0x%04x'\n", packetbuf_datalen(), + *(uint16_t *)packetbuf_dataptr()); +} +/*---------------------------------------------------------------------------*/ +static const struct broadcast_callbacks bc_rx = { broadcast_recv }; +static struct broadcast_conn bc; +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(openmote_demo_process, ev, data) +{ + static struct etimer et; + static int16_t counter; + static uint16_t adxl346_present, sht21_present, max44009_present; + static int16_t accel, light, temperature, humidity; + + PROCESS_EXITHANDLER(broadcast_close(&bc)) + + PROCESS_BEGIN(); + + /* Initialize and calibrate the ADXL346 sensor */ + adxl346_present = SENSORS_ACTIVATE(adxl346); + if(adxl346_present == ADXL346_ERROR) { + printf("ADXL346 sensor is NOT present!\n"); + leds_on(LEDS_YELLOW); + } else { + adxl346.configure(ADXL346_CALIB_OFFSET, 0); + } + + /* Initialize the MAX44009 sensor */ + max44009_present = SENSORS_ACTIVATE(max44009); + if(max44009_present == MAX44009_ERROR) { + printf("MAX44009 sensor is NOT present!\n"); + leds_on(LEDS_ORANGE); + } + + /* Initialize the SHT21 sensor */ + sht21_present = SENSORS_ACTIVATE(sht21); + if(sht21_present == SHT21_ERROR) { + printf("SHT21 sensor is NOT present!\n"); + leds_on(LEDS_RED); + } + + counter = 0; + broadcast_open(&bc, BROADCAST_CHANNEL, &bc_rx); + + printf("****************************************\n"); + + while(1) { + etimer_set(&et, CLOCK_SECOND); + + PROCESS_YIELD(); + + if(ev == PROCESS_EVENT_TIMER) { + if(adxl346_present != ADXL346_ERROR) { + leds_on(LEDS_YELLOW); + accel = adxl346.value(ADXL346_READ_X_mG); + printf("X Acceleration: %d.%u G\n", accel / 1000, accel % 1000); + accel = adxl346.value(ADXL346_READ_Y_mG); + printf("Y Acceleration: %d.%u G\n", accel / 1000, accel % 1000); + accel = adxl346.value(ADXL346_READ_Z_mG); + printf("Z Acceleration: %d.%u G\n", accel / 1000, accel % 1000); + leds_off(LEDS_YELLOW); + } + + if(max44009_present != MAX44009_ERROR) { + leds_on(LEDS_ORANGE); + light = max44009.value(MAX44009_READ_LIGHT); + printf("Light: %u.%ulux\n", light / 100, light % 100); + leds_off(LEDS_ORANGE); + } + + if(sht21_present != SHT21_ERROR) { + leds_on(LEDS_RED); + temperature = sht21.value(SHT21_READ_TEMP); + printf("Temperature: %u.%uC\n", temperature / 100, temperature % 100); + humidity = sht21.value(SHT21_READ_RHUM); + printf("Rel. humidity: %u.%u%%\n", humidity / 100, humidity % 100); + leds_off(LEDS_RED); + } + + printf("****************************************\n"); + } + + if(ev == sensors_event) { + if(data == &button_sensor) { + if(button_sensor.value(BUTTON_SENSOR_VALUE_TYPE_LEVEL) == + BUTTON_SENSOR_PRESSED_LEVEL) { + leds_toggle(LEDS_GREEN); + packetbuf_copyfrom(&counter, sizeof(counter)); + broadcast_send(&bc); + } + } + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + */ diff --git a/examples/openmote-cc2538/openmote-demo.gdb b/examples/openmote-cc2538/openmote-demo.gdb new file mode 100644 index 000000000..43cbb5530 --- /dev/null +++ b/examples/openmote-cc2538/openmote-demo.gdb @@ -0,0 +1,10 @@ +target remote localhost:2331 +monitor interface JTAG +monitor endian little +monitor speed auto +monitor flash device = CC2538SF53 +monitor flash breakpoints = 1 +monitor flash download = 1 +monitor reset +load +continue diff --git a/examples/openmote-cc2538/project-conf.h b/examples/openmote-cc2538/project-conf.h new file mode 100644 index 000000000..718ce668d --- /dev/null +++ b/examples/openmote-cc2538/project-conf.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup remote-examples + * @{ + * + * \file + * Project specific configuration defines for the basic RE-Mote examples + */ +/*---------------------------------------------------------------------------*/ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ +/*---------------------------------------------------------------------------*/ +#define BROADCAST_CHANNEL 129 +#define NETSTACK_CONF_RDC nullrdc_driver +/*---------------------------------------------------------------------------*/ +#endif /* PROJECT_CONF_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/examples/osd/.gitignore b/examples/osd/.gitignore index d21857f07..179e9fe4c 100644 --- a/examples/osd/.gitignore +++ b/examples/osd/.gitignore @@ -1,2 +1,4 @@ *.osd-merkur *.eep +*.osd-merkur-128 +*.osd-merkur-256 diff --git a/examples/osd/arduino-bh1750/BH1750FVI-master/.gitattributes b/examples/osd/arduino-bh1750/BH1750FVI-master/.gitattributes new file mode 100644 index 000000000..412eeda78 --- /dev/null +++ b/examples/osd/arduino-bh1750/BH1750FVI-master/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/examples/osd/arduino-bh1750/BH1750FVI-master/.gitignore b/examples/osd/arduino-bh1750/BH1750FVI-master/.gitignore new file mode 100644 index 000000000..6dae74742 --- /dev/null +++ b/examples/osd/arduino-bh1750/BH1750FVI-master/.gitignore @@ -0,0 +1,36 @@ +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# ========================= +# Operating System Files +# ========================= + +# OSX +# ========================= + +.DS_Store +.AppleDouble +.LSOverride + +# Icon must ends with two \r. +Icon + +# Thumbnails +._* + +# Files that might appear on external disk +.Spotlight-V100 +.Trashes diff --git a/examples/osd/arduino-bh1750/BH1750FVI-master/BH1750FVI.cpp b/examples/osd/arduino-bh1750/BH1750FVI-master/BH1750FVI.cpp new file mode 100644 index 000000000..600905394 --- /dev/null +++ b/examples/osd/arduino-bh1750/BH1750FVI-master/BH1750FVI.cpp @@ -0,0 +1,209 @@ +#include "BH1750FVI.h" +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#include + +void BH1750FVI::begin(byte mode, byte addr, double sens, int pin){ + if(pin>=0 && pin<55){ + pinMode(pin, OUTPUT); + if(addr==BH_AddrL) digitalWrite(pin, LOW); + if(addr==BH_AddrH) digitalWrite(pin, HIGH); + } + byte sensitivity; + if(sens> 5); + MTreg_loByte = BH_MTrLb | (sensitivity & 0b00011111); + switch(mode){ + case BH_ContL: + case BH_ContH: + case BH_Conth: + startOngoingSamples(mode); + break; + case BH_SingH: + case BH_Singh: + case BH_SingL: + startSingleSample(mode); + break; + default: + mode = BH_EasyH; + startOngoingSamples(mode); + break; + } + sampleUnseen = false; + lastSampleStart = 0; +} + +word BH1750FVI::startOngoingSamples(char mode){ + if(mode==BH_NoMod) mode=currentMode; + byte lowLevelMode = mode; + if(lowLevelMode==BH_EasyH) lowLevelMode=BH_ContH; + switch(mode){ + case BH_EasyH: + case BH_ContH: + case BH_Conth: + case BH_ContL: + i2cWrite(BH_PowOn); + i2cWrite(MTreg_hiByte); + i2cWrite(MTreg_loByte); + i2cWrite(lowLevelMode); + lastSampleStart = millis(); + currentMode = mode; + return setSensitivity(currentSensitivity); + break; + default: + return 0; + } +} + +word BH1750FVI::startSingleSample(char mode){ + if(mode==BH_NoMod){ + mode=currentMode; + } + switch(mode){ + case BH_SingH: + case BH_Singh: + case BH_SingL: + i2cWrite(BH_PowOn); + i2cWrite(MTreg_hiByte); + i2cWrite(MTreg_loByte); + i2cWrite(mode); + lastSampleStart = millis(); + currentMode = mode; + return setSensitivity(currentSensitivity); + break; + default: + return 0; + } +} + +bool BH1750FVI::sampleIsFresh(){ + if(sampleUnseen) return true; + else if((millis() > (lastSampleStart+currentSamplingTime))){ + sampleUnseen = true; + return true; + } + else return false; +} + +word BH1750FVI::getLightLevel(char mode){ + unsigned long int Intensity_value; + sampleUnseen = false; + Intensity_value = i2cRead(); + if(mode!='r'){ + Intensity_value = (Intensity_value*5)/6; + if(mode!='c'){ + Intensity_value = (Intensity_value*69)/currentSensitivity; + } + /*this next adjustment is not useful in practice. if you're using + a half-scale mode, you want the extra sensitivity. I'm leaving it + here for reference. + switch(currentMode){ + case BH_Singh: + case BH_Conth: + Intensity_value /= 2; + }*/ + Intensity_value = constrain(Intensity_value, 0, 65535); + } + switch(currentMode){ + case BH_ContH: + case BH_Conth: + case BH_ContL: + case BH_EasyH: + //this is a fake previous sample time that will keep pace with + //the actual BH1750FVI's sampling rate, but isn't necessarily + //synchronized to the earliest time each new sample is available. + //if you want true synchronized timing, use a single-sample mode. + lastSampleStart = millis(); + } + return (word)Intensity_value; +} + +word BH1750FVI::setSensitivity(double sens){ + if(sens<((double)(BH_MinSv/2))){ + sens = constrain(sens, + ((double)BH_MinSv/(double)BH_DefSv), + ((double)BH_MaxSv/(double)BH_DefSv) + ); + sens = sens*(double)BH_DefSv; + } + else{ + sens = constrain(sens, (double)BH_MinSv, (double)BH_MaxSv); + } + return setSensitivity((byte)round(sens)); +} + +word BH1750FVI::setSensitivity(float sens){ + return setSensitivity((double)sens); +} + +word BH1750FVI::setSensitivity(int sens){ + sens = constrain(sens, 1, BH_MaxSv); + return setSensitivity((byte)sens); +} + +word BH1750FVI::setSensitivity(byte sens){ + if(sens<(BH_MinSv/2)){ + sens = BH_DefSv*(constrain(sens, (byte)1, (byte)3)); + } + else{ + sens = constrain(sens, BH_MinSv, BH_MaxSv); + } + switch(currentMode){ + case BH_ContL: + case BH_SingL: + currentSamplingTime = (word)((BH_FastD*(unsigned long int)sens)/BH_DefSv); + break; + default: + currentSamplingTime = (word)((((unsigned long int)BH_SlowD)*((unsigned long int)sens))/BH_DefSv); + break; + } + MTreg_hiByte = BH_MTrHb | (sens >> 5); + MTreg_loByte = BH_MTrLb | (sens & 0b00011111); + currentSensitivity = sens; + sampleUnseen = false; + return currentSamplingTime; +} + +void BH1750FVI::powerDown(){ + i2cWrite(BH_PowOf); +} + +/*I2C INTERFACE + These two functions were originally based on code written by + https://github.com/claws/ and + https://github.com/Genotronex/ +*/ +void BH1750FVI::i2cWrite(byte dataToSend){ + Wire.beginTransmission(address); + Wire.write(dataToSend); + Wire.endTransmission(); +} + +word BH1750FVI::i2cRead(){ + word value; + Wire.beginTransmission(address); + Wire.requestFrom(address, (byte)2); + if(Wire.available()){ + value = Wire.read(); + if(Wire.available()){ + value <<= 8; + value |= Wire.read(); + } + else value=0; + } + else value=0; + Wire.endTransmission(); + return value; +} \ No newline at end of file diff --git a/examples/osd/arduino-bh1750/BH1750FVI-master/BH1750FVI.h b/examples/osd/arduino-bh1750/BH1750FVI-master/BH1750FVI.h new file mode 100644 index 000000000..4a7dc9866 --- /dev/null +++ b/examples/osd/arduino-bh1750/BH1750FVI-master/BH1750FVI.h @@ -0,0 +1,115 @@ +#ifndef BH1750FVI_h +#define BH1750FVI_h + +#if ARDUINO >= 100 + #include "Arduino.h" +#else + #include "WProgram.h" +#endif + +#include + +//device address options +#define BH_AddrL 0x23 // Device address when addr pin is LOW +#define BH_AddrH 0x5C // Device address when addr pin is HIGH + +//power codes +#define BH_PowOf 0x00 // power-off code +#define BH_PowOn 0x01 // power-on code +#define BH_Reset 0x07 // code to reset the light reading register to zero + +//mode codes +#define BH_NoMod 0x02 // No mode specified. Keeps mode the same as before. +#define BH_EasyH 0x03 // 'easy' mode. basically the same as ContH +#define BH_ContH 0x10 // continuous full-scale, high-resolution sampling +#define BH_Conth 0x11 // continuous with twice the resolution but half the max value +#define BH_ContL 0x13 // continuous full-scale, low-resolution sampling. faster. +#define BH_SingH 0x20 // take one high-resolution, full-scale sample then turn off +#define BH_Singh 0x21 // take one high-resolution, half-scale sample then turn off +#define BH_SingL 0x23 // take one low-resolution, full-scale sample then turn off + // (happens to be the same as the low address value) + +//sensitivity codes +#define BH_MTrHb 0x40 // last 3 bits must be masked to 3 MSB of desired value +#define BH_MTrLb 0x60 // last 5 bits must be masked to 5 LSB of desired value +#define BH_MinSv 31 // minimum sensitivity register value, yields Lux * 0.45 +#define BH_MaxSv 254 // maximum sensitivity register value, yields Lux * 3.68 +#define BH_DefSv 69 // default sensitivity register value, yields Lux * 1.00 + +//timing delays. they're actually longer than the datasheet says. +#define BH_FastD 18 // basic delay in microseconds for a fast sample +#define BH_SlowD 125 // basic delay in microseconds for a slow sample + +class BH1750FVI { + public: + /*BEGIN + this is intended to be as error-tolerant as possible. if you don't supply + a mode, the default mode will be 'easy'. the sensitivity obviously defaults + to 1.0 (byte value of 69). Default address selection is LOW, which is how + the BH1750FVI should default if you don't connect anything to its ADDR pin. + */void begin(byte mode=BH_EasyH, byte addr=BH_AddrL, double sens=BH_DefSv, int addrPin=-1); + + /*FRESH SAMPLE POLLING + Check whether you have already looked at the current sample. + */bool sampleIsFresh(); + + /*ACTUALLY GET A READING FROM THE SENSOR + This is probably all you wanted from this library. Return value is an + unsigned 16 bit integer with units of Lux. There are three possible modes: + 'r' raw numerical reading, no units, you get what you get + 'c' convert units to Lux or half-Lux, depending on the mode, but don't + compensate for the sensitivity setting. This allows sensitivity to + be used as enclosure optics calibration/compensation. + 't' true Lux (or half-Lux) reading, regardless of sensitivity settings. + */word getLightLevel(char adjustments='c'); + + word retrieveSample(); + + /*CONTINUOUS SAMPLING + Return value of this start function is the delay time between refreshes of + the ambient light reading. After you call this function, you can use getLightLevel() + to read the most recent ambient light level. If you try to run this ongoing start + function with a one-time mode argument, it will do nothing and return 0. + */word startOngoingSamples(char mode=BH_NoMod); + + /*ONE-TIME SAMPLE START + Return value of this start function is the delay time before the new ambient + light reading will be available. You can check whether the new sample is ready + yet using sampleIsFresh(). Retrieve that single sample with getLightLevel(). + If you give this one-time start function a continuous mode argument, it will + do nothing and return 0. + */word startSingleSample(char mode=BH_NoMod); + + /*SENSITIVITY SETTINGS + This function lets you change the 'sensitivity' of the BH1750FVI by changing + its sampling time up or down. The sensitivity is stored as a number between + 31 and 254, with a default value of 69. This is intended to compensate for + having the chip installed in an enclosure that blocks some ambient light. + The floating point versions of the function allow the sensitivity to be + given as a ratio between ~0.45 and ~3.68. The return value is the number of + milliseconds that the chip will take to create a new light level reading. + */word setSensitivity(double sens); + word setSensitivity(float sens); + word setSensitivity(int sens); + word setSensitivity(byte sens=BH_DefSv); + + /*POWERDOWN FUNCTION + In case you want to turn off the BH1750FVI to save power. Other commands will wake + the chip back up. Single sample modes automatically turn off the chip after sampling, + but you can still read the value from it without waking it up. + */void powerDown(); + + private: + void init(byte mode, byte addr, byte sens); + void i2cWrite(byte dataToSend); + word i2cRead(); + byte address; + byte currentMode; + byte currentSensitivity; + bool sampleUnseen; + byte MTreg_hiByte; + byte MTreg_loByte; + unsigned long int lastSampleStart; + word currentSamplingTime; +}; +#endif \ No newline at end of file diff --git a/examples/osd/arduino-bh1750/BH1750FVI-master/BasicDemo/BasicDemo.ino b/examples/osd/arduino-bh1750/BH1750FVI-master/BasicDemo/BasicDemo.ino new file mode 100644 index 000000000..3625f5202 --- /dev/null +++ b/examples/osd/arduino-bh1750/BH1750FVI-master/BasicDemo/BasicDemo.ino @@ -0,0 +1,23 @@ +#include +#include + +BH1750FVI eye; +word maxLux = 0; + +void setup() { + Wire.begin(); + Serial.begin(115200); + //most basic setup with all default options + eye.begin(); +} + +void loop() { + //take a sensor reading, with units of Lux + word value = eye.getLightLevel(); + byte spaces; + if(value>maxLux) maxLux=value; + spaces=map(value, 0, maxLux, 0, 32); + for(int i=0; i +#include + +BH1750FVI eye; + +void setup() { + Wire.begin(); + Serial.begin(115200); + //setup with continuous sampling, using the low address and double sensitivity + eye.begin(BH_ContH, BH_AddrL, 2.0); +} + +void loop() { + //test if the sensor has had time to produce a new reading + if(eye.sampleIsFresh()){ + //read the calibration-adjusted value, according to the sensitivity setting + word value = eye.getLightLevel('c'); + logarithmicGraphing(value); + Serial.println(value); + } +} + + + + +void logarithmicGraphing(word value){ + int i=0; + while(value>>i){ + i++; + Serial.print(" "); + } + if(i>=2){ + i=i-2; + if(value&(1<= 100 + #include "Arduino.h" +//#else +// #include "WProgram.h" +//#endif + +#include + +void BH1750FVI::begin(byte mode, byte addr, double sens, int pin){ + if(pin>=0 && pin<55){ + pinMode(pin, OUTPUT); + if(addr==BH_AddrL) digitalWrite(pin, LOW); + if(addr==BH_AddrH) digitalWrite(pin, HIGH); + } + byte sensitivity; + if(sens> 5); + MTreg_loByte = BH_MTrLb | (sensitivity & 0b00011111); + switch(mode){ + case BH_ContL: + case BH_ContH: + case BH_Conth: + startOngoingSamples(mode); + break; + case BH_SingH: + case BH_Singh: + case BH_SingL: + startSingleSample(mode); + break; + default: + mode = BH_EasyH; + startOngoingSamples(mode); + break; + } + sampleUnseen = false; + lastSampleStart = 0; +} + +word BH1750FVI::startOngoingSamples(char mode){ + if(mode==BH_NoMod) mode=currentMode; + byte lowLevelMode = mode; + if(lowLevelMode==BH_EasyH) lowLevelMode=BH_ContH; + switch(mode){ + case BH_EasyH: + case BH_ContH: + case BH_Conth: + case BH_ContL: + i2cWrite(BH_PowOn); + i2cWrite(MTreg_hiByte); + i2cWrite(MTreg_loByte); + i2cWrite(lowLevelMode); + lastSampleStart = millis(); + currentMode = mode; + return setSensitivity(currentSensitivity); + break; + default: + return 0; + } +} + +word BH1750FVI::startSingleSample(char mode){ + if(mode==BH_NoMod){ + mode=currentMode; + } + switch(mode){ + case BH_SingH: + case BH_Singh: + case BH_SingL: + i2cWrite(BH_PowOn); + i2cWrite(MTreg_hiByte); + i2cWrite(MTreg_loByte); + i2cWrite(mode); + lastSampleStart = millis(); + currentMode = mode; + return setSensitivity(currentSensitivity); + break; + default: + return 0; + } +} + +bool BH1750FVI::sampleIsFresh(){ + if(sampleUnseen) return true; + else if((millis() > (lastSampleStart+currentSamplingTime))){ + sampleUnseen = true; + return true; + } + else return false; +} + +word BH1750FVI::getLightLevel(char mode){ + unsigned long int Intensity_value; + sampleUnseen = false; + Intensity_value = i2cRead(); + if(mode!='r'){ + Intensity_value = (Intensity_value*5)/6; + if(mode!='c'){ + Intensity_value = (Intensity_value*69)/currentSensitivity; + } + /*this next adjustment is not useful in practice. if you're using + a half-scale mode, you want the extra sensitivity. I'm leaving it + here for reference. + switch(currentMode){ + case BH_Singh: + case BH_Conth: + Intensity_value /= 2; + }*/ + Intensity_value = constrain(Intensity_value, 0, 65535); + } + switch(currentMode){ + case BH_ContH: + case BH_Conth: + case BH_ContL: + case BH_EasyH: + //this is a fake previous sample time that will keep pace with + //the actual BH1750FVI's sampling rate, but isn't necessarily + //synchronized to the earliest time each new sample is available. + //if you want true synchronized timing, use a single-sample mode. + lastSampleStart = millis(); + } + return (word)Intensity_value; +} + +word BH1750FVI::setSensitivity(double sens){ + if(sens<((double)(BH_MinSv/2))){ + sens = constrain(sens, + ((double)BH_MinSv/(double)BH_DefSv), + ((double)BH_MaxSv/(double)BH_DefSv) + ); + sens = sens*(double)BH_DefSv; + } + else{ + sens = constrain(sens, (double)BH_MinSv, (double)BH_MaxSv); + } + return setSensitivity((byte)round(sens)); +} + +word BH1750FVI::setSensitivity(float sens){ + return setSensitivity((double)sens); +} + +word BH1750FVI::setSensitivity(int sens){ + sens = constrain(sens, 1, BH_MaxSv); + return setSensitivity((byte)sens); +} + +word BH1750FVI::setSensitivity(byte sens){ + if(sens<(BH_MinSv/2)){ + sens = BH_DefSv*(constrain(sens, (byte)1, (byte)3)); + } + else{ + sens = constrain(sens, BH_MinSv, BH_MaxSv); + } + switch(currentMode){ + case BH_ContL: + case BH_SingL: + currentSamplingTime = (word)((BH_FastD*(unsigned long int)sens)/BH_DefSv); + break; + default: + currentSamplingTime = (word)((((unsigned long int)BH_SlowD)*((unsigned long int)sens))/BH_DefSv); + break; + } + MTreg_hiByte = BH_MTrHb | (sens >> 5); + MTreg_loByte = BH_MTrLb | (sens & 0b00011111); + currentSensitivity = sens; + sampleUnseen = false; + return currentSamplingTime; +} + +void BH1750FVI::powerDown(){ + i2cWrite(BH_PowOf); +} + +/*I2C INTERFACE + These two functions were originally based on code written by + https://github.com/claws/ and + https://github.com/Genotronex/ +*/ +void BH1750FVI::i2cWrite(byte dataToSend){ + Wire.beginTransmission(address); + Wire.write(dataToSend); + Wire.endTransmission(); +} + +word BH1750FVI::i2cRead(){ + word value; + Wire.beginTransmission(address); + Wire.requestFrom(address, (byte)2); + if(Wire.available()){ + value = Wire.read(); + if(Wire.available()){ + value <<= 8; + value |= Wire.read(); + } + else value=0; + } + else value=0; + Wire.endTransmission(); + return value; +} diff --git a/examples/osd/arduino-bh1750/BH1750FVI.h b/examples/osd/arduino-bh1750/BH1750FVI.h new file mode 100644 index 000000000..acdf62102 --- /dev/null +++ b/examples/osd/arduino-bh1750/BH1750FVI.h @@ -0,0 +1,115 @@ +#ifndef BH1750FVI_h +#define BH1750FVI_h + +//#if ARDUINO >= 100 + #include "Arduino.h" +//#else +// #include "WProgram.h" +//#endif + +#include + +//device address options +#define BH_AddrL 0x23 // Device address when addr pin is LOW +#define BH_AddrH 0x5C // Device address when addr pin is HIGH + +//power codes +#define BH_PowOf 0x00 // power-off code +#define BH_PowOn 0x01 // power-on code +#define BH_Reset 0x07 // code to reset the light reading register to zero + +//mode codes +#define BH_NoMod 0x02 // No mode specified. Keeps mode the same as before. +#define BH_EasyH 0x03 // 'easy' mode. basically the same as ContH +#define BH_ContH 0x10 // continuous full-scale, high-resolution sampling +#define BH_Conth 0x11 // continuous with twice the resolution but half the max value +#define BH_ContL 0x13 // continuous full-scale, low-resolution sampling. faster. +#define BH_SingH 0x20 // take one high-resolution, full-scale sample then turn off +#define BH_Singh 0x21 // take one high-resolution, half-scale sample then turn off +#define BH_SingL 0x23 // take one low-resolution, full-scale sample then turn off + // (happens to be the same as the low address value) + +//sensitivity codes +#define BH_MTrHb 0x40 // last 3 bits must be masked to 3 MSB of desired value +#define BH_MTrLb 0x60 // last 5 bits must be masked to 5 LSB of desired value +#define BH_MinSv 31 // minimum sensitivity register value, yields Lux * 0.45 +#define BH_MaxSv 254 // maximum sensitivity register value, yields Lux * 3.68 +#define BH_DefSv 69 // default sensitivity register value, yields Lux * 1.00 + +//timing delays. they're actually longer than the datasheet says. +#define BH_FastD 18 // basic delay in microseconds for a fast sample +#define BH_SlowD 125 // basic delay in microseconds for a slow sample + +class BH1750FVI { + public: + /*BEGIN + this is intended to be as error-tolerant as possible. if you don't supply + a mode, the default mode will be 'easy'. the sensitivity obviously defaults + to 1.0 (byte value of 69). Default address selection is LOW, which is how + the BH1750FVI should default if you don't connect anything to its ADDR pin. + */void begin(byte mode=BH_EasyH, byte addr=BH_AddrL, double sens=BH_DefSv, int addrPin=-1); + + /*FRESH SAMPLE POLLING + Check whether you have already looked at the current sample. + */bool sampleIsFresh(); + + /*ACTUALLY GET A READING FROM THE SENSOR + This is probably all you wanted from this library. Return value is an + unsigned 16 bit integer with units of Lux. There are three possible modes: + 'r' raw numerical reading, no units, you get what you get + 'c' convert units to Lux or half-Lux, depending on the mode, but don't + compensate for the sensitivity setting. This allows sensitivity to + be used as enclosure optics calibration/compensation. + 't' true Lux (or half-Lux) reading, regardless of sensitivity settings. + */word getLightLevel(char adjustments='c'); + + word retrieveSample(); + + /*CONTINUOUS SAMPLING + Return value of this start function is the delay time between refreshes of + the ambient light reading. After you call this function, you can use getLightLevel() + to read the most recent ambient light level. If you try to run this ongoing start + function with a one-time mode argument, it will do nothing and return 0. + */word startOngoingSamples(char mode=BH_NoMod); + + /*ONE-TIME SAMPLE START + Return value of this start function is the delay time before the new ambient + light reading will be available. You can check whether the new sample is ready + yet using sampleIsFresh(). Retrieve that single sample with getLightLevel(). + If you give this one-time start function a continuous mode argument, it will + do nothing and return 0. + */word startSingleSample(char mode=BH_NoMod); + + /*SENSITIVITY SETTINGS + This function lets you change the 'sensitivity' of the BH1750FVI by changing + its sampling time up or down. The sensitivity is stored as a number between + 31 and 254, with a default value of 69. This is intended to compensate for + having the chip installed in an enclosure that blocks some ambient light. + The floating point versions of the function allow the sensitivity to be + given as a ratio between ~0.45 and ~3.68. The return value is the number of + milliseconds that the chip will take to create a new light level reading. + */word setSensitivity(double sens); + word setSensitivity(float sens); + word setSensitivity(int sens); + word setSensitivity(byte sens=BH_DefSv); + + /*POWERDOWN FUNCTION + In case you want to turn off the BH1750FVI to save power. Other commands will wake + the chip back up. Single sample modes automatically turn off the chip after sampling, + but you can still read the value from it without waking it up. + */void powerDown(); + + private: + void init(byte mode, byte addr, byte sens); + void i2cWrite(byte dataToSend); + word i2cRead(); + byte address; + byte currentMode; + byte currentSensitivity; + bool sampleUnseen; + byte MTreg_hiByte; + byte MTreg_loByte; + unsigned long int lastSampleStart; + word currentSamplingTime; +}; +#endif diff --git a/examples/osd/arduino-bh1750/Makefile b/examples/osd/arduino-bh1750/Makefile new file mode 100644 index 000000000..201eeac72 --- /dev/null +++ b/examples/osd/arduino-bh1750/Makefile @@ -0,0 +1,71 @@ +# Set this to the name of your sketch (without extension .pde) +SKETCH=sketch +EXE=arduino-example + +all: $(EXE) + +CONTIKI=../../.. + +# Contiki IPv6 configuration +CONTIKI_WITH_IPV6 = 1 + +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" +LFLAGS += -lm + +PROJECT_SOURCEFILES += ${SKETCH}.cpp BH1750FVI.cpp + +# automatically build RESTful resources +REST_RESOURCES_DIR = ./resources +REST_RESOURCES_DIR_COMMON = ../resources-common +REST_RESOURCES_FILES= $(notdir \ + $(shell find $(REST_RESOURCES_DIR) -name '*.c') \ + $(shell find $(REST_RESOURCES_DIR_COMMON) -name '*.c') \ + ) + +PROJECTDIRS += $(REST_RESOURCES_DIR) $(REST_RESOURCES_DIR_COMMON) +PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) + +# variable for Makefile.include +ifneq ($(TARGET), minimal-net) +CFLAGS += -DUIP_CONF_IPV6_RPL=1 +else +# minimal-net does not support RPL under Linux and is mostly used to test CoAP only +${info INFO: compiling without RPL} +CFLAGS += -DUIP_CONF_IPV6_RPL=0 +CFLAGS += -DHARD_CODED_ADDRESS=\"fdfd::10\" +${info INFO: compiling with large buffers} +CFLAGS += -DUIP_CONF_BUFFER_SIZE=2048 +CFLAGS += -DREST_MAX_CHUNK_SIZE=1024 +CFLAGS += -DCOAP_MAX_HEADER_SIZE=640 +endif + +# linker optimizations +SMALL=1 + + +# REST Engine shall use Erbium CoAP implementation +APPS += er-coap +APPS += rest-engine +APPS += arduino + +include $(CONTIKI)/Makefile.include +include $(CONTIKI)/apps/arduino/Makefile.include + +$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c + (cd $(CONTIKI)/tools && $(MAKE) tunslip6) + +connect-router: $(CONTIKI)/tools/tunslip6 + sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64 + +connect-router-cooja: $(CONTIKI)/tools/tunslip6 + sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 aaaa::1/64 + +connect-minimal: + sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/arduino-bh1750/README.md b/examples/osd/arduino-bh1750/README.md new file mode 100644 index 000000000..e1490ed05 --- /dev/null +++ b/examples/osd/arduino-bh1750/README.md @@ -0,0 +1,11 @@ +Arduino compatibility example +============================= + +This example shows that it is now possible to re-use arduino sketches in +Contiki. This example documents the necessary magic. Arduino specifies +two routines, `setup` and `loop`. Before `setup` is called, the +framework initializes hardware. In original Arduino, all this is done in +a `main` function (in C). For contiki we define a process that does the +same. + +See the documentation file in apps/contiki-compat/README.md diff --git a/examples/osd/arduino-bh1750/arduino-example.c b/examples/osd/arduino-bh1750/arduino-example.c new file mode 100644 index 000000000..ea74dd8b8 --- /dev/null +++ b/examples/osd/arduino-bh1750/arduino-example.c @@ -0,0 +1,2 @@ +#include +AUTOSTART_PROCESSES(&arduino_sketch); diff --git a/examples/osd/arduino-bh1750/flash.sh b/examples/osd/arduino-bh1750/flash.sh new file mode 100755 index 000000000..e82962073 --- /dev/null +++ b/examples/osd/arduino-bh1750/flash.sh @@ -0,0 +1,2 @@ +#!/bin/bash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/led-strip/project-conf.h b/examples/osd/arduino-bh1750/project-conf.h similarity index 88% rename from examples/osd/led-strip/project-conf.h rename to examples/osd/arduino-bh1750/project-conf.h index e45478f02..e25aed53c 100644 --- a/examples/osd/led-strip/project-conf.h +++ b/examples/osd/arduino-bh1750/project-conf.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Matthias Kovatsch + * Copyright (c) 2010, Swedish Institute of Computer Science. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,20 +29,23 @@ * */ -#ifndef PROJECT_ERBIUM_CONF_H_ -#define PROJECT_ERBIUM_CONF_H_ +#ifndef PROJECT_RPL_WEB_CONF_H_ +#define PROJECT_RPL_WEB_CONF_H_ -#define PLATFORM_HAS_INFO 1 -#define PLATFORM_HAS_BATTERY 1 -//#define PLATFORM_HAS_DHT11TEMP 1 #define PLATFORM_HAS_LEDS 1 +//#define PLATFORM_HAS_BUTTON 1 +#define PLATFORM_HAS_BATTERY 1 + +#define SICSLOWPAN_CONF_FRAG 1 + +#define LOOP_INTERVAL (10 * CLOCK_SECOND) + +/* Save energy */ +//#define RDC_CONF_PT_YIELD_OFF /* For Debug: Dont allow MCU sleeping between channel checks */ -#undef RDC_CONF_MCU_SLEEP -#define RDC_CONF_MCU_SLEEP 0 - -/* Some platforms have weird includes. */ -#undef IEEE802154_CONF_PANID +//#undef RDC_CONF_MCU_SLEEP +//#define RDC_CONF_MCU_SLEEP 0 /* Disabling RDC for demo purposes. Core updates often require more memory. */ /* For projects, optimize memory and enable RDC again. */ @@ -99,4 +102,5 @@ #undef SICSLOWPAN_CONF_FRAG #define SICSLOWPAN_CONF_FRAG 1 */ -#endif /* PROJECT_ERBIUM_CONF_H_ */ + +#endif /* PROJECT_RPL_WEB_CONF_H_ */ diff --git a/examples/osd/arduino-bh1750/resources/res-bh1750.c b/examples/osd/arduino-bh1750/resources/res-bh1750.c new file mode 100644 index 000000000..ae47f07a5 --- /dev/null +++ b/examples/osd/arduino-bh1750/resources/res-bh1750.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Moisture resource + * \author + * Harald Pichler + */ + +#include "contiki.h" + +#include +#include "rest-engine.h" +#include "Arduino.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +/* A simple getter example. Returns the reading from the sensor with a simple etag */ +RESOURCE(res_bh1750, + "title=\"Lux status\";rt=\"Lux\"", + res_get_handler, + NULL, + NULL, + NULL); + +extern uint16_t lux; + + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + + unsigned int accept = -1; + REST.get_header_accept(request, &accept); + + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", lux); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'lux':%d}", lux); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + const char *msg = "Supporting content-types text/plain and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); + } +} diff --git a/examples/osd/led-strip/run.sh b/examples/osd/arduino-bh1750/run.sh similarity index 68% rename from examples/osd/led-strip/run.sh rename to examples/osd/arduino-bh1750/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/led-strip/run.sh +++ b/examples/osd/arduino-bh1750/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/arduino-bh1750/sketch.pde b/examples/osd/arduino-bh1750/sketch.pde new file mode 100644 index 000000000..775b96bce --- /dev/null +++ b/examples/osd/arduino-bh1750/sketch.pde @@ -0,0 +1,50 @@ +/* + * Sample arduino sketch using contiki features. + * We turn the LED off + * We allow read the moisture sensor + * Unfortunately sleeping for long times in loop() isn't currently + * possible, something turns off the CPU (including PWM outputs) if a + * Proto-Thread is taking too long. We need to find out how to sleep in + * a Contiki-compatible way. + * Note that for a normal arduino sketch you won't have to include any + * of the contiki-specific files here, the sketch should just work. + */ + +#include +#include "BH1750FVI.h" + +extern "C" { +#include "arduino-process.h" +#include "rest-engine.h" + +BH1750FVI lightMeter; + +extern resource_t res_bh1750, res_battery; +uint16_t lux; + +#define LED_PIN 4 +} + +void setup (void) +{ + // switch off the led + pinMode(LED_PIN, OUTPUT); + digitalWrite(LED_PIN, HIGH); + // BH1750 sensor + Wire.begin(); + lightMeter.begin(); + // init coap resourcen + rest_init_engine (); + rest_activate_resource (&res_bh1750, "s/lux"); + rest_activate_resource (&res_battery, "s/battery"); +} + +// at project-conf.h +// LOOP_INTERVAL (10 * CLOCK_SECOND) +void loop (void) +{ + mcu_sleep_off(); + lux = lightMeter.getLightLevel(); + printf("Lux: %d\n",lux); + mcu_sleep_on(); +} diff --git a/examples/osd/arduino-bmp085/Barometer.cpp b/examples/osd/arduino-bmp085/Barometer.cpp new file mode 100644 index 000000000..ec8b294a8 --- /dev/null +++ b/examples/osd/arduino-bmp085/Barometer.cpp @@ -0,0 +1,175 @@ +/* + Barometer library V1.0 + 2010 Copyright (c) Seeed Technology Inc. All right reserved. + + Original Author: LG + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "Barometer.h" +#include +#include + +void Barometer::init(void) +{ + Wire.begin(); +// Serial.print("Temperaturet: "); + ac1 = bmp085ReadInt(0xAA); + ac2 = bmp085ReadInt(0xAC); + ac3 = bmp085ReadInt(0xAE); + ac4 = bmp085ReadInt(0xB0); + ac5 = bmp085ReadInt(0xB2); + ac6 = bmp085ReadInt(0xB4); + b1 = bmp085ReadInt(0xB6); + b2 = bmp085ReadInt(0xB8); + mb = bmp085ReadInt(0xBA); + mc = bmp085ReadInt(0xBC); + md = bmp085ReadInt(0xBE); +// Serial.print("Temperaturet2: "); +} +// Read 1 byte from the BMP085 at 'address' +// Return: the read byte; +char Barometer::bmp085Read(unsigned char address) +{ + //Wire.begin(); + //unsigned char data; + Wire.beginTransmission(BMP085_ADDRESS); + Wire.write(address); + Wire.endTransmission(); + + Wire.requestFrom(BMP085_ADDRESS, 1); + while(!Wire.available()); + return Wire.read(); +} +// Read 2 bytes from the BMP085 +// First byte will be from 'address' +// Second byte will be from 'address'+1 +int Barometer::bmp085ReadInt(unsigned char address) +{ + unsigned char msb, lsb; + Wire.beginTransmission(BMP085_ADDRESS); + Wire.write(address); + Wire.endTransmission(); + Wire.requestFrom(BMP085_ADDRESS, 2); + while(Wire.available()<2); + msb = Wire.read(); + lsb = Wire.read(); + return (int) msb<<8 | lsb; +} +// Read the uncompensated temperature value +unsigned int Barometer::bmp085ReadUT() +{ + unsigned int ut; + Wire.beginTransmission(BMP085_ADDRESS); + Wire.write(0xF4); + Wire.write(0x2E); + Wire.endTransmission(); + delay(5); + ut = bmp085ReadInt(0xF6); + return ut; +} +// Read the uncompensated pressure value +unsigned long Barometer::bmp085ReadUP() +{ + unsigned char msb, lsb, xlsb; + unsigned long up = 0; + Wire.beginTransmission(BMP085_ADDRESS); + Wire.write(0xF4); + Wire.write(0x34 + (OSS<<6)); + Wire.endTransmission(); + delay(2 + (3<> (8-OSS); + return up; +} +void Barometer::writeRegister(int deviceAddress, byte address, byte val) +{ + Wire.beginTransmission(deviceAddress); // start transmission to device + Wire.write(address); // send register address + Wire.write(val); // send value to write + Wire.endTransmission(); // end transmission +} +int Barometer::readRegister(int deviceAddress, byte address) +{ + int v; + Wire.beginTransmission(deviceAddress); + Wire.write(address); // register to read + Wire.endTransmission(); + + Wire.requestFrom(deviceAddress, 1); // read a byte + + while(!Wire.available()) { + // waiting + } + + v = Wire.read(); + return v; +} +float Barometer::calcAltitude(float pressure) +{ + float A = pressure/101325; + float B = 1/5.25588; + float C = pow(A,B); + C = 1 - C; + C = C /0.0000225577; + return C; +} +float Barometer::bmp085GetTemperature(unsigned int ut) +{ + long x1, x2; + + x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15; + x2 = ((long)mc << 11)/(x1 + md); + PressureCompensate = x1 + x2; + + float temp = ((PressureCompensate + 8)>>4); + temp = temp /10; + + return temp; +} +long Barometer::bmp085GetPressure(unsigned long up) +{ + long x1, x2, x3, b3, b6, p; + unsigned long b4, b7; + b6 = PressureCompensate - 4000; + x1 = (b2 * (b6 * b6)>>12)>>11; + x2 = (ac2 * b6)>>11; + x3 = x1 + x2; + b3 = (((((long)ac1)*4 + x3)<>2; + + // Calculate B4 + x1 = (ac3 * b6)>>13; + x2 = (b1 * ((b6 * b6)>>12))>>16; + x3 = ((x1 + x2) + 2)>>2; + b4 = (ac4 * (unsigned long)(x3 + 32768))>>15; + + b7 = ((unsigned long)(up - b3) * (50000>>OSS)); + if (b7 < 0x80000000) + p = (b7<<1)/b4; + else + p = (b7/b4)<<1; + + x1 = (p>>8) * (p>>8); + x1 = (x1 * 3038)>>16; + x2 = (-7357 * p)>>16; + p += (x1 + x2 + 3791)>>4; + + long temp = p; + return temp; +} diff --git a/examples/osd/arduino-bmp085/Barometer.h b/examples/osd/arduino-bmp085/Barometer.h new file mode 100644 index 000000000..161702718 --- /dev/null +++ b/examples/osd/arduino-bmp085/Barometer.h @@ -0,0 +1,58 @@ +/* + Barometer library V1.0 + 2010 Copyright (c) Seeed Technology Inc. All right reserved. + + Original Author: LG + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef __BAROMETER_H__ +#define __BAROMETER_H__ + +#include +#include + +const unsigned char OSS = 0; +#define BMP085_ADDRESS 0x77 +class Barometer +{ +public: + void init(void); + long PressureCompensate; + float bmp085GetTemperature(unsigned int ut); + long bmp085GetPressure(unsigned long up); + float calcAltitude(float pressure); + unsigned int bmp085ReadUT(void); + unsigned long bmp085ReadUP(void); + +private: + int ac1; + int ac2; + int ac3; + unsigned int ac4; + unsigned int ac5; + unsigned int ac6; + int b1; + int b2; + int mb; + int mc; + int md; + char bmp085Read(unsigned char address); + int bmp085ReadInt(unsigned char address); + void writeRegister(int deviceAddress, byte address, byte val); + int readRegister(int deviceAddress, byte address); +}; + +#endif diff --git a/examples/osd/arduino-bmp085/Barometer_Sensor/Barometer.cpp b/examples/osd/arduino-bmp085/Barometer_Sensor/Barometer.cpp new file mode 100644 index 000000000..208f8b5a5 --- /dev/null +++ b/examples/osd/arduino-bmp085/Barometer_Sensor/Barometer.cpp @@ -0,0 +1,175 @@ +/* + Barometer library V1.0 + 2010 Copyright (c) Seeed Technology Inc. All right reserved. + + Original Author: LG + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "Barometer.h" +#include +#include + +void Barometer::init(void) +{ + Wire.begin(); + Serial.print("Temperaturet: "); + ac1 = bmp085ReadInt(0xAA); + ac2 = bmp085ReadInt(0xAC); + ac3 = bmp085ReadInt(0xAE); + ac4 = bmp085ReadInt(0xB0); + ac5 = bmp085ReadInt(0xB2); + ac6 = bmp085ReadInt(0xB4); + b1 = bmp085ReadInt(0xB6); + b2 = bmp085ReadInt(0xB8); + mb = bmp085ReadInt(0xBA); + mc = bmp085ReadInt(0xBC); + md = bmp085ReadInt(0xBE); + Serial.print("Temperaturet2: "); +} +// Read 1 byte from the BMP085 at 'address' +// Return: the read byte; +char Barometer::bmp085Read(unsigned char address) +{ + //Wire.begin(); + unsigned char data; + Wire.beginTransmission(BMP085_ADDRESS); + Wire.write(address); + Wire.endTransmission(); + + Wire.requestFrom(BMP085_ADDRESS, 1); + while(!Wire.available()); + return Wire.read(); +} +// Read 2 bytes from the BMP085 +// First byte will be from 'address' +// Second byte will be from 'address'+1 +int Barometer::bmp085ReadInt(unsigned char address) +{ + unsigned char msb, lsb; + Wire.beginTransmission(BMP085_ADDRESS); + Wire.write(address); + Wire.endTransmission(); + Wire.requestFrom(BMP085_ADDRESS, 2); + while(Wire.available()<2); + msb = Wire.read(); + lsb = Wire.read(); + return (int) msb<<8 | lsb; +} +// Read the uncompensated temperature value +unsigned int Barometer::bmp085ReadUT() +{ + unsigned int ut; + Wire.beginTransmission(BMP085_ADDRESS); + Wire.write(0xF4); + Wire.write(0x2E); + Wire.endTransmission(); + delay(5); + ut = bmp085ReadInt(0xF6); + return ut; +} +// Read the uncompensated pressure value +unsigned long Barometer::bmp085ReadUP() +{ + unsigned char msb, lsb, xlsb; + unsigned long up = 0; + Wire.beginTransmission(BMP085_ADDRESS); + Wire.write(0xF4); + Wire.write(0x34 + (OSS<<6)); + Wire.endTransmission(); + delay(2 + (3<> (8-OSS); + return up; +} +void Barometer::writeRegister(int deviceAddress, byte address, byte val) +{ + Wire.beginTransmission(deviceAddress); // start transmission to device + Wire.write(address); // send register address + Wire.write(val); // send value to write + Wire.endTransmission(); // end transmission +} +int Barometer::readRegister(int deviceAddress, byte address) +{ + int v; + Wire.beginTransmission(deviceAddress); + Wire.write(address); // register to read + Wire.endTransmission(); + + Wire.requestFrom(deviceAddress, 1); // read a byte + + while(!Wire.available()) { + // waiting + } + + v = Wire.read(); + return v; +} +float Barometer::calcAltitude(float pressure) +{ + float A = pressure/101325; + float B = 1/5.25588; + float C = pow(A,B); + C = 1 - C; + C = C /0.0000225577; + return C; +} +float Barometer::bmp085GetTemperature(unsigned int ut) +{ + long x1, x2; + + x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15; + x2 = ((long)mc << 11)/(x1 + md); + PressureCompensate = x1 + x2; + + float temp = ((PressureCompensate + 8)>>4); + temp = temp /10; + + return temp; +} +long Barometer::bmp085GetPressure(unsigned long up) +{ + long x1, x2, x3, b3, b6, p; + unsigned long b4, b7; + b6 = PressureCompensate - 4000; + x1 = (b2 * (b6 * b6)>>12)>>11; + x2 = (ac2 * b6)>>11; + x3 = x1 + x2; + b3 = (((((long)ac1)*4 + x3)<>2; + + // Calculate B4 + x1 = (ac3 * b6)>>13; + x2 = (b1 * ((b6 * b6)>>12))>>16; + x3 = ((x1 + x2) + 2)>>2; + b4 = (ac4 * (unsigned long)(x3 + 32768))>>15; + + b7 = ((unsigned long)(up - b3) * (50000>>OSS)); + if (b7 < 0x80000000) + p = (b7<<1)/b4; + else + p = (b7/b4)<<1; + + x1 = (p>>8) * (p>>8); + x1 = (x1 * 3038)>>16; + x2 = (-7357 * p)>>16; + p += (x1 + x2 + 3791)>>4; + + long temp = p; + return temp; +} diff --git a/examples/osd/arduino-bmp085/Barometer_Sensor/Barometer.h b/examples/osd/arduino-bmp085/Barometer_Sensor/Barometer.h new file mode 100644 index 000000000..161702718 --- /dev/null +++ b/examples/osd/arduino-bmp085/Barometer_Sensor/Barometer.h @@ -0,0 +1,58 @@ +/* + Barometer library V1.0 + 2010 Copyright (c) Seeed Technology Inc. All right reserved. + + Original Author: LG + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef __BAROMETER_H__ +#define __BAROMETER_H__ + +#include +#include + +const unsigned char OSS = 0; +#define BMP085_ADDRESS 0x77 +class Barometer +{ +public: + void init(void); + long PressureCompensate; + float bmp085GetTemperature(unsigned int ut); + long bmp085GetPressure(unsigned long up); + float calcAltitude(float pressure); + unsigned int bmp085ReadUT(void); + unsigned long bmp085ReadUP(void); + +private: + int ac1; + int ac2; + int ac3; + unsigned int ac4; + unsigned int ac5; + unsigned int ac6; + int b1; + int b2; + int mb; + int mc; + int md; + char bmp085Read(unsigned char address); + int bmp085ReadInt(unsigned char address); + void writeRegister(int deviceAddress, byte address, byte val); + int readRegister(int deviceAddress, byte address); +}; + +#endif diff --git a/examples/osd/arduino-bmp085/Barometer_Sensor/examples/Barometer_Sensor/Barometer_Sensor.ino b/examples/osd/arduino-bmp085/Barometer_Sensor/examples/Barometer_Sensor/Barometer_Sensor.ino new file mode 100644 index 000000000..7fe3b3ec5 --- /dev/null +++ b/examples/osd/arduino-bmp085/Barometer_Sensor/examples/Barometer_Sensor/Barometer_Sensor.ino @@ -0,0 +1,49 @@ +/* Barometer demo V1.0 +* Based largely on code by Jim Lindblom +* Get pressure, altitude, and temperature from the BMP085. +* Serial.print it out at 9600 baud to serial monitor. +* +* By:http://www.seeedstudio.com +*/ +#include "Barometer.h" +#include +float temperature; +float pressure; +float atm; +float altitude; +Barometer myBarometer; +void setup(){ + Serial.begin(9600); + myBarometer.init(); + +} + +void loop() +{ + temperature = myBarometer.bmp085GetTemperature(myBarometer.bmp085ReadUT()); //Get the temperature, bmp085ReadUT MUST be called first + pressure = myBarometer.bmp085GetPressure(myBarometer.bmp085ReadUP());//Get the temperature + altitude = myBarometer.calcAltitude(pressure); //Uncompensated caculation - in Meters + atm = pressure / 101325; + + Serial.print("Temperature: "); + Serial.print(temperature, 2); //display 2 decimal places + Serial.println("deg C"); + + Serial.print("Pressure: "); + Serial.print(pressure, 0); //whole number only. + Serial.println(" Pa"); + + Serial.print("Ralated Atmosphere: "); + Serial.println(atm, 4); //display 4 decimal places + + Serial.print("Altitude: "); + Serial.print(altitude, 2); //display 2 decimal places + Serial.println(" m"); + + Serial.println(); + + delay(1000); //wait a second and get values again. +} + + + diff --git a/examples/osd/arduino-bmp085/Makefile b/examples/osd/arduino-bmp085/Makefile new file mode 100644 index 000000000..b74569ff2 --- /dev/null +++ b/examples/osd/arduino-bmp085/Makefile @@ -0,0 +1,71 @@ +# Set this to the name of your sketch (without extension .pde) +SKETCH=sketch +EXE=arduino-example + +all: $(EXE) + +CONTIKI=../../.. + +# Contiki IPv6 configuration +CONTIKI_WITH_IPV6 = 1 + +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" +LFLAGS += -lm + +PROJECT_SOURCEFILES += ${SKETCH}.cpp Barometer.cpp + +# automatically build RESTful resources +REST_RESOURCES_DIR = ./resources +REST_RESOURCES_DIR_COMMON = ../resources-common +REST_RESOURCES_FILES= $(notdir \ + $(shell find $(REST_RESOURCES_DIR) -name '*.c') \ + $(shell find $(REST_RESOURCES_DIR_COMMON) -name '*.c') \ + ) + +PROJECTDIRS += $(REST_RESOURCES_DIR) $(REST_RESOURCES_DIR_COMMON) +PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) + +# variable for Makefile.include +ifneq ($(TARGET), minimal-net) +CFLAGS += -DUIP_CONF_IPV6_RPL=1 +else +# minimal-net does not support RPL under Linux and is mostly used to test CoAP only +${info INFO: compiling without RPL} +CFLAGS += -DUIP_CONF_IPV6_RPL=0 +CFLAGS += -DHARD_CODED_ADDRESS=\"fdfd::10\" +${info INFO: compiling with large buffers} +CFLAGS += -DUIP_CONF_BUFFER_SIZE=2048 +CFLAGS += -DREST_MAX_CHUNK_SIZE=1024 +CFLAGS += -DCOAP_MAX_HEADER_SIZE=640 +endif + +# linker optimizations +SMALL=1 + + +# REST Engine shall use Erbium CoAP implementation +APPS += er-coap +APPS += rest-engine +APPS += arduino + +include $(CONTIKI)/Makefile.include +include $(CONTIKI)/apps/arduino/Makefile.include + +$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c + (cd $(CONTIKI)/tools && $(MAKE) tunslip6) + +connect-router: $(CONTIKI)/tools/tunslip6 + sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64 + +connect-router-cooja: $(CONTIKI)/tools/tunslip6 + sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 aaaa::1/64 + +connect-minimal: + sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/arduino-bmp085/README.md b/examples/osd/arduino-bmp085/README.md new file mode 100644 index 000000000..e1490ed05 --- /dev/null +++ b/examples/osd/arduino-bmp085/README.md @@ -0,0 +1,11 @@ +Arduino compatibility example +============================= + +This example shows that it is now possible to re-use arduino sketches in +Contiki. This example documents the necessary magic. Arduino specifies +two routines, `setup` and `loop`. Before `setup` is called, the +framework initializes hardware. In original Arduino, all this is done in +a `main` function (in C). For contiki we define a process that does the +same. + +See the documentation file in apps/contiki-compat/README.md diff --git a/examples/osd/arduino-bmp085/arduino-example.c b/examples/osd/arduino-bmp085/arduino-example.c new file mode 100644 index 000000000..ea74dd8b8 --- /dev/null +++ b/examples/osd/arduino-bmp085/arduino-example.c @@ -0,0 +1,2 @@ +#include +AUTOSTART_PROCESSES(&arduino_sketch); diff --git a/examples/osd/arduino-bmp085/flash.sh b/examples/osd/arduino-bmp085/flash.sh new file mode 100755 index 000000000..e82962073 --- /dev/null +++ b/examples/osd/arduino-bmp085/flash.sh @@ -0,0 +1,2 @@ +#!/bin/bash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/arduino-bmp085/project-conf.h b/examples/osd/arduino-bmp085/project-conf.h new file mode 100644 index 000000000..e25aed53c --- /dev/null +++ b/examples/osd/arduino-bmp085/project-conf.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + */ + +#ifndef PROJECT_RPL_WEB_CONF_H_ +#define PROJECT_RPL_WEB_CONF_H_ + +#define PLATFORM_HAS_LEDS 1 +//#define PLATFORM_HAS_BUTTON 1 +#define PLATFORM_HAS_BATTERY 1 + +#define SICSLOWPAN_CONF_FRAG 1 + +#define LOOP_INTERVAL (10 * CLOCK_SECOND) + +/* Save energy */ +//#define RDC_CONF_PT_YIELD_OFF + +/* For Debug: Dont allow MCU sleeping between channel checks */ +//#undef RDC_CONF_MCU_SLEEP +//#define RDC_CONF_MCU_SLEEP 0 + +/* Disabling RDC for demo purposes. Core updates often require more memory. */ +/* For projects, optimize memory and enable RDC again. */ +// #undef NETSTACK_CONF_RDC +//#define NETSTACK_CONF_RDC nullrdc_driver + +/* Increase rpl-border-router IP-buffer when using more than 64. */ +#undef REST_MAX_CHUNK_SIZE +#define REST_MAX_CHUNK_SIZE 64 + +/* Estimate your header size, especially when using Proxy-Uri. */ +/* +#undef COAP_MAX_HEADER_SIZE +#define COAP_MAX_HEADER_SIZE 70 +*/ + +/* The IP buffer size must fit all other hops, in particular the border router. */ + +#undef UIP_CONF_BUFFER_SIZE +#define UIP_CONF_BUFFER_SIZE 256 + + +/* Multiplies with chunk size, be aware of memory constraints. */ +#undef COAP_MAX_OPEN_TRANSACTIONS +#define COAP_MAX_OPEN_TRANSACTIONS 4 + +/* Must be <= open transaction number, default is COAP_MAX_OPEN_TRANSACTIONS-1. */ +/* +#undef COAP_MAX_OBSERVERS +#define COAP_MAX_OBSERVERS 2 +*/ + +/* Filtering .well-known/core per query can be disabled to save space. */ +/* +#undef COAP_LINK_FORMAT_FILTERING +#define COAP_LINK_FORMAT_FILTERING 0 +*/ + +/* Save some memory for the sky platform. */ +/* +#undef NBR_TABLE_CONF_MAX_NEIGHBORS +#define NBR_TABLE_CONF_MAX_NEIGHBORS 10 +#undef UIP_CONF_MAX_ROUTES +#define UIP_CONF_MAX_ROUTES 10 +*/ + +/* Reduce 802.15.4 frame queue to save RAM. */ +/* +#undef QUEUEBUF_CONF_NUM +#define QUEUEBUF_CONF_NUM 4 +*/ + +/* +#undef SICSLOWPAN_CONF_FRAG +#define SICSLOWPAN_CONF_FRAG 1 +*/ + +#endif /* PROJECT_RPL_WEB_CONF_H_ */ diff --git a/examples/osd/arduino-bmp085/resources/res-bmp085alt.c b/examples/osd/arduino-bmp085/resources/res-bmp085alt.c new file mode 100644 index 000000000..de90eae4f --- /dev/null +++ b/examples/osd/arduino-bmp085/resources/res-bmp085alt.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Barometer resource + * \author + * Harald Pichler + */ + +#include "contiki.h" + +#include +#include "rest-engine.h" +#include "Arduino.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +/* A simple getter example. Returns the reading from the sensor with a simple etag */ +RESOURCE(res_bmp085alt, + "title=\"alt status\";rt=\"alt\"", + res_get_handler, + NULL, + NULL, + NULL); + +extern char bmp085alt_s[8]; + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + + unsigned int accept = -1; + REST.get_header_accept(request, &accept); + + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", bmp085alt_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'temperature':%s}", bmp085alt_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + const char *msg = "Supporting content-types text/plain and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); + } +} diff --git a/examples/osd/arduino-bmp085/resources/res-bmp085atm.c b/examples/osd/arduino-bmp085/resources/res-bmp085atm.c new file mode 100644 index 000000000..b97cffe6e --- /dev/null +++ b/examples/osd/arduino-bmp085/resources/res-bmp085atm.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Barometer resource + * \author + * Harald Pichler + */ + +#include "contiki.h" + +#include +#include "rest-engine.h" +#include "Arduino.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +/* A simple getter example. Returns the reading from the sensor with a simple etag */ +RESOURCE(res_bmp085atm, + "title=\"atm status\";rt=\"atm\"", + res_get_handler, + NULL, + NULL, + NULL); + +extern char bmp085atm_s[8]; + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + + unsigned int accept = -1; + REST.get_header_accept(request, &accept); + + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", bmp085atm_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'temperature':%s}", bmp085atm_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + const char *msg = "Supporting content-types text/plain and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); + } +} diff --git a/examples/osd/arduino-bmp085/resources/res-bmp085press.c b/examples/osd/arduino-bmp085/resources/res-bmp085press.c new file mode 100644 index 000000000..6a02f4bf0 --- /dev/null +++ b/examples/osd/arduino-bmp085/resources/res-bmp085press.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Barometer resource + * \author + * Harald Pichler + */ + +#include "contiki.h" + +#include +#include "rest-engine.h" +#include "Arduino.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +/* A simple getter example. Returns the reading from the sensor with a simple etag */ +RESOURCE(res_bmp085press, + "title=\"pressure status\";rt=\"pressure\"", + res_get_handler, + NULL, + NULL, + NULL); + +extern char bmp085press_s[8]; + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + + unsigned int accept = -1; + REST.get_header_accept(request, &accept); + + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", bmp085press_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'pressure':%s}", bmp085press_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + const char *msg = "Supporting content-types text/plain and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); + } +} diff --git a/examples/osd/arduino-bmp085/resources/res-bmp085temp.c b/examples/osd/arduino-bmp085/resources/res-bmp085temp.c new file mode 100644 index 000000000..f0e45f810 --- /dev/null +++ b/examples/osd/arduino-bmp085/resources/res-bmp085temp.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Barometer resource + * \author + * Harald Pichler + */ + +#include "contiki.h" + +#include +#include "rest-engine.h" +#include "Arduino.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +/* A simple getter example. Returns the reading from the sensor with a simple etag */ +RESOURCE(res_bmp085temp, + "title=\"Temperature status\";rt=\"Temperatur\"", + res_get_handler, + NULL, + NULL, + NULL); + +extern char bmp085temp_s[8]; + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + + unsigned int accept = -1; + REST.get_header_accept(request, &accept); + + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", bmp085temp_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'temperature':%s}", bmp085temp_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + const char *msg = "Supporting content-types text/plain and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); + } +} diff --git a/examples/osd/arduino-bmp085/run.sh b/examples/osd/arduino-bmp085/run.sh new file mode 100755 index 000000000..5d5cbbbb4 --- /dev/null +++ b/examples/osd/arduino-bmp085/run.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# For the ages-old bootloader (before 2014) you want to use +# BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/arduino-bmp085/sketch.pde b/examples/osd/arduino-bmp085/sketch.pde new file mode 100644 index 000000000..c84a488a9 --- /dev/null +++ b/examples/osd/arduino-bmp085/sketch.pde @@ -0,0 +1,86 @@ +/* + * Sample arduino sketch using contiki features. + * We turn the LED off + * We allow read the moisture sensor + * Unfortunately sleeping for long times in loop() isn't currently + * possible, something turns off the CPU (including PWM outputs) if a + * Proto-Thread is taking too long. We need to find out how to sleep in + * a Contiki-compatible way. + * Note that for a normal arduino sketch you won't have to include any + * of the contiki-specific files here, the sketch should just work. + */ + +#include +#include "Barometer.h" + +extern "C" { +#include "arduino-process.h" +#include "rest-engine.h" + +extern resource_t res_bmp085temp,res_bmp085press,res_bmp085atm,res_bmp085alt, res_battery; + +float bmp085temp; +float bmp085press; +float bmp085atm; +float bmp085alt; +char bmp085temp_s[8]; +char bmp085press_s[8]; +char bmp085atm_s[8]; +char bmp085alt_s[8]; + +Barometer myBarometer; + +#define LED_PIN 4 +} + +void setup (void) +{ + // switch off the led + pinMode(LED_PIN, OUTPUT); + digitalWrite(LED_PIN, HIGH); + // BMP085 sensor + myBarometer.init(); + // init coap resourcen + rest_init_engine (); + rest_activate_resource (&res_bmp085temp, "s/temp"); + rest_activate_resource (&res_bmp085press, "s/press"); + rest_activate_resource (&res_bmp085atm, "s/atm"); + rest_activate_resource (&res_bmp085alt, "s/alt"); + rest_activate_resource (&res_battery, "s/battery"); +} + +// at project-conf.h +// LOOP_INTERVAL (10 * CLOCK_SECOND) +void loop (void) +{ + mcu_sleep_off(); + bmp085temp = myBarometer.bmp085GetTemperature(myBarometer.bmp085ReadUT()); //Get the temperature, bmp085ReadUT MUST be called first + bmp085press = myBarometer.bmp085GetPressure(myBarometer.bmp085ReadUP());//Get the temperature + bmp085alt = myBarometer.calcAltitude(bmp085press); //Uncompensated caculation - in Meters + bmp085atm = bmp085press / 101325; + + dtostrf(bmp085temp , 6, 2, bmp085temp_s ); + dtostrf(bmp085press , 6, 2, bmp085press_s ); + dtostrf(bmp085alt , 6, 2, bmp085alt_s ); + dtostrf(bmp085atm , 6, 2, bmp085atm_s ); + // remove space + if(bmp085temp_s[0]==' '){ + memcpy (bmp085temp_s,bmp085temp_s+1,strlen(bmp085temp_s)+1); + } + if(bmp085press_s[0]==' '){ + memcpy (bmp085press_s,bmp085press_s+1,strlen(bmp085press_s)+1); + } + if(bmp085alt_s[0]==' '){ + memcpy (bmp085alt_s,bmp085alt_s+1,strlen(bmp085alt_s)+1); + } + if(bmp085atm_s[0]==' '){ + memcpy (bmp085atm_s,bmp085atm_s+1,strlen(bmp085atm_s)+1); + } + +// Debug Print + printf("Temp: %s",bmp085temp_s); + printf("\t\tPress: %s\n",bmp085press_s); + printf("\t\tAltitude: %s\n",bmp085alt_s); + printf("\t\tatm: %s\n",bmp085atm_s); + mcu_sleep_on(); +} diff --git a/examples/osd/arduino-climate3/Makefile b/examples/osd/arduino-climate3/Makefile index eb3d964f4..540913919 100644 --- a/examples/osd/arduino-climate3/Makefile +++ b/examples/osd/arduino-climate3/Makefile @@ -1,18 +1,11 @@ # Set this to the name of your sketch (without extension .pde) SKETCH=sketch +EXE=arduino-example -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size arduino-example.osd-merkur.hex \ - arduino-example.osd-merkur.eep -endif - -all: arduino-example $(PLATFORM_FILES) +all: $(EXE) CONTIKI=../../.. -# Contiki IPv6 configuration -CONTIKI_WITH_IPV6 = 1 - CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" LFLAGS += -lm @@ -29,59 +22,33 @@ REST_RESOURCES_FILES= $(notdir \ PROJECTDIRS += $(REST_RESOURCES_DIR) $(REST_RESOURCES_DIR_COMMON) PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) -# variable for Makefile.include -ifneq ($(TARGET), minimal-net) -CFLAGS += -DUIP_CONF_IPV6_RPL=1 -else -# minimal-net does not support RPL under Linux and is mostly used to test CoAP only -${info INFO: compiling without RPL} -CFLAGS += -DUIP_CONF_IPV6_RPL=0 -CFLAGS += -DHARD_CODED_ADDRESS=\"fdfd::10\" -${info INFO: compiling with large buffers} -CFLAGS += -DUIP_CONF_BUFFER_SIZE=2048 -CFLAGS += -DREST_MAX_CHUNK_SIZE=1024 -CFLAGS += -DCOAP_MAX_HEADER_SIZE=640 -endif - # linker optimizations SMALL=1 - # REST Engine shall use Erbium CoAP implementation APPS += er-coap APPS += rest-engine APPS += arduino +CONTIKI_WITH_IPV6 = 1 include $(CONTIKI)/Makefile.include include $(CONTIKI)/apps/arduino/Makefile.include -avr-size: arduino-example.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 arduino-example.osd-merkur - -arduino-example.osd-merkur.hex: arduino-example.osd-merkur - avr-objcopy -j .text -j .data -O ihex arduino-example.osd-merkur \ - arduino-example.osd-merkur.hex - -arduino-example.osd-merkur.eep: arduino-example.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - arduino-example.osd-merkur arduino-example.osd-merkur.eep - -flash: arduino-example.osd-merkur.hex arduino-example.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:arduino-example.osd-merkur.hex:a -U \ - eeprom:w:arduino-example.osd-merkur.eep:a - -.PHONY: flash avr-size - -$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c +$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) connect-router: $(CONTIKI)/tools/tunslip6 sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64 -connect-router-cooja: $(CONTIKI)/tools/tunslip6 +connect-router-cooja: $(CONTIKI)/tools/tunslip6 sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 aaaa::1/64 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/arduino-climate3/flash.sh b/examples/osd/arduino-climate3/flash.sh index e9cb40bfc..e82962073 100755 --- a/examples/osd/arduino-climate3/flash.sh +++ b/examples/osd/arduino-climate3/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -make TARGET=osd-merkur flash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/arduino-climate3/run.sh b/examples/osd/arduino-climate3/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/arduino-climate3/run.sh +++ b/examples/osd/arduino-climate3/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/arduino-climate3/sketch.pde b/examples/osd/arduino-climate3/sketch.pde index fd1bee2c0..9f9cb22d7 100644 --- a/examples/osd/arduino-climate3/sketch.pde +++ b/examples/osd/arduino-climate3/sketch.pde @@ -17,12 +17,10 @@ extern "C" { - +#include "arduino-process.h" #include "rest-engine.h" #include "sketch.h" -extern volatile uint8_t mcusleepcycle; // default 16 - // Data wire is plugged into port 2 on the Arduino #define ONE_WIRE_BUS 3 #define TEMPERATURE_PRECISION 9 @@ -130,7 +128,7 @@ void setup (void) // LOOP_INTERVAL (20 * CLOCK_SECOND) void loop (void) { - mcusleepcycle=0; // dont sleep + mcu_sleep_off(); // call sensors.requestTemperatures() to issue a global temperature // request to all devices on the bus // printf("Requesting temperatures..."); @@ -156,5 +154,5 @@ void loop (void) printf("Temp: %s",htu21d_temp_s); printf("\t\tHum: %s\n",htu21d_hum_s); - mcusleepcycle=32; // sleep, wakeup every 32 cycles + mcu_sleep_on(); } diff --git a/examples/osd/arduino-dallastemp/Makefile b/examples/osd/arduino-dallastemp/Makefile index 6d55a10a7..f1741488c 100644 --- a/examples/osd/arduino-dallastemp/Makefile +++ b/examples/osd/arduino-dallastemp/Makefile @@ -1,12 +1,8 @@ # Set this to the name of your sketch (without extension .pde) SKETCH=sketch +EXE=arduino-example -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size arduino-example.osd-merkur.hex \ - arduino-example.osd-merkur.eep -endif - -all: arduino-example $(PLATFORM_FILES) +all: $(EXE) CONTIKI=../../.. @@ -55,25 +51,6 @@ APPS += arduino include $(CONTIKI)/Makefile.include include $(CONTIKI)/apps/arduino/Makefile.include -avr-size: arduino-example.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 arduino-example.osd-merkur - -arduino-example.osd-merkur.hex: arduino-example.osd-merkur - avr-objcopy -j .text -j .data -O ihex arduino-example.osd-merkur \ - arduino-example.osd-merkur.hex - -arduino-example.osd-merkur.eep: arduino-example.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - arduino-example.osd-merkur arduino-example.osd-merkur.eep - -flash: arduino-example.osd-merkur.hex arduino-example.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:arduino-example.osd-merkur.hex:a -U \ - eeprom:w:arduino-example.osd-merkur.eep:a - -.PHONY: flash avr-size - $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -85,3 +62,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/arduino-dallastemp/flash.sh b/examples/osd/arduino-dallastemp/flash.sh index e9cb40bfc..e82962073 100755 --- a/examples/osd/arduino-dallastemp/flash.sh +++ b/examples/osd/arduino-dallastemp/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -make TARGET=osd-merkur flash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/arduino-dallastemp/run.sh b/examples/osd/arduino-dallastemp/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/arduino-dallastemp/run.sh +++ b/examples/osd/arduino-dallastemp/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/arduino-dallastemp/sketch.pde b/examples/osd/arduino-dallastemp/sketch.pde index 0aaff48e2..37f5c4413 100644 --- a/examples/osd/arduino-dallastemp/sketch.pde +++ b/examples/osd/arduino-dallastemp/sketch.pde @@ -15,7 +15,7 @@ extern "C" { - +#include "arduino-process.h" #include "rest-engine.h" #include "sketch.h" @@ -161,7 +161,7 @@ void setup (void) // LOOP_INTERVAL (10 * CLOCK_SECOND) void loop (void) { - mcusleepcycle=0; // dont sleep + mcu_sleep_off(); // call sensors.requestTemperatures() to issue a global temperature // request to all devices on the bus printf("Requesting temperatures..."); @@ -171,7 +171,7 @@ void loop (void) // print the device information printData(insideThermometer,0); printData(outsideThermometer,1); - mcusleepcycle=32; // sleep, wakeup every 32 cycles + mcu_sleep_on(); // debug only } diff --git a/examples/osd/arduino-distance/Makefile b/examples/osd/arduino-distance/Makefile index 70153c277..5a017eac0 100644 --- a/examples/osd/arduino-distance/Makefile +++ b/examples/osd/arduino-distance/Makefile @@ -1,12 +1,8 @@ # Set this to the name of your sketch (without extension .pde) SKETCH=sketch +EXE=arduino-example -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size arduino-example.osd-merkur.hex \ - arduino-example.osd-merkur.eep -endif - -all: arduino-example $(PLATFORM_FILES) +all: $(EXE) CONTIKI=../../.. @@ -54,25 +50,6 @@ APPS += arduino include $(CONTIKI)/Makefile.include include $(CONTIKI)/apps/arduino/Makefile.include -avr-size: arduino-example.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 arduino-example.osd-merkur - -arduino-example.osd-merkur.hex: arduino-example.osd-merkur - avr-objcopy -j .text -j .data -O ihex arduino-example.osd-merkur \ - arduino-example.osd-merkur.hex - -arduino-example.osd-merkur.eep: arduino-example.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - arduino-example.osd-merkur arduino-example.osd-merkur.eep - -flash: arduino-example.osd-merkur.hex arduino-example.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/tty.usbserial-AE01CZ7S -b57600 -e -U \ - flash:w:arduino-example.osd-merkur.hex:a -U \ - eeprom:w:arduino-example.osd-merkur.eep:a - -.PHONY: flash avr-size - $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -84,3 +61,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/arduino-distance/flash.sh b/examples/osd/arduino-distance/flash.sh index e9cb40bfc..e82962073 100755 --- a/examples/osd/arduino-distance/flash.sh +++ b/examples/osd/arduino-distance/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -make TARGET=osd-merkur flash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/arduino-distance/run.sh b/examples/osd/arduino-distance/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/arduino-distance/run.sh +++ b/examples/osd/arduino-distance/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/arduino-distance/sketch.pde b/examples/osd/arduino-distance/sketch.pde index 2233e0a7b..11d268b1c 100644 --- a/examples/osd/arduino-distance/sketch.pde +++ b/examples/osd/arduino-distance/sketch.pde @@ -11,11 +11,11 @@ */ extern "C" { +#include "arduino-process.h" #include "sketch.h" #include "rest-engine.h" #include "net/netstack.h" -extern volatile uint8_t mcusleepcycle; // default 16 extern resource_t res_battery, res_distance; #define LED_PIN 4 /* LED Pin */ @@ -39,8 +39,8 @@ void setup (void) void loop (void) { - mcusleepcycle=0; // dont sleep - - mcusleepcycle=16; // sleep, wakeup every 32 cycles + mcu_sleep_off(); + + mcu_sleep_on(); } diff --git a/examples/osd/arduino-dooralert/Makefile b/examples/osd/arduino-dooralert/Makefile index 7dc5c26a1..5a017eac0 100644 --- a/examples/osd/arduino-dooralert/Makefile +++ b/examples/osd/arduino-dooralert/Makefile @@ -1,12 +1,8 @@ # Set this to the name of your sketch (without extension .pde) SKETCH=sketch +EXE=arduino-example -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size arduino-example.osd-merkur.hex \ - arduino-example.osd-merkur.eep -endif - -all: arduino-example $(PLATFORM_FILES) +all: $(EXE) CONTIKI=../../.. @@ -54,25 +50,6 @@ APPS += arduino include $(CONTIKI)/Makefile.include include $(CONTIKI)/apps/arduino/Makefile.include -avr-size: arduino-example.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 arduino-example.osd-merkur - -arduino-example.osd-merkur.hex: arduino-example.osd-merkur - avr-objcopy -j .text -j .data -O ihex arduino-example.osd-merkur \ - arduino-example.osd-merkur.hex - -arduino-example.osd-merkur.eep: arduino-example.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - arduino-example.osd-merkur arduino-example.osd-merkur.eep - -flash: arduino-example.osd-merkur.hex arduino-example.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:arduino-example.osd-merkur.hex:a -U \ - eeprom:w:arduino-example.osd-merkur.eep:a - -.PHONY: flash avr-size - $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -84,3 +61,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/arduino-dooralert/flash.sh b/examples/osd/arduino-dooralert/flash.sh index e9cb40bfc..e82962073 100755 --- a/examples/osd/arduino-dooralert/flash.sh +++ b/examples/osd/arduino-dooralert/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -make TARGET=osd-merkur flash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/arduino-dooralert/run.sh b/examples/osd/arduino-dooralert/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/arduino-dooralert/run.sh +++ b/examples/osd/arduino-dooralert/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/arduino-dooralert/sketch.pde b/examples/osd/arduino-dooralert/sketch.pde index 67603c19a..d7de583c8 100644 --- a/examples/osd/arduino-dooralert/sketch.pde +++ b/examples/osd/arduino-dooralert/sketch.pde @@ -11,6 +11,7 @@ */ extern "C" { +#include "arduino-process.h" #include "rest-engine.h" extern resource_t res_door, res_battery; @@ -29,9 +30,12 @@ void setup (void) rest_init_engine (); rest_activate_resource (&res_door, "s/door"); rest_activate_resource (&res_battery, "s/battery"); + // NETSTACK_MAC.off(1); } void loop (void) { - + mcu_sleep_off(); + + mcu_sleep_on(); } diff --git a/examples/osd/arduino-htu21/Makefile b/examples/osd/arduino-htu21/Makefile index cdf737098..b44ef11f1 100644 --- a/examples/osd/arduino-htu21/Makefile +++ b/examples/osd/arduino-htu21/Makefile @@ -1,12 +1,8 @@ # Set this to the name of your sketch (without extension .pde) SKETCH=sketch +EXE=arduino-example -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size arduino-example.osd-merkur.hex \ - arduino-example.osd-merkur.eep -endif - -all: arduino-example $(PLATFORM_FILES) +all: $(EXE) CONTIKI=../../.. @@ -55,25 +51,6 @@ APPS += arduino include $(CONTIKI)/Makefile.include include $(CONTIKI)/apps/arduino/Makefile.include -avr-size: arduino-example.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 arduino-example.osd-merkur - -arduino-example.osd-merkur.hex: arduino-example.osd-merkur - avr-objcopy -j .text -j .data -O ihex arduino-example.osd-merkur \ - arduino-example.osd-merkur.hex - -arduino-example.osd-merkur.eep: arduino-example.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - arduino-example.osd-merkur arduino-example.osd-merkur.eep - -flash: arduino-example.osd-merkur.hex arduino-example.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:arduino-example.osd-merkur.hex:a -U \ - eeprom:w:arduino-example.osd-merkur.eep:a - -.PHONY: flash avr-size - $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -85,3 +62,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/arduino-htu21/flash.sh b/examples/osd/arduino-htu21/flash.sh index e9cb40bfc..e82962073 100755 --- a/examples/osd/arduino-htu21/flash.sh +++ b/examples/osd/arduino-htu21/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -make TARGET=osd-merkur flash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/arduino-htu21/run.sh b/examples/osd/arduino-htu21/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/arduino-htu21/run.sh +++ b/examples/osd/arduino-htu21/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/arduino-htu21/sketch.pde b/examples/osd/arduino-htu21/sketch.pde index 93dc1d1c3..4ea3500ea 100644 --- a/examples/osd/arduino-htu21/sketch.pde +++ b/examples/osd/arduino-htu21/sketch.pde @@ -14,12 +14,9 @@ #include "Adafruit_HTU21DF.h" extern "C" { - - +#include "arduino-process.h" #include "rest-engine.h" -extern volatile uint8_t mcusleepcycle; // default 16 - Adafruit_HTU21DF htu = Adafruit_HTU21DF(); extern resource_t res_htu21dtemp, res_htu21dhum, res_battery; @@ -51,19 +48,19 @@ void setup (void) // LOOP_INTERVAL (10 * CLOCK_SECOND) void loop (void) { - mcusleepcycle=0; // dont sleep - htu21d_temp = htu.readTemperature(); - htu21d_hum = htu.readHumidity(); - mcusleepcycle=32; // sleep, wakeup every 32 cycles - dtostrf(htu21d_temp , 6, 2, htu21d_temp_s ); - dtostrf(htu21d_hum , 6, 2, htu21d_hum_s ); - // remove space - if(htu21d_temp_s[0]==' '){ - memcpy (htu21d_temp_s,htu21d_temp_s+1,strlen(htu21d_temp_s)+1); - } - if(htu21d_hum_s[0]==' '){ + mcu_sleep_off(); + htu21d_temp = htu.readTemperature(); + htu21d_hum = htu.readHumidity(); + mcu_sleep_on(); + dtostrf(htu21d_temp , 6, 2, htu21d_temp_s ); + dtostrf(htu21d_hum , 6, 2, htu21d_hum_s ); + // remove space + if(htu21d_temp_s[0]==' '){ + memcpy (htu21d_temp_s,htu21d_temp_s+1,strlen(htu21d_temp_s)+1); + } + if(htu21d_hum_s[0]==' '){ memcpy (htu21d_hum_s,htu21d_hum_s+1,strlen(htu21d_hum_s)+1); - } + } // debug only // printf("Temp: %s",htu21d_temp_s); diff --git a/examples/osd/arduino-ledstrip/Makefile b/examples/osd/arduino-ledstrip/Makefile index 09e4a28a5..f03fdfc85 100644 --- a/examples/osd/arduino-ledstrip/Makefile +++ b/examples/osd/arduino-ledstrip/Makefile @@ -1,12 +1,8 @@ # Set this to the name of your sketch (without extension .pde) SKETCH=sketch +EXE=arduino-example -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size arduino-example.osd-merkur.hex \ - arduino-example.osd-merkur.eep -endif - -all: arduino-example $(PLATFORM_FILES) +all: $(EXE) CONTIKI=../../.. @@ -55,25 +51,6 @@ APPS += json json-resource include $(CONTIKI)/Makefile.include include $(CONTIKI)/apps/arduino/Makefile.include -avr-size: arduino-example.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 arduino-example.osd-merkur - -arduino-example.osd-merkur.hex: arduino-example.osd-merkur - avr-objcopy -j .text -j .data -O ihex arduino-example.osd-merkur \ - arduino-example.osd-merkur.hex - -arduino-example.osd-merkur.eep: arduino-example.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - arduino-example.osd-merkur arduino-example.osd-merkur.eep - -flash: arduino-example.osd-merkur.hex arduino-example.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:arduino-example.osd-merkur.hex:a -U \ - eeprom:w:arduino-example.osd-merkur.eep:a - -.PHONY: flash avr-size - $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -86,3 +63,9 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/arduino-ledstrip/flash.sh b/examples/osd/arduino-ledstrip/flash.sh index e9cb40bfc..e82962073 100755 --- a/examples/osd/arduino-ledstrip/flash.sh +++ b/examples/osd/arduino-ledstrip/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -make TARGET=osd-merkur flash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/arduino-ledstrip/run.sh b/examples/osd/arduino-ledstrip/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/arduino-ledstrip/run.sh +++ b/examples/osd/arduino-ledstrip/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/arduino-merkurboard/Makefile b/examples/osd/arduino-merkurboard/Makefile index 7dc5c26a1..5a017eac0 100644 --- a/examples/osd/arduino-merkurboard/Makefile +++ b/examples/osd/arduino-merkurboard/Makefile @@ -1,12 +1,8 @@ # Set this to the name of your sketch (without extension .pde) SKETCH=sketch +EXE=arduino-example -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size arduino-example.osd-merkur.hex \ - arduino-example.osd-merkur.eep -endif - -all: arduino-example $(PLATFORM_FILES) +all: $(EXE) CONTIKI=../../.. @@ -54,25 +50,6 @@ APPS += arduino include $(CONTIKI)/Makefile.include include $(CONTIKI)/apps/arduino/Makefile.include -avr-size: arduino-example.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 arduino-example.osd-merkur - -arduino-example.osd-merkur.hex: arduino-example.osd-merkur - avr-objcopy -j .text -j .data -O ihex arduino-example.osd-merkur \ - arduino-example.osd-merkur.hex - -arduino-example.osd-merkur.eep: arduino-example.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - arduino-example.osd-merkur arduino-example.osd-merkur.eep - -flash: arduino-example.osd-merkur.hex arduino-example.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:arduino-example.osd-merkur.hex:a -U \ - eeprom:w:arduino-example.osd-merkur.eep:a - -.PHONY: flash avr-size - $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -84,3 +61,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/arduino-merkurboard/flash.sh b/examples/osd/arduino-merkurboard/flash.sh index e9cb40bfc..e82962073 100755 --- a/examples/osd/arduino-merkurboard/flash.sh +++ b/examples/osd/arduino-merkurboard/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -make TARGET=osd-merkur flash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/arduino-merkurboard/resources/res-led.c b/examples/osd/arduino-merkurboard/resources/res-led.c new file mode 100644 index 000000000..fb0fa138f --- /dev/null +++ b/examples/osd/arduino-merkurboard/resources/res-led.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Door resource + * \author + * Harald Pichler + */ + +#include "contiki.h" + +#include +#include "rest-engine.h" +#include "Arduino.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); +static void res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +/* A simple getter example. Returns the reading from the sensor with a simple etag */ +RESOURCE(res_led, + "title=\"LED: , POST/PUT mode=on|off\";rt=\"Control\"", + res_get_handler, + res_post_put_handler, + res_post_put_handler, + NULL); + +extern uint8_t led_pin; +extern uint8_t led_status; + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + unsigned int accept = -1; + REST.get_header_accept(request, &accept); + + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", led_status); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'led':%d}", led_status); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + const char *msg = "Supporting content-types text/plain and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); + } +} + +static void +res_post_put_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + size_t len = 0; + const char *mode = NULL; + int success = 1; + + if(success && (len = REST.get_post_variable(request, "mode", &mode))) { + if(strncmp(mode, "on", len) == 0) { + digitalWrite(led_pin, LOW); + led_status=1; + } else if(strncmp(mode, "off", len) == 0) { + digitalWrite(led_pin, HIGH); + led_status=0; + } else { + success = 0; + } + } else { + success = 0; + } if(!success) { + REST.set_response_status(response, REST.status.BAD_REQUEST); + } +} diff --git a/examples/osd/arduino-merkurboard/run.sh b/examples/osd/arduino-merkurboard/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/arduino-merkurboard/run.sh +++ b/examples/osd/arduino-merkurboard/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/arduino-merkurboard/sketch.pde b/examples/osd/arduino-merkurboard/sketch.pde index 0f60b8dad..41df5a847 100644 --- a/examples/osd/arduino-merkurboard/sketch.pde +++ b/examples/osd/arduino-merkurboard/sketch.pde @@ -11,26 +11,25 @@ */ extern "C" { +#include "arduino-process.h" #include "rest-engine.h" #include "net/netstack.h" -extern volatile uint8_t mcusleepcycle; // default 16 +extern resource_t res_led, res_battery, res_cputemp; -extern resource_t res_leds, res_battery, res_cputemp; -uint8_t door_pin = 3; -uint8_t door_status = 0; - -#define LED_PIN 4 +uint8_t led_pin=4; +uint8_t led_status; } void setup (void) { // switch off the led - pinMode(LED_PIN, OUTPUT); - digitalWrite(LED_PIN, HIGH); + pinMode(led_pin, OUTPUT); + digitalWrite(led_pin, HIGH); + led_status=0; // init coap resourcen rest_init_engine (); - rest_activate_resource (&res_leds, "s/leds"); + rest_activate_resource (&res_led, "s/led"); rest_activate_resource (&res_battery, "s/battery"); rest_activate_resource (&res_cputemp, "s/cputemp"); @@ -39,7 +38,7 @@ void setup (void) void loop (void) { - mcusleepcycle=0; - - mcusleepcycle=16; + mcu_sleep_off(); + + mcu_sleep_on(); } diff --git a/examples/osd/arduino-plantobserving/Makefile b/examples/osd/arduino-plantobserving/Makefile index 7dc5c26a1..5a017eac0 100644 --- a/examples/osd/arduino-plantobserving/Makefile +++ b/examples/osd/arduino-plantobserving/Makefile @@ -1,12 +1,8 @@ # Set this to the name of your sketch (without extension .pde) SKETCH=sketch +EXE=arduino-example -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size arduino-example.osd-merkur.hex \ - arduino-example.osd-merkur.eep -endif - -all: arduino-example $(PLATFORM_FILES) +all: $(EXE) CONTIKI=../../.. @@ -54,25 +50,6 @@ APPS += arduino include $(CONTIKI)/Makefile.include include $(CONTIKI)/apps/arduino/Makefile.include -avr-size: arduino-example.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 arduino-example.osd-merkur - -arduino-example.osd-merkur.hex: arduino-example.osd-merkur - avr-objcopy -j .text -j .data -O ihex arduino-example.osd-merkur \ - arduino-example.osd-merkur.hex - -arduino-example.osd-merkur.eep: arduino-example.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - arduino-example.osd-merkur arduino-example.osd-merkur.eep - -flash: arduino-example.osd-merkur.hex arduino-example.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:arduino-example.osd-merkur.hex:a -U \ - eeprom:w:arduino-example.osd-merkur.eep:a - -.PHONY: flash avr-size - $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -84,3 +61,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/arduino-plantobserving/flash.sh b/examples/osd/arduino-plantobserving/flash.sh index e9cb40bfc..e82962073 100755 --- a/examples/osd/arduino-plantobserving/flash.sh +++ b/examples/osd/arduino-plantobserving/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -make TARGET=osd-merkur flash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/arduino-plantobserving/run.sh b/examples/osd/arduino-plantobserving/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/arduino-plantobserving/run.sh +++ b/examples/osd/arduino-plantobserving/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/arduino-roller/Makefile b/examples/osd/arduino-roller/Makefile index 254357fd9..5ffe58cad 100644 --- a/examples/osd/arduino-roller/Makefile +++ b/examples/osd/arduino-roller/Makefile @@ -1,12 +1,8 @@ # Set this to the name of your sketch (without extension .pde) SKETCH=sketch +EXE=arduino-example -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size arduino-example.osd-merkur.hex \ - arduino-example.osd-merkur.eep -endif - -all: arduino-example $(PLATFORM_FILES) +all: $(EXE) CONTIKI=../../.. @@ -54,25 +50,6 @@ APPS += arduino include $(CONTIKI)/Makefile.include include $(CONTIKI)/apps/arduino/Makefile.include -avr-size: arduino-example.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 arduino-example.osd-merkur - -arduino-example.osd-merkur.hex: arduino-example.osd-merkur - avr-objcopy -j .text -j .data -O ihex arduino-example.osd-merkur \ - arduino-example.osd-merkur.hex - -arduino-example.osd-merkur.eep: arduino-example.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - arduino-example.osd-merkur arduino-example.osd-merkur.eep - -flash: arduino-example.osd-merkur.hex arduino-example.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:arduino-example.osd-merkur.hex:a -U \ - eeprom:w:arduino-example.osd-merkur.eep:a - -.PHONY: flash avr-size - $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -84,3 +61,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/arduino-roller/flash.sh b/examples/osd/arduino-roller/flash.sh index e9cb40bfc..e82962073 100755 --- a/examples/osd/arduino-roller/flash.sh +++ b/examples/osd/arduino-roller/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -make TARGET=osd-merkur flash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/arduino-roller/run.sh b/examples/osd/arduino-roller/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/arduino-roller/run.sh +++ b/examples/osd/arduino-roller/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/arduino-roomalert/Makefile b/examples/osd/arduino-roomalert/Makefile index 650158d21..fad4a2b73 100644 --- a/examples/osd/arduino-roomalert/Makefile +++ b/examples/osd/arduino-roomalert/Makefile @@ -1,12 +1,8 @@ # Set this to the name of your sketch (without extension .pde) SKETCH=sketch +EXE=arduino-example -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size arduino-example.osd-merkur.hex \ - arduino-example.osd-merkur.eep -endif - -all: arduino-example $(PLATFORM_FILES) +all: $(EXE) CONTIKI=../../.. @@ -55,25 +51,6 @@ APPS += arduino include $(CONTIKI)/Makefile.include include $(CONTIKI)/apps/arduino/Makefile.include -avr-size: arduino-example.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 arduino-example.osd-merkur - -arduino-example.osd-merkur.hex: arduino-example.osd-merkur - avr-objcopy -j .text -j .data -O ihex arduino-example.osd-merkur \ - arduino-example.osd-merkur.hex - -arduino-example.osd-merkur.eep: arduino-example.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - arduino-example.osd-merkur arduino-example.osd-merkur.eep - -flash: arduino-example.osd-merkur.hex arduino-example.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:arduino-example.osd-merkur.hex:a -U \ - eeprom:w:arduino-example.osd-merkur.eep:a - -.PHONY: flash avr-size - $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -85,3 +62,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/arduino-roomalert/flash.sh b/examples/osd/arduino-roomalert/flash.sh index e9cb40bfc..e82962073 100755 --- a/examples/osd/arduino-roomalert/flash.sh +++ b/examples/osd/arduino-roomalert/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -make TARGET=osd-merkur flash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/arduino-roomalert/run.sh b/examples/osd/arduino-roomalert/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/arduino-roomalert/run.sh +++ b/examples/osd/arduino-roomalert/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/arduino-sketch/Makefile b/examples/osd/arduino-sketch/Makefile index 0f2c1dcc2..d54e087b2 100644 --- a/examples/osd/arduino-sketch/Makefile +++ b/examples/osd/arduino-sketch/Makefile @@ -1,12 +1,8 @@ # Set this to the name of your sketch (without extension .pde) SKETCH=sketch +EXE=arduino-example -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size arduino-example.osd-merkur.hex \ - arduino-example.osd-merkur.eep -endif - -all: arduino-example $(PLATFORM_FILES) +all: $(EXE) CONTIKI=../../.. @@ -42,25 +38,6 @@ APPS += time json arduino json-resource include $(CONTIKI)/Makefile.include include $(CONTIKI)/apps/arduino/Makefile.include -avr-size: arduino-example.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 arduino-example.osd-merkur - -arduino-example.osd-merkur.hex: arduino-example.osd-merkur - avr-objcopy -j .text -j .data -O ihex arduino-example.osd-merkur \ - arduino-example.osd-merkur.hex - -arduino-example.osd-merkur.eep: arduino-example.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - arduino-example.osd-merkur arduino-example.osd-merkur.eep - -flash: arduino-example.osd-merkur.hex arduino-example.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:arduino-example.osd-merkur.hex:a -U \ - eeprom:w:arduino-example.osd-merkur.eep:a - -.PHONY: flash avr-size - $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -72,3 +49,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/arduino-sketch/flash.sh b/examples/osd/arduino-sketch/flash.sh index e9cb40bfc..e82962073 100755 --- a/examples/osd/arduino-sketch/flash.sh +++ b/examples/osd/arduino-sketch/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -make TARGET=osd-merkur flash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/arduino-sketch/run.sh b/examples/osd/arduino-sketch/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/arduino-sketch/run.sh +++ b/examples/osd/arduino-sketch/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/arduino-wateralert/Makefile b/examples/osd/arduino-wateralert/Makefile index 7dc5c26a1..5a017eac0 100644 --- a/examples/osd/arduino-wateralert/Makefile +++ b/examples/osd/arduino-wateralert/Makefile @@ -1,12 +1,8 @@ # Set this to the name of your sketch (without extension .pde) SKETCH=sketch +EXE=arduino-example -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size arduino-example.osd-merkur.hex \ - arduino-example.osd-merkur.eep -endif - -all: arduino-example $(PLATFORM_FILES) +all: $(EXE) CONTIKI=../../.. @@ -54,25 +50,6 @@ APPS += arduino include $(CONTIKI)/Makefile.include include $(CONTIKI)/apps/arduino/Makefile.include -avr-size: arduino-example.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 arduino-example.osd-merkur - -arduino-example.osd-merkur.hex: arduino-example.osd-merkur - avr-objcopy -j .text -j .data -O ihex arduino-example.osd-merkur \ - arduino-example.osd-merkur.hex - -arduino-example.osd-merkur.eep: arduino-example.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - arduino-example.osd-merkur arduino-example.osd-merkur.eep - -flash: arduino-example.osd-merkur.hex arduino-example.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:arduino-example.osd-merkur.hex:a -U \ - eeprom:w:arduino-example.osd-merkur.eep:a - -.PHONY: flash avr-size - $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -84,3 +61,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/arduino-wateralert/flash.sh b/examples/osd/arduino-wateralert/flash.sh index e9cb40bfc..e82962073 100755 --- a/examples/osd/arduino-wateralert/flash.sh +++ b/examples/osd/arduino-wateralert/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -make TARGET=osd-merkur flash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/arduino-wateralert/run.sh b/examples/osd/arduino-wateralert/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/arduino-wateralert/run.sh +++ b/examples/osd/arduino-wateralert/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/arduino-wateralert/sketch.pde b/examples/osd/arduino-wateralert/sketch.pde index b8a6d559a..22aaa864f 100644 --- a/examples/osd/arduino-wateralert/sketch.pde +++ b/examples/osd/arduino-wateralert/sketch.pde @@ -11,6 +11,7 @@ */ extern "C" { +#include "arduino-process.h" #include "rest-engine.h" extern volatile uint8_t mcusleepcycle; // default 16 @@ -37,12 +38,12 @@ void setup (void) void loop (void) { - mcusleepcycle=0; // dont sleep + mcu_sleep_off(); moisture_voltage = analogRead(moisture_pin); if(moisture_voltage < 800){ digitalWrite(BUZZER_PIN, LOW); }else{ digitalWrite(BUZZER_PIN, HIGH); } - mcusleepcycle=32; // sleep, wakeup every 32 cycles + mcu_sleep_on(); } diff --git a/examples/osd/arduino-weather/Adafruit_HTU21DF.cpp b/examples/osd/arduino-weather/Adafruit_HTU21DF.cpp new file mode 100644 index 000000000..84bbeb066 --- /dev/null +++ b/examples/osd/arduino-weather/Adafruit_HTU21DF.cpp @@ -0,0 +1,100 @@ +/*************************************************** + This is a library for the HTU21DF Humidity & Temp Sensor + + Designed specifically to work with the HTU21DF sensor from Adafruit + ----> https://www.adafruit.com/products/1899 + + These displays use I2C to communicate, 2 pins are required to + interface + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + Written by Limor Fried/Ladyada for Adafruit Industries. + BSD license, all text above must be included in any redistribution + ****************************************************/ + +#include "Adafruit_HTU21DF.h" +#if defined(__AVR__) +#include +#endif + +Adafruit_HTU21DF::Adafruit_HTU21DF() { +} + + +boolean Adafruit_HTU21DF::begin(void) { + Wire.begin(); + + reset(); + + Wire.beginTransmission(HTU21DF_I2CADDR); + Wire.write(HTU21DF_READREG); + Wire.endTransmission(); + Wire.requestFrom(HTU21DF_I2CADDR, 1); + return (Wire.read() == 0x2); // after reset should be 0x2 +} + +void Adafruit_HTU21DF::reset(void) { + Wire.beginTransmission(HTU21DF_I2CADDR); + Wire.write(HTU21DF_RESET); + Wire.endTransmission(); + delay(15); +} + + +float Adafruit_HTU21DF::readTemperature(void) { + + // OK lets ready! + Wire.beginTransmission(HTU21DF_I2CADDR); + Wire.write(HTU21DF_READTEMP); + Wire.endTransmission(); + + delay(50); // add delay between request and actual read! + + Wire.requestFrom(HTU21DF_I2CADDR, 3); + while (!Wire.available()) {} + + uint16_t t = Wire.read(); + t <<= 8; + t |= Wire.read(); + + uint8_t crc = Wire.read(); + + float temp = t; + temp *= 175.72; + temp /= 65536; + temp -= 46.85; + + return temp; +} + + +float Adafruit_HTU21DF::readHumidity(void) { + // OK lets ready! + Wire.beginTransmission(HTU21DF_I2CADDR); + Wire.write(HTU21DF_READHUM); + Wire.endTransmission(); + + delay(50); // add delay between request and actual read! + + Wire.requestFrom(HTU21DF_I2CADDR, 3); + while (!Wire.available()) {} + + uint16_t h = Wire.read(); + h <<= 8; + h |= Wire.read(); + + uint8_t crc = Wire.read(); + + float hum = h; + hum *= 125; + hum /= 65536; + hum -= 6; + + return hum; +} + + + +/*********************************************************************/ diff --git a/examples/osd/arduino-weather/Adafruit_HTU21DF.h b/examples/osd/arduino-weather/Adafruit_HTU21DF.h new file mode 100644 index 000000000..fe8870e39 --- /dev/null +++ b/examples/osd/arduino-weather/Adafruit_HTU21DF.h @@ -0,0 +1,44 @@ +/*************************************************** + This is a library for the HTU21D-F Humidity & Temp Sensor + + Designed specifically to work with the HTU21D-F sensor from Adafruit + ----> https://www.adafruit.com/products/1899 + + These displays use I2C to communicate, 2 pins are required to + interface + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + Written by Limor Fried/Ladyada for Adafruit Industries. + BSD license, all text above must be included in any redistribution + ****************************************************/ + +//#if (ARDUINO >= 100) + #include "Arduino.h" +//#else +// #include "WProgram.h" +//#endif +#include "Wire.h" + +#define HTU21DF_I2CADDR 0x40 +#define HTU21DF_READTEMP 0xE3 +#define HTU21DF_READHUM 0xE5 +#define HTU21DF_WRITEREG 0xE6 +#define HTU21DF_READREG 0xE7 +#define HTU21DF_RESET 0xFE + + + +class Adafruit_HTU21DF { + public: + Adafruit_HTU21DF(); + boolean begin(void); + float readTemperature(void); + float readHumidity(void); + void reset(void); + private: + boolean readData(void); + float humidity, temp; +}; + diff --git a/examples/osd/arduino-weather/BH1750FVI.cpp b/examples/osd/arduino-weather/BH1750FVI.cpp new file mode 100644 index 000000000..fd871371a --- /dev/null +++ b/examples/osd/arduino-weather/BH1750FVI.cpp @@ -0,0 +1,209 @@ +#include "BH1750FVI.h" +//#if ARDUINO >= 100 + #include "Arduino.h" +//#else +// #include "WProgram.h" +//#endif + +#include + +void BH1750FVI::begin(byte mode, byte addr, double sens, int pin){ + if(pin>=0 && pin<55){ + pinMode(pin, OUTPUT); + if(addr==BH_AddrL) digitalWrite(pin, LOW); + if(addr==BH_AddrH) digitalWrite(pin, HIGH); + } + byte sensitivity; + if(sens> 5); + MTreg_loByte = BH_MTrLb | (sensitivity & 0b00011111); + switch(mode){ + case BH_ContL: + case BH_ContH: + case BH_Conth: + startOngoingSamples(mode); + break; + case BH_SingH: + case BH_Singh: + case BH_SingL: + startSingleSample(mode); + break; + default: + mode = BH_EasyH; + startOngoingSamples(mode); + break; + } + sampleUnseen = false; + lastSampleStart = 0; +} + +word BH1750FVI::startOngoingSamples(char mode){ + if(mode==BH_NoMod) mode=currentMode; + byte lowLevelMode = mode; + if(lowLevelMode==BH_EasyH) lowLevelMode=BH_ContH; + switch(mode){ + case BH_EasyH: + case BH_ContH: + case BH_Conth: + case BH_ContL: + i2cWrite(BH_PowOn); + i2cWrite(MTreg_hiByte); + i2cWrite(MTreg_loByte); + i2cWrite(lowLevelMode); + lastSampleStart = millis(); + currentMode = mode; + return setSensitivity(currentSensitivity); + break; + default: + return 0; + } +} + +word BH1750FVI::startSingleSample(char mode){ + if(mode==BH_NoMod){ + mode=currentMode; + } + switch(mode){ + case BH_SingH: + case BH_Singh: + case BH_SingL: + i2cWrite(BH_PowOn); + i2cWrite(MTreg_hiByte); + i2cWrite(MTreg_loByte); + i2cWrite(mode); + lastSampleStart = millis(); + currentMode = mode; + return setSensitivity(currentSensitivity); + break; + default: + return 0; + } +} + +bool BH1750FVI::sampleIsFresh(){ + if(sampleUnseen) return true; + else if((millis() > (lastSampleStart+currentSamplingTime))){ + sampleUnseen = true; + return true; + } + else return false; +} + +word BH1750FVI::getLightLevel(char mode){ + unsigned long int Intensity_value; + sampleUnseen = false; + Intensity_value = i2cRead(); + if(mode!='r'){ + Intensity_value = (Intensity_value*5)/6; + if(mode!='c'){ + Intensity_value = (Intensity_value*69)/currentSensitivity; + } + /*this next adjustment is not useful in practice. if you're using + a half-scale mode, you want the extra sensitivity. I'm leaving it + here for reference. + switch(currentMode){ + case BH_Singh: + case BH_Conth: + Intensity_value /= 2; + }*/ + Intensity_value = constrain(Intensity_value, 0, 65535); + } + switch(currentMode){ + case BH_ContH: + case BH_Conth: + case BH_ContL: + case BH_EasyH: + //this is a fake previous sample time that will keep pace with + //the actual BH1750FVI's sampling rate, but isn't necessarily + //synchronized to the earliest time each new sample is available. + //if you want true synchronized timing, use a single-sample mode. + lastSampleStart = millis(); + } + return (word)Intensity_value; +} + +word BH1750FVI::setSensitivity(double sens){ + if(sens<((double)(BH_MinSv/2))){ + sens = constrain(sens, + ((double)BH_MinSv/(double)BH_DefSv), + ((double)BH_MaxSv/(double)BH_DefSv) + ); + sens = sens*(double)BH_DefSv; + } + else{ + sens = constrain(sens, (double)BH_MinSv, (double)BH_MaxSv); + } + return setSensitivity((byte)round(sens)); +} + +word BH1750FVI::setSensitivity(float sens){ + return setSensitivity((double)sens); +} + +word BH1750FVI::setSensitivity(int sens){ + sens = constrain(sens, 1, BH_MaxSv); + return setSensitivity((byte)sens); +} + +word BH1750FVI::setSensitivity(byte sens){ + if(sens<(BH_MinSv/2)){ + sens = BH_DefSv*(constrain(sens, (byte)1, (byte)3)); + } + else{ + sens = constrain(sens, BH_MinSv, BH_MaxSv); + } + switch(currentMode){ + case BH_ContL: + case BH_SingL: + currentSamplingTime = (word)((BH_FastD*(unsigned long int)sens)/BH_DefSv); + break; + default: + currentSamplingTime = (word)((((unsigned long int)BH_SlowD)*((unsigned long int)sens))/BH_DefSv); + break; + } + MTreg_hiByte = BH_MTrHb | (sens >> 5); + MTreg_loByte = BH_MTrLb | (sens & 0b00011111); + currentSensitivity = sens; + sampleUnseen = false; + return currentSamplingTime; +} + +void BH1750FVI::powerDown(){ + i2cWrite(BH_PowOf); +} + +/*I2C INTERFACE + These two functions were originally based on code written by + https://github.com/claws/ and + https://github.com/Genotronex/ +*/ +void BH1750FVI::i2cWrite(byte dataToSend){ + Wire.beginTransmission(address); + Wire.write(dataToSend); + Wire.endTransmission(); +} + +word BH1750FVI::i2cRead(){ + word value; + Wire.beginTransmission(address); + Wire.requestFrom(address, (byte)2); + if(Wire.available()){ + value = Wire.read(); + if(Wire.available()){ + value <<= 8; + value |= Wire.read(); + } + else value=0; + } + else value=0; + Wire.endTransmission(); + return value; +} diff --git a/examples/osd/arduino-weather/BH1750FVI.h b/examples/osd/arduino-weather/BH1750FVI.h new file mode 100644 index 000000000..acdf62102 --- /dev/null +++ b/examples/osd/arduino-weather/BH1750FVI.h @@ -0,0 +1,115 @@ +#ifndef BH1750FVI_h +#define BH1750FVI_h + +//#if ARDUINO >= 100 + #include "Arduino.h" +//#else +// #include "WProgram.h" +//#endif + +#include + +//device address options +#define BH_AddrL 0x23 // Device address when addr pin is LOW +#define BH_AddrH 0x5C // Device address when addr pin is HIGH + +//power codes +#define BH_PowOf 0x00 // power-off code +#define BH_PowOn 0x01 // power-on code +#define BH_Reset 0x07 // code to reset the light reading register to zero + +//mode codes +#define BH_NoMod 0x02 // No mode specified. Keeps mode the same as before. +#define BH_EasyH 0x03 // 'easy' mode. basically the same as ContH +#define BH_ContH 0x10 // continuous full-scale, high-resolution sampling +#define BH_Conth 0x11 // continuous with twice the resolution but half the max value +#define BH_ContL 0x13 // continuous full-scale, low-resolution sampling. faster. +#define BH_SingH 0x20 // take one high-resolution, full-scale sample then turn off +#define BH_Singh 0x21 // take one high-resolution, half-scale sample then turn off +#define BH_SingL 0x23 // take one low-resolution, full-scale sample then turn off + // (happens to be the same as the low address value) + +//sensitivity codes +#define BH_MTrHb 0x40 // last 3 bits must be masked to 3 MSB of desired value +#define BH_MTrLb 0x60 // last 5 bits must be masked to 5 LSB of desired value +#define BH_MinSv 31 // minimum sensitivity register value, yields Lux * 0.45 +#define BH_MaxSv 254 // maximum sensitivity register value, yields Lux * 3.68 +#define BH_DefSv 69 // default sensitivity register value, yields Lux * 1.00 + +//timing delays. they're actually longer than the datasheet says. +#define BH_FastD 18 // basic delay in microseconds for a fast sample +#define BH_SlowD 125 // basic delay in microseconds for a slow sample + +class BH1750FVI { + public: + /*BEGIN + this is intended to be as error-tolerant as possible. if you don't supply + a mode, the default mode will be 'easy'. the sensitivity obviously defaults + to 1.0 (byte value of 69). Default address selection is LOW, which is how + the BH1750FVI should default if you don't connect anything to its ADDR pin. + */void begin(byte mode=BH_EasyH, byte addr=BH_AddrL, double sens=BH_DefSv, int addrPin=-1); + + /*FRESH SAMPLE POLLING + Check whether you have already looked at the current sample. + */bool sampleIsFresh(); + + /*ACTUALLY GET A READING FROM THE SENSOR + This is probably all you wanted from this library. Return value is an + unsigned 16 bit integer with units of Lux. There are three possible modes: + 'r' raw numerical reading, no units, you get what you get + 'c' convert units to Lux or half-Lux, depending on the mode, but don't + compensate for the sensitivity setting. This allows sensitivity to + be used as enclosure optics calibration/compensation. + 't' true Lux (or half-Lux) reading, regardless of sensitivity settings. + */word getLightLevel(char adjustments='c'); + + word retrieveSample(); + + /*CONTINUOUS SAMPLING + Return value of this start function is the delay time between refreshes of + the ambient light reading. After you call this function, you can use getLightLevel() + to read the most recent ambient light level. If you try to run this ongoing start + function with a one-time mode argument, it will do nothing and return 0. + */word startOngoingSamples(char mode=BH_NoMod); + + /*ONE-TIME SAMPLE START + Return value of this start function is the delay time before the new ambient + light reading will be available. You can check whether the new sample is ready + yet using sampleIsFresh(). Retrieve that single sample with getLightLevel(). + If you give this one-time start function a continuous mode argument, it will + do nothing and return 0. + */word startSingleSample(char mode=BH_NoMod); + + /*SENSITIVITY SETTINGS + This function lets you change the 'sensitivity' of the BH1750FVI by changing + its sampling time up or down. The sensitivity is stored as a number between + 31 and 254, with a default value of 69. This is intended to compensate for + having the chip installed in an enclosure that blocks some ambient light. + The floating point versions of the function allow the sensitivity to be + given as a ratio between ~0.45 and ~3.68. The return value is the number of + milliseconds that the chip will take to create a new light level reading. + */word setSensitivity(double sens); + word setSensitivity(float sens); + word setSensitivity(int sens); + word setSensitivity(byte sens=BH_DefSv); + + /*POWERDOWN FUNCTION + In case you want to turn off the BH1750FVI to save power. Other commands will wake + the chip back up. Single sample modes automatically turn off the chip after sampling, + but you can still read the value from it without waking it up. + */void powerDown(); + + private: + void init(byte mode, byte addr, byte sens); + void i2cWrite(byte dataToSend); + word i2cRead(); + byte address; + byte currentMode; + byte currentSensitivity; + bool sampleUnseen; + byte MTreg_hiByte; + byte MTreg_loByte; + unsigned long int lastSampleStart; + word currentSamplingTime; +}; +#endif diff --git a/examples/osd/arduino-weather/Barometer.cpp b/examples/osd/arduino-weather/Barometer.cpp new file mode 100644 index 000000000..ec8b294a8 --- /dev/null +++ b/examples/osd/arduino-weather/Barometer.cpp @@ -0,0 +1,175 @@ +/* + Barometer library V1.0 + 2010 Copyright (c) Seeed Technology Inc. All right reserved. + + Original Author: LG + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#include "Barometer.h" +#include +#include + +void Barometer::init(void) +{ + Wire.begin(); +// Serial.print("Temperaturet: "); + ac1 = bmp085ReadInt(0xAA); + ac2 = bmp085ReadInt(0xAC); + ac3 = bmp085ReadInt(0xAE); + ac4 = bmp085ReadInt(0xB0); + ac5 = bmp085ReadInt(0xB2); + ac6 = bmp085ReadInt(0xB4); + b1 = bmp085ReadInt(0xB6); + b2 = bmp085ReadInt(0xB8); + mb = bmp085ReadInt(0xBA); + mc = bmp085ReadInt(0xBC); + md = bmp085ReadInt(0xBE); +// Serial.print("Temperaturet2: "); +} +// Read 1 byte from the BMP085 at 'address' +// Return: the read byte; +char Barometer::bmp085Read(unsigned char address) +{ + //Wire.begin(); + //unsigned char data; + Wire.beginTransmission(BMP085_ADDRESS); + Wire.write(address); + Wire.endTransmission(); + + Wire.requestFrom(BMP085_ADDRESS, 1); + while(!Wire.available()); + return Wire.read(); +} +// Read 2 bytes from the BMP085 +// First byte will be from 'address' +// Second byte will be from 'address'+1 +int Barometer::bmp085ReadInt(unsigned char address) +{ + unsigned char msb, lsb; + Wire.beginTransmission(BMP085_ADDRESS); + Wire.write(address); + Wire.endTransmission(); + Wire.requestFrom(BMP085_ADDRESS, 2); + while(Wire.available()<2); + msb = Wire.read(); + lsb = Wire.read(); + return (int) msb<<8 | lsb; +} +// Read the uncompensated temperature value +unsigned int Barometer::bmp085ReadUT() +{ + unsigned int ut; + Wire.beginTransmission(BMP085_ADDRESS); + Wire.write(0xF4); + Wire.write(0x2E); + Wire.endTransmission(); + delay(5); + ut = bmp085ReadInt(0xF6); + return ut; +} +// Read the uncompensated pressure value +unsigned long Barometer::bmp085ReadUP() +{ + unsigned char msb, lsb, xlsb; + unsigned long up = 0; + Wire.beginTransmission(BMP085_ADDRESS); + Wire.write(0xF4); + Wire.write(0x34 + (OSS<<6)); + Wire.endTransmission(); + delay(2 + (3<> (8-OSS); + return up; +} +void Barometer::writeRegister(int deviceAddress, byte address, byte val) +{ + Wire.beginTransmission(deviceAddress); // start transmission to device + Wire.write(address); // send register address + Wire.write(val); // send value to write + Wire.endTransmission(); // end transmission +} +int Barometer::readRegister(int deviceAddress, byte address) +{ + int v; + Wire.beginTransmission(deviceAddress); + Wire.write(address); // register to read + Wire.endTransmission(); + + Wire.requestFrom(deviceAddress, 1); // read a byte + + while(!Wire.available()) { + // waiting + } + + v = Wire.read(); + return v; +} +float Barometer::calcAltitude(float pressure) +{ + float A = pressure/101325; + float B = 1/5.25588; + float C = pow(A,B); + C = 1 - C; + C = C /0.0000225577; + return C; +} +float Barometer::bmp085GetTemperature(unsigned int ut) +{ + long x1, x2; + + x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15; + x2 = ((long)mc << 11)/(x1 + md); + PressureCompensate = x1 + x2; + + float temp = ((PressureCompensate + 8)>>4); + temp = temp /10; + + return temp; +} +long Barometer::bmp085GetPressure(unsigned long up) +{ + long x1, x2, x3, b3, b6, p; + unsigned long b4, b7; + b6 = PressureCompensate - 4000; + x1 = (b2 * (b6 * b6)>>12)>>11; + x2 = (ac2 * b6)>>11; + x3 = x1 + x2; + b3 = (((((long)ac1)*4 + x3)<>2; + + // Calculate B4 + x1 = (ac3 * b6)>>13; + x2 = (b1 * ((b6 * b6)>>12))>>16; + x3 = ((x1 + x2) + 2)>>2; + b4 = (ac4 * (unsigned long)(x3 + 32768))>>15; + + b7 = ((unsigned long)(up - b3) * (50000>>OSS)); + if (b7 < 0x80000000) + p = (b7<<1)/b4; + else + p = (b7/b4)<<1; + + x1 = (p>>8) * (p>>8); + x1 = (x1 * 3038)>>16; + x2 = (-7357 * p)>>16; + p += (x1 + x2 + 3791)>>4; + + long temp = p; + return temp; +} diff --git a/examples/osd/arduino-weather/Barometer.h b/examples/osd/arduino-weather/Barometer.h new file mode 100644 index 000000000..161702718 --- /dev/null +++ b/examples/osd/arduino-weather/Barometer.h @@ -0,0 +1,58 @@ +/* + Barometer library V1.0 + 2010 Copyright (c) Seeed Technology Inc. All right reserved. + + Original Author: LG + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +#ifndef __BAROMETER_H__ +#define __BAROMETER_H__ + +#include +#include + +const unsigned char OSS = 0; +#define BMP085_ADDRESS 0x77 +class Barometer +{ +public: + void init(void); + long PressureCompensate; + float bmp085GetTemperature(unsigned int ut); + long bmp085GetPressure(unsigned long up); + float calcAltitude(float pressure); + unsigned int bmp085ReadUT(void); + unsigned long bmp085ReadUP(void); + +private: + int ac1; + int ac2; + int ac3; + unsigned int ac4; + unsigned int ac5; + unsigned int ac6; + int b1; + int b2; + int mb; + int mc; + int md; + char bmp085Read(unsigned char address); + int bmp085ReadInt(unsigned char address); + void writeRegister(int deviceAddress, byte address, byte val); + int readRegister(int deviceAddress, byte address); +}; + +#endif diff --git a/examples/osd/arduino-weather/Makefile b/examples/osd/arduino-weather/Makefile new file mode 100644 index 000000000..79a367a8c --- /dev/null +++ b/examples/osd/arduino-weather/Makefile @@ -0,0 +1,71 @@ +# Set this to the name of your sketch (without extension .pde) +SKETCH=sketch +EXE=arduino-example + +all: $(EXE) + +CONTIKI=../../.. + +# Contiki IPv6 configuration +CONTIKI_WITH_IPV6 = 1 + +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" +LFLAGS += -lm + +PROJECT_SOURCEFILES += ${SKETCH}.cpp Barometer.cpp BH1750FVI.cpp Adafruit_HTU21DF.cpp + +# automatically build RESTful resources +REST_RESOURCES_DIR = ./resources +REST_RESOURCES_DIR_COMMON = ../resources-common +REST_RESOURCES_FILES= $(notdir \ + $(shell find $(REST_RESOURCES_DIR) -name '*.c') \ + $(shell find $(REST_RESOURCES_DIR_COMMON) -name '*.c') \ + ) + +PROJECTDIRS += $(REST_RESOURCES_DIR) $(REST_RESOURCES_DIR_COMMON) +PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) + +# variable for Makefile.include +ifneq ($(TARGET), minimal-net) +CFLAGS += -DUIP_CONF_IPV6_RPL=1 +else +# minimal-net does not support RPL under Linux and is mostly used to test CoAP only +${info INFO: compiling without RPL} +CFLAGS += -DUIP_CONF_IPV6_RPL=0 +CFLAGS += -DHARD_CODED_ADDRESS=\"fdfd::10\" +${info INFO: compiling with large buffers} +CFLAGS += -DUIP_CONF_BUFFER_SIZE=2048 +CFLAGS += -DREST_MAX_CHUNK_SIZE=1024 +CFLAGS += -DCOAP_MAX_HEADER_SIZE=640 +endif + +# linker optimizations +SMALL=1 + + +# REST Engine shall use Erbium CoAP implementation +APPS += er-coap +APPS += rest-engine +APPS += arduino + +include $(CONTIKI)/Makefile.include +include $(CONTIKI)/apps/arduino/Makefile.include + +$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c + (cd $(CONTIKI)/tools && $(MAKE) tunslip6) + +connect-router: $(CONTIKI)/tools/tunslip6 + sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64 + +connect-router-cooja: $(CONTIKI)/tools/tunslip6 + sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 aaaa::1/64 + +connect-minimal: + sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/arduino-weather/README.md b/examples/osd/arduino-weather/README.md new file mode 100644 index 000000000..e1490ed05 --- /dev/null +++ b/examples/osd/arduino-weather/README.md @@ -0,0 +1,11 @@ +Arduino compatibility example +============================= + +This example shows that it is now possible to re-use arduino sketches in +Contiki. This example documents the necessary magic. Arduino specifies +two routines, `setup` and `loop`. Before `setup` is called, the +framework initializes hardware. In original Arduino, all this is done in +a `main` function (in C). For contiki we define a process that does the +same. + +See the documentation file in apps/contiki-compat/README.md diff --git a/examples/osd/arduino-weather/arduino-example.c b/examples/osd/arduino-weather/arduino-example.c new file mode 100644 index 000000000..ea74dd8b8 --- /dev/null +++ b/examples/osd/arduino-weather/arduino-example.c @@ -0,0 +1,2 @@ +#include +AUTOSTART_PROCESSES(&arduino_sketch); diff --git a/examples/osd/arduino-weather/flash.sh b/examples/osd/arduino-weather/flash.sh new file mode 100755 index 000000000..e82962073 --- /dev/null +++ b/examples/osd/arduino-weather/flash.sh @@ -0,0 +1,2 @@ +#!/bin/bash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/arduino-weather/project-conf.h b/examples/osd/arduino-weather/project-conf.h new file mode 100644 index 000000000..e25aed53c --- /dev/null +++ b/examples/osd/arduino-weather/project-conf.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + */ + +#ifndef PROJECT_RPL_WEB_CONF_H_ +#define PROJECT_RPL_WEB_CONF_H_ + +#define PLATFORM_HAS_LEDS 1 +//#define PLATFORM_HAS_BUTTON 1 +#define PLATFORM_HAS_BATTERY 1 + +#define SICSLOWPAN_CONF_FRAG 1 + +#define LOOP_INTERVAL (10 * CLOCK_SECOND) + +/* Save energy */ +//#define RDC_CONF_PT_YIELD_OFF + +/* For Debug: Dont allow MCU sleeping between channel checks */ +//#undef RDC_CONF_MCU_SLEEP +//#define RDC_CONF_MCU_SLEEP 0 + +/* Disabling RDC for demo purposes. Core updates often require more memory. */ +/* For projects, optimize memory and enable RDC again. */ +// #undef NETSTACK_CONF_RDC +//#define NETSTACK_CONF_RDC nullrdc_driver + +/* Increase rpl-border-router IP-buffer when using more than 64. */ +#undef REST_MAX_CHUNK_SIZE +#define REST_MAX_CHUNK_SIZE 64 + +/* Estimate your header size, especially when using Proxy-Uri. */ +/* +#undef COAP_MAX_HEADER_SIZE +#define COAP_MAX_HEADER_SIZE 70 +*/ + +/* The IP buffer size must fit all other hops, in particular the border router. */ + +#undef UIP_CONF_BUFFER_SIZE +#define UIP_CONF_BUFFER_SIZE 256 + + +/* Multiplies with chunk size, be aware of memory constraints. */ +#undef COAP_MAX_OPEN_TRANSACTIONS +#define COAP_MAX_OPEN_TRANSACTIONS 4 + +/* Must be <= open transaction number, default is COAP_MAX_OPEN_TRANSACTIONS-1. */ +/* +#undef COAP_MAX_OBSERVERS +#define COAP_MAX_OBSERVERS 2 +*/ + +/* Filtering .well-known/core per query can be disabled to save space. */ +/* +#undef COAP_LINK_FORMAT_FILTERING +#define COAP_LINK_FORMAT_FILTERING 0 +*/ + +/* Save some memory for the sky platform. */ +/* +#undef NBR_TABLE_CONF_MAX_NEIGHBORS +#define NBR_TABLE_CONF_MAX_NEIGHBORS 10 +#undef UIP_CONF_MAX_ROUTES +#define UIP_CONF_MAX_ROUTES 10 +*/ + +/* Reduce 802.15.4 frame queue to save RAM. */ +/* +#undef QUEUEBUF_CONF_NUM +#define QUEUEBUF_CONF_NUM 4 +*/ + +/* +#undef SICSLOWPAN_CONF_FRAG +#define SICSLOWPAN_CONF_FRAG 1 +*/ + +#endif /* PROJECT_RPL_WEB_CONF_H_ */ diff --git a/examples/osd/arduino-weather/resources/res-bh1750.c b/examples/osd/arduino-weather/resources/res-bh1750.c new file mode 100644 index 000000000..ae47f07a5 --- /dev/null +++ b/examples/osd/arduino-weather/resources/res-bh1750.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Moisture resource + * \author + * Harald Pichler + */ + +#include "contiki.h" + +#include +#include "rest-engine.h" +#include "Arduino.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +/* A simple getter example. Returns the reading from the sensor with a simple etag */ +RESOURCE(res_bh1750, + "title=\"Lux status\";rt=\"Lux\"", + res_get_handler, + NULL, + NULL, + NULL); + +extern uint16_t lux; + + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + + unsigned int accept = -1; + REST.get_header_accept(request, &accept); + + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", lux); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'lux':%d}", lux); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + const char *msg = "Supporting content-types text/plain and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); + } +} diff --git a/examples/osd/arduino-weather/resources/res-bmp085alt.c b/examples/osd/arduino-weather/resources/res-bmp085alt.c new file mode 100644 index 000000000..de90eae4f --- /dev/null +++ b/examples/osd/arduino-weather/resources/res-bmp085alt.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Barometer resource + * \author + * Harald Pichler + */ + +#include "contiki.h" + +#include +#include "rest-engine.h" +#include "Arduino.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +/* A simple getter example. Returns the reading from the sensor with a simple etag */ +RESOURCE(res_bmp085alt, + "title=\"alt status\";rt=\"alt\"", + res_get_handler, + NULL, + NULL, + NULL); + +extern char bmp085alt_s[8]; + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + + unsigned int accept = -1; + REST.get_header_accept(request, &accept); + + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", bmp085alt_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'temperature':%s}", bmp085alt_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + const char *msg = "Supporting content-types text/plain and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); + } +} diff --git a/examples/osd/arduino-weather/resources/res-bmp085atm.c b/examples/osd/arduino-weather/resources/res-bmp085atm.c new file mode 100644 index 000000000..b97cffe6e --- /dev/null +++ b/examples/osd/arduino-weather/resources/res-bmp085atm.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Barometer resource + * \author + * Harald Pichler + */ + +#include "contiki.h" + +#include +#include "rest-engine.h" +#include "Arduino.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +/* A simple getter example. Returns the reading from the sensor with a simple etag */ +RESOURCE(res_bmp085atm, + "title=\"atm status\";rt=\"atm\"", + res_get_handler, + NULL, + NULL, + NULL); + +extern char bmp085atm_s[8]; + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + + unsigned int accept = -1; + REST.get_header_accept(request, &accept); + + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", bmp085atm_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'temperature':%s}", bmp085atm_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + const char *msg = "Supporting content-types text/plain and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); + } +} diff --git a/examples/osd/arduino-weather/resources/res-bmp085press.c b/examples/osd/arduino-weather/resources/res-bmp085press.c new file mode 100644 index 000000000..6a02f4bf0 --- /dev/null +++ b/examples/osd/arduino-weather/resources/res-bmp085press.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Barometer resource + * \author + * Harald Pichler + */ + +#include "contiki.h" + +#include +#include "rest-engine.h" +#include "Arduino.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +/* A simple getter example. Returns the reading from the sensor with a simple etag */ +RESOURCE(res_bmp085press, + "title=\"pressure status\";rt=\"pressure\"", + res_get_handler, + NULL, + NULL, + NULL); + +extern char bmp085press_s[8]; + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + + unsigned int accept = -1; + REST.get_header_accept(request, &accept); + + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", bmp085press_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'pressure':%s}", bmp085press_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + const char *msg = "Supporting content-types text/plain and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); + } +} diff --git a/examples/osd/arduino-merkurboard/resources/res-door.c b/examples/osd/arduino-weather/resources/res-htu21dhum.c similarity index 91% rename from examples/osd/arduino-merkurboard/resources/res-door.c rename to examples/osd/arduino-weather/resources/res-htu21dhum.c index 97a5e9b72..f66c71c74 100644 --- a/examples/osd/arduino-merkurboard/resources/res-door.c +++ b/examples/osd/arduino-weather/resources/res-htu21dhum.c @@ -31,7 +31,7 @@ /** * \file - * Door resource + * Moisture resource * \author * Harald Pichler */ @@ -45,33 +45,31 @@ static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); /* A simple getter example. Returns the reading from the sensor with a simple etag */ -RESOURCE(res_door, +RESOURCE(res_htu21dhum, "title=\"Moisture status\";rt=\"Moisture\"", res_get_handler, NULL, NULL, NULL); -extern uint8_t door_pin; -extern uint8_t door_status; +extern char htu21d_hum_s[8]; + static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - door_status = digitalRead(door_pin); - unsigned int accept = -1; REST.get_header_accept(request, &accept); if(accept == -1 || accept == REST.type.TEXT_PLAIN) { REST.set_header_content_type(response, REST.type.TEXT_PLAIN); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%d", door_status); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", htu21d_hum_s); REST.set_response_payload(response, buffer, strlen((char *)buffer)); } else if(accept == REST.type.APPLICATION_JSON) { REST.set_header_content_type(response, REST.type.APPLICATION_JSON); - snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'door':%d}", door_status); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'moisture':%s}", htu21d_hum_s); REST.set_response_payload(response, buffer, strlen((char *)buffer)); } else { diff --git a/examples/osd/arduino-weather/resources/res-htu21dtemp.c b/examples/osd/arduino-weather/resources/res-htu21dtemp.c new file mode 100644 index 000000000..cdc9a9a7d --- /dev/null +++ b/examples/osd/arduino-weather/resources/res-htu21dtemp.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013, Institute for Pervasive Computing, ETH Zurich + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + */ + +/** + * \file + * Moisture resource + * \author + * Harald Pichler + */ + +#include "contiki.h" + +#include +#include "rest-engine.h" +#include "Arduino.h" + +static void res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset); + +/* A simple getter example. Returns the reading from the sensor with a simple etag */ +RESOURCE(res_htu21dtemp, + "title=\"Temperature status\";rt=\"Temperatur\"", + res_get_handler, + NULL, + NULL, + NULL); + +extern char htu21d_temp_s[8]; + +static void +res_get_handler(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) +{ + + unsigned int accept = -1; + REST.get_header_accept(request, &accept); + + if(accept == -1 || accept == REST.type.TEXT_PLAIN) { + REST.set_header_content_type(response, REST.type.TEXT_PLAIN); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "%s", htu21d_temp_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else if(accept == REST.type.APPLICATION_JSON) { + REST.set_header_content_type(response, REST.type.APPLICATION_JSON); + snprintf((char *)buffer, REST_MAX_CHUNK_SIZE, "{'temperature':%s}", htu21d_temp_s); + + REST.set_response_payload(response, buffer, strlen((char *)buffer)); + } else { + REST.set_response_status(response, REST.status.NOT_ACCEPTABLE); + const char *msg = "Supporting content-types text/plain and application/json"; + REST.set_response_payload(response, msg, strlen(msg)); + } +} diff --git a/examples/osd/arduino-weather/run.sh b/examples/osd/arduino-weather/run.sh new file mode 100755 index 000000000..5d5cbbbb4 --- /dev/null +++ b/examples/osd/arduino-weather/run.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# For the ages-old bootloader (before 2014) you want to use +# BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/arduino-weather/sketch.pde b/examples/osd/arduino-weather/sketch.pde new file mode 100644 index 000000000..e83fd2b8c --- /dev/null +++ b/examples/osd/arduino-weather/sketch.pde @@ -0,0 +1,128 @@ +/* + * Sample arduino sketch using contiki features. + * We turn the LED off + * We allow read the moisture sensor + * Unfortunately sleeping for long times in loop() isn't currently + * possible, something turns off the CPU (including PWM outputs) if a + * Proto-Thread is taking too long. We need to find out how to sleep in + * a Contiki-compatible way. + * Note that for a normal arduino sketch you won't have to include any + * of the contiki-specific files here, the sketch should just work. + */ + +#include +#include "Barometer.h" +#include "Adafruit_HTU21DF.h" +#include "BH1750FVI.h" + +extern "C" { +#include "arduino-process.h" +#include "rest-engine.h" + +extern resource_t res_bh1750, res_htu21dtemp, res_htu21dhum, res_bmp085press,res_bmp085atm,res_bmp085alt, res_battery; + +float bmp085temp; +float bmp085press; +float bmp085atm; +float bmp085alt; +char bmp085temp_s[8]; +char bmp085press_s[8]; +char bmp085atm_s[8]; +char bmp085alt_s[8]; + +Barometer myBarometer; + +float htu21d_hum; +float htu21d_temp; +char htu21d_hum_s[8]; +char htu21d_temp_s[8]; + +Adafruit_HTU21DF htu = Adafruit_HTU21DF(); + +uint16_t lux; + +BH1750FVI lightMeter; + +#define LED_PIN 4 +} + +void setup (void) +{ + // switch off the led + pinMode(LED_PIN, OUTPUT); + digitalWrite(LED_PIN, HIGH); + // BH1750 sensor + Wire.begin(); + lightMeter.begin(); + // BMP085 sensor + myBarometer.init(); + // htu21d sensor + if (!htu.begin()) { + printf("Couldn't find sensor htu21d !"); + } + // init coap resourcen + rest_init_engine (); + rest_activate_resource (&res_bmp085press, "s/press"); + rest_activate_resource (&res_bmp085atm, "s/atm"); + rest_activate_resource (&res_bmp085alt, "s/alt"); + rest_activate_resource (&res_htu21dtemp, "s/temp"); + rest_activate_resource (&res_htu21dhum, "s/hum"); + rest_activate_resource (&res_bh1750, "s/lux"); + rest_activate_resource (&res_battery, "s/battery"); +} + +// at project-conf.h +// LOOP_INTERVAL (10 * CLOCK_SECOND) +void loop (void) +{ + mcu_sleep_off(); + // BMP085 Sensor + bmp085temp = myBarometer.bmp085GetTemperature(myBarometer.bmp085ReadUT()); //Get the temperature, bmp085ReadUT MUST be called first + bmp085press = myBarometer.bmp085GetPressure(myBarometer.bmp085ReadUP());//Get the temperature + bmp085alt = myBarometer.calcAltitude(bmp085press); //Uncompensated caculation - in Meters + bmp085atm = bmp085press / 101325; + + dtostrf(bmp085temp , 6, 2, bmp085temp_s ); + dtostrf(bmp085press , 6, 2, bmp085press_s ); + dtostrf(bmp085alt , 6, 2, bmp085alt_s ); + dtostrf(bmp085atm , 6, 2, bmp085atm_s ); + // remove space + if(bmp085temp_s[0]==' '){ + memcpy (bmp085temp_s,bmp085temp_s+1,strlen(bmp085temp_s)+1); + } + if(bmp085press_s[0]==' '){ + memcpy (bmp085press_s,bmp085press_s+1,strlen(bmp085press_s)+1); + } + if(bmp085alt_s[0]==' '){ + memcpy (bmp085alt_s,bmp085alt_s+1,strlen(bmp085alt_s)+1); + } + if(bmp085atm_s[0]==' '){ + memcpy (bmp085atm_s,bmp085atm_s+1,strlen(bmp085atm_s)+1); + } + // HTU21d Sensor + htu21d_temp = htu.readTemperature(); + htu21d_hum = htu.readHumidity(); + dtostrf(htu21d_temp , 6, 2, htu21d_temp_s ); + dtostrf(htu21d_hum , 6, 2, htu21d_hum_s ); + // remove space + if(htu21d_temp_s[0]==' '){ + memcpy (htu21d_temp_s,htu21d_temp_s+1,strlen(htu21d_temp_s)+1); + } + if(htu21d_hum_s[0]==' '){ + memcpy (htu21d_hum_s,htu21d_hum_s+1,strlen(htu21d_hum_s)+1); + } + // BH1750 + lux = lightMeter.getLightLevel(); + +// Debug Print + printf("BMP085\n"); + printf("Press: %s\n",bmp085press_s); + printf("Altitude: %s\n",bmp085alt_s); + printf("atm: %s\n",bmp085atm_s); + printf("HTU21d\n"); + printf("Temp: %s\n",htu21d_temp_s); + printf("Hum: %s\n",htu21d_hum_s); + printf("BH1750\n"); + printf("Lux: %d\n",lux); + mcu_sleep_on(); +} diff --git a/examples/osd/climate/Makefile b/examples/osd/climate/Makefile index 7bde50858..211ea0c1c 100644 --- a/examples/osd/climate/Makefile +++ b/examples/osd/climate/Makefile @@ -1,10 +1,5 @@ -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size er-example-server.osd-merkur.hex \ - er-example-server.osd-merkur.eep -endif - -all: er-example-server $(PLATFORM_FILES) -# use target "er-plugtest-server" explicitly when requried +EXE=er-example-server +all: $(EXE) CONTIKI=../../.. @@ -74,21 +69,9 @@ connect-router-native: $(CONTIKI)/examples/ipv6/native-border-router/border-rout connect-minimal: sudo ip address add fdfd::1/64 dev tap0 -avr-size: er-example-server.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur +avr-size: $(EXE).$(TARGET).sz -er-example-server.osd-merkur.hex: er-example-server.osd-merkur - avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur \ - er-example-server.osd-merkur.hex - -er-example-server.osd-merkur.eep: er-example-server.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - er-example-server.osd-merkur er-example-server.osd-merkur.eep - -flash: er-example-server.osd-merkur.hex er-example-server.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:er-example-server.osd-merkur.hex:a -U \ - eeprom:w:er-example-server.osd-merkur.eep:a +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu .PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/climate/flash.sh b/examples/osd/climate/flash.sh index e92d472f6..e82962073 100755 --- a/examples/osd/climate/flash.sh +++ b/examples/osd/climate/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -sudo avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U flash:w:er-example-server.osd-merkur.hex:a -U eeprom:w:er-example-server.osd-merkur.eep:a +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/climate/run.sh b/examples/osd/climate/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/climate/run.sh +++ b/examples/osd/climate/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/climate2/Makefile b/examples/osd/climate2/Makefile index 7bde50858..ee3981b6a 100644 --- a/examples/osd/climate2/Makefile +++ b/examples/osd/climate2/Makefile @@ -1,9 +1,6 @@ -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size er-example-server.osd-merkur.hex \ - er-example-server.osd-merkur.eep -endif +EXE=er-example-server -all: er-example-server $(PLATFORM_FILES) +all: $(EXE) # use target "er-plugtest-server" explicitly when requried CONTIKI=../../.. @@ -74,21 +71,9 @@ connect-router-native: $(CONTIKI)/examples/ipv6/native-border-router/border-rout connect-minimal: sudo ip address add fdfd::1/64 dev tap0 -avr-size: er-example-server.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur +avr-size: $(EXE).$(TARGET).sz -er-example-server.osd-merkur.hex: er-example-server.osd-merkur - avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur \ - er-example-server.osd-merkur.hex - -er-example-server.osd-merkur.eep: er-example-server.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - er-example-server.osd-merkur er-example-server.osd-merkur.eep - -flash: er-example-server.osd-merkur.hex er-example-server.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:er-example-server.osd-merkur.hex:a -U \ - eeprom:w:er-example-server.osd-merkur.eep:a +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu .PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/climate2/flash.sh b/examples/osd/climate2/flash.sh index e92d472f6..e82962073 100755 --- a/examples/osd/climate2/flash.sh +++ b/examples/osd/climate2/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -sudo avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U flash:w:er-example-server.osd-merkur.hex:a -U eeprom:w:er-example-server.osd-merkur.eep:a +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/climate2/run.sh b/examples/osd/climate2/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/climate2/run.sh +++ b/examples/osd/climate2/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/dual-rgbw-actor/Makefile b/examples/osd/dual-rgbw-actor/Makefile index 1305e71b9..d0e207dcf 100644 --- a/examples/osd/dual-rgbw-actor/Makefile +++ b/examples/osd/dual-rgbw-actor/Makefile @@ -1,5 +1,6 @@ -all: er-example-server -# use this target explicitly if requried: er-plugtest-server +EXE=er-example-server + +all: $(EXE) # variable for this Makefile # configure CoAP implementation (3|7|12|13) (er-coap-07 also supports CoAP draft 08) @@ -91,3 +92,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/dual-rgbw-actor/flash.sh b/examples/osd/dual-rgbw-actor/flash.sh index b91668634..e82962073 100755 --- a/examples/osd/dual-rgbw-actor/flash.sh +++ b/examples/osd/dual-rgbw-actor/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U flash:w:er-example-server.osd-merkur.hex:a -U eeprom:w:er-example-server.osd-merkur.eep:a +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/dual-rgbw-actor/run.sh b/examples/osd/dual-rgbw-actor/run.sh index 19451da3a..7b3a1dc9f 100755 --- a/examples/osd/dual-rgbw-actor/run.sh +++ b/examples/osd/dual-rgbw-actor/run.sh @@ -1,8 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -#make clean TARGET=osd-merkur -make -j TARGET=osd-merkur -#avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur -avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.hex -avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.eep +make clean TARGET=osd-merkur-128 +make -j TARGET=osd-merkur-128 diff --git a/examples/osd/embedd-vm-merkurboard/Makefile b/examples/osd/embedd-vm-merkurboard/Makefile index ee049c6f2..6e69fd76f 100644 --- a/examples/osd/embedd-vm-merkurboard/Makefile +++ b/examples/osd/embedd-vm-merkurboard/Makefile @@ -1,4 +1,6 @@ -all: embedd-vm-server +EXE=embedd-vm-server + +all: $(EXE) # use this target explicitly if requried: er-plugtest-server # variable for this Makefile @@ -60,3 +62,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/embedd-vm-merkurboard/flash.sh b/examples/osd/embedd-vm-merkurboard/flash.sh index fe0d83f0d..e82962073 100755 --- a/examples/osd/embedd-vm-merkurboard/flash.sh +++ b/examples/osd/embedd-vm-merkurboard/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -sudo avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U flash:w:embedd-vm-server.osd-merkur.hex:a -U eeprom:w:embedd-vm-server.osd-merkur.eep:a +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/embedd-vm-merkurboard/run.sh b/examples/osd/embedd-vm-merkurboard/run.sh index cd9abaee7..5d5cbbbb4 100755 --- a/examples/osd/embedd-vm-merkurboard/run.sh +++ b/examples/osd/embedd-vm-merkurboard/run.sh @@ -1,8 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur -avr-size -C --mcu=MCU=atmega128rfa1 embedd-vm-server.osd-merkur -avr-objcopy -j .text -j .data -O ihex embedd-vm-server.osd-merkur embedd-vm-server.osd-merkur.hex -avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex embedd-vm-server.osd-merkur embedd-vm-server.osd-merkur.eep +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/er-rest-example-merkurboard/Makefile b/examples/osd/er-rest-example-merkurboard/Makefile index b9ce03b4d..21cc867a2 100644 --- a/examples/osd/er-rest-example-merkurboard/Makefile +++ b/examples/osd/er-rest-example-merkurboard/Makefile @@ -1,11 +1,6 @@ -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size-server er-example-server.osd-merkur.hex \ - er-example-server.osd-merkur.eep \ - avr-size-client er-example-client.osd-merkur.hex \ - er-example-client.osd-merkur.eep -endif +EXE=er-example-client er-example-server -all: er-example-server er-example-client $(PLATFORM_FILES) +all: $(EXE) # use target "er-plugtest-server" explicitly when requried @@ -81,38 +76,15 @@ connect-router-native: $(CONTIKI)/examples/ipv6/native-border-router/border-rout connect-minimal: sudo ip address add fdfd::1/64 dev tap0 -avr-size-server: er-example-server.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur +avr-size-server: er-example-server.$(TARGET).sz -er-example-server.osd-merkur.hex: er-example-server.osd-merkur - avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur \ - er-example-server.osd-merkur.hex +avr-size-client: er-example-server.$(TARGET).sz -er-example-server.osd-merkur.eep: er-example-server.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - er-example-server.osd-merkur er-example-server.osd-merkur.eep +flash-server: er-example-server.$(TARGET).u er-example-server.$(TARGET).eu -flash-server: er-example-server.osd-merkur.hex er-example-server.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:er-example-server.osd-merkur.hex:a -U \ - eeprom:w:er-example-server.osd-merkur.eep:a - -avr-size-client: er-example-client.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 er-example-client.osd-merkur - -er-example-client.osd-merkur.hex: er-example-client.osd-merkur - avr-objcopy -j .text -j .data -O ihex er-example-client.osd-merkur \ - er-example-client.osd-merkur.hex - -er-example-client.osd-merkur.eep: er-example-client.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - er-example-client.osd-merkur er-example-client.osd-merkur.eep - -flash-client: er-example-client.osd-merkur.hex er-example-client.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:er-example-client.osd-merkur.hex:a -U \ - eeprom:w:er-example-client.osd-merkur.eep:a +flash-client: er-example-client.$(TARGET).u er-example-client.$(TARGET).eu .PHONY: flash-client avr-size-client flash-server avr-size-server +.PRECIOUS: er-example-server.$(TARGET).hex er-example-server.$(TARGET).eep \ + er-example-client.$(TARGET).hex er-example-client.$(TARGET).eep + diff --git a/examples/osd/er-rest-example-merkurboard/flash.sh b/examples/osd/er-rest-example-merkurboard/flash.sh index c75149555..e82962073 100755 --- a/examples/osd/er-rest-example-merkurboard/flash.sh +++ b/examples/osd/er-rest-example-merkurboard/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -sudo make flash-server +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/er-rest-example-merkurboard/run.sh b/examples/osd/er-rest-example-merkurboard/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/er-rest-example-merkurboard/run.sh +++ b/examples/osd/er-rest-example-merkurboard/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/led-strip/Makefile b/examples/osd/led-strip/Makefile deleted file mode 100644 index cced7c282..000000000 --- a/examples/osd/led-strip/Makefile +++ /dev/null @@ -1,94 +0,0 @@ -SERIAL=/dev/ttyUSB0 -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size led-strip.osd-merkur.hex \ - led-strip.osd-merkur.eep -endif - -all: led-strip $(PLATFORM_FILES) - -CONTIKI=../../.. - -# Contiki IPv6 configuration -WITH_UIP6=1 -UIP_CONF_IPV6=1 -CFLAGS += -DUIP_CONF_IPV6=1 -CFLAGS += -DUIP_CONF_IPV6_RPL=1 - -CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" - -# automatically build RESTful resources -REST_RESOURCES_DIR = ./resources -REST_RESOURCES_DIR_COMMON = ../resources-common -REST_RESOURCES_FILES= $(notdir \ - $(shell find $(REST_RESOURCES_DIR_COMMON) -name '*.c') \ - ) - -PROJECTDIRS += $(REST_RESOURCES_DIR_COMMON) -PROJECT_SOURCEFILES += $(REST_RESOURCES_FILES) - -# linker optimizations -SMALL=1 - -# REST Engine shall use Erbium CoAP implementation -APPS += er-coap -APPS += rest-engine -APPS += json json-resource - -# optional rules to get assembly -#CUSTOM_RULE_C_TO_OBJECTDIR_O = 1 -#CUSTOM_RULE_S_TO_OBJECTDIR_O = 1 - -include $(CONTIKI)/Makefile.include - -# minimal-net target is currently broken in Contiki -ifeq ($(TARGET), minimal-net) -CFLAGS += -DHARD_CODED_ADDRESS=\"fdfd::10\" -${info INFO: compiling with large buffers} -CFLAGS += -DUIP_CONF_BUFFER_SIZE=1300 -CFLAGS += -DREST_MAX_CHUNK_SIZE=1024 -CFLAGS += -DCOAP_MAX_HEADER_SIZE=176 -CFLAGS += -DUIP_CONF_IPV6_RPL=0 -endif - -# optional rules to get assembly -#$(OBJECTDIR)/%.o: asmdir/%.S -# $(CC) $(CFLAGS) -MMD -c $< -o $@ -# @$(FINALIZE_DEPENDENCY) -# -#asmdir/%.S: %.c -# $(CC) $(CFLAGS) -MMD -S $< -o $@ - -# border router rules -$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c - (cd $(CONTIKI)/tools && $(MAKE) tunslip6) - -connect-router: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64 - -connect-router-cooja: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 -p 60001 aaaa::1/64 - -connect-router-native: $(CONTIKI)/examples/ipv6/native-border-router/border-router.native - sudo $(CONTIKI)/exmples/ipv6/native-border-router/border-router.native -a 127.0.0.1 -p 60001 aaaa::1/64 - -connect-minimal: - sudo ip address add fdfd::1/64 dev tap0 - -avr-size: led-strip.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 led-strip.osd-merkur - -led-strip.osd-merkur.hex: led-strip.osd-merkur - avr-objcopy -j .text -j .data -O ihex led-strip.osd-merkur \ - led-strip.osd-merkur.hex - -led-strip.osd-merkur.eep: led-strip.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - led-strip.osd-merkur led-strip.osd-merkur.eep - -flash: led-strip.osd-merkur.hex led-strip.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P$(SERIAL) -b57600 -e -U \ - flash:w:led-strip.osd-merkur.hex:a -U \ - eeprom:w:led-strip.osd-merkur.eep:a - -.PHONY: flash avr-size diff --git a/examples/osd/led-strip/flash.sh b/examples/osd/led-strip/flash.sh deleted file mode 100755 index 2b14c43f4..000000000 --- a/examples/osd/led-strip/flash.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -make flash TARGET=osd-merkur diff --git a/examples/osd/led-strip/led-strip.c b/examples/osd/led-strip/led-strip.c deleted file mode 100644 index d691a91a5..000000000 --- a/examples/osd/led-strip/led-strip.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2015, Ralf Schlatterbeck Open Source Consulting - * 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 - * LED-strip driver for Seeed Studio LED-Strip - * \author - * Ralf Schlatterbeck - */ - -#include -#include -#include -#include -#include "contiki.h" -#include "contiki-net.h" -#include "rest-engine.h" -#include "generic_resource.h" - -/* - * Resources to be activated need to be imported through the extern keyword. - * The build system automatically compiles the resources in the - * corresponding sub-directory. - */ - -#if PLATFORM_HAS_BATTERY -#include "dev/battery-sensor.h" -extern resource_t res_battery; -#endif - -#if PLATFORM_HAS_RADIO -#include "dev/radio-sensor.h" -extern resource_t res_radio; -#endif - -#include "LED_Strip_Suli.h" - -uint8_t color_rgb [3] = {0, 255, 0}; - -static uint8_t name_to_offset (const char * name) -{ - uint8_t offset = 0; - if (0 == strcmp (name, "green")) { - offset = 1; - } else if (0 == strcmp (name, "blue")) { - offset = 2; - } - return offset; -} - -static size_t -color_to_string (const char *name, const char *uri, char *buf, size_t bsize) -{ - return snprintf (buf, bsize, "%d", color_rgb [name_to_offset (name)]); -} - -int color_from_string (const char *name, const char *uri, const char *s) -{ - color_rgb [name_to_offset (name)] = atoi (s); - led_strip_begin (); - led_strip_set_color (color_rgb [0], color_rgb [1], color_rgb [2]); - led_strip_end (); - printf ("Set to R:%d G:%d B:%d\n" - , color_rgb [0], color_rgb [1], color_rgb [2]) - ; - return 0; -} - -GENERIC_RESOURCE - ( red - , RED_LED - , s - , 1 - , color_from_string - , color_to_string - ); - -GENERIC_RESOURCE - ( green - , GREEN_LED - , s - , 1 - , color_from_string - , color_to_string - ); - -GENERIC_RESOURCE - ( blue - , BLUE_LED - , s - , 1 - , color_from_string - , color_to_string - ); - - -PROCESS(led_strip, "LED Strip Example"); -AUTOSTART_PROCESSES(&led_strip); - -PROCESS_THREAD(led_strip, ev, data) -{ - - PROCESS_BEGIN(); - - /* Initialize the REST engine. */ - rest_init_engine (); - printf ("Initialized\n"); - led_strip_init (3, 14); - led_strip_begin (); - led_strip_set_color (color_rgb [0], color_rgb [1], color_rgb [2]); - led_strip_end (); - printf ("Set to R:%d G:%d B:%d\n" - , color_rgb [0], color_rgb [1], color_rgb [2]) - ; - - /* Activate the application-specific resources. */ -#if PLATFORM_HAS_BATTERY - SENSORS_ACTIVATE(battery_sensor); - rest_activate_resource (&res_battery,"s/battery"); -#endif - rest_activate_resource (&res_red, "led/R"); - rest_activate_resource (&res_green, "led/G"); - rest_activate_resource (&res_blue, "led/B"); - - /* Define application-specific events here. */ - /* Don't do anything for now, everything done in resources */ - while(1) { - PROCESS_WAIT_EVENT(); - } /* while (1) */ - - PROCESS_END(); -} diff --git a/examples/osd/light-actor/Makefile b/examples/osd/light-actor/Makefile index 02b345590..881d7002c 100644 --- a/examples/osd/light-actor/Makefile +++ b/examples/osd/light-actor/Makefile @@ -1,10 +1,6 @@ -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size er-example-server.osd-merkur.hex \ - er-example-server.osd-merkur.eep -endif +EXE=er-example-server -all: er-example-server $(PLATFORM_FILES) -# use this target explicitly if requried: er-plugtest-server +all: $(EXE) CONTIKI=../../.. @@ -41,25 +37,6 @@ APPS += json json-resource include $(CONTIKI)/Makefile.include -avr-size: er-example-server.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur - -er-example-server.osd-merkur.hex: er-example-server.osd-merkur - avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur \ - er-example-server.osd-merkur.hex - -er-example-server.osd-merkur.eep: er-example-server.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - er-example-server.osd-merkur er-example-server.osd-merkur.eep - -flash: er-example-server.osd-merkur.hex er-example-server.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:er-example-server.osd-merkur.hex:a -U \ - eeprom:w:er-example-server.osd-merkur.eep:a - -.PHONY: flash avr-size - $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -71,3 +48,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/light-actor/flash.sh b/examples/osd/light-actor/flash.sh index e92d472f6..e82962073 100755 --- a/examples/osd/light-actor/flash.sh +++ b/examples/osd/light-actor/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -sudo avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U flash:w:er-example-server.osd-merkur.hex:a -U eeprom:w:er-example-server.osd-merkur.eep:a +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/light-actor/pcintkey.c b/examples/osd/light-actor/pcintkey.c index 5fc065e24..f9553efd4 100644 --- a/examples/osd/light-actor/pcintkey.c +++ b/examples/osd/light-actor/pcintkey.c @@ -55,9 +55,32 @@ ISR(PCINT0_vect) // } // } } + +/* Compatibility of old vs new definitions in io.h */ +#ifndef DDE0 +#define DDE0 DDRE0 +#define DDE1 DDRE1 +#define DDE2 DDRE2 +#define DDE3 DDRE3 +#define DDE4 DDRE4 +#define DDE5 DDRE5 +#define DDE6 DDRE6 +#define DDE7 DDRE7 +#endif +#ifndef DDF0 +#define DDF0 DDRF0 +#define DDF1 DDRF1 +#define DDF2 DDRF2 +#define DDF3 DDRF3 +#define DDF4 DDRF4 +#define DDF5 DDRF5 +#define DDF6 DDRF6 +#define DDF7 DDRF7 +#endif + /** * \brief This will intialize the KEY for button readings. -*/ + */ void key_init(void) { diff --git a/examples/osd/light-actor/run.sh b/examples/osd/light-actor/run.sh index 4b11e9d2a..5d5cbbbb4 100755 --- a/examples/osd/light-actor/run.sh +++ b/examples/osd/light-actor/run.sh @@ -1,8 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur -avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur -avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.hex -avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.eep +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/light-shutter-control/Makefile b/examples/osd/light-shutter-control/Makefile index 7a3466655..340032d58 100644 --- a/examples/osd/light-shutter-control/Makefile +++ b/examples/osd/light-shutter-control/Makefile @@ -1,6 +1,6 @@ -all: er-example-server -# use this target explicitly if requried: er-plugtest-server +EXE=er-example-server +all: $(EXE) # variable for this Makefile # configure CoAP implementation (3|7|12|13) (er-coap-07 also supports CoAP draft 08) @@ -96,3 +96,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/light-shutter-control/flash.sh b/examples/osd/light-shutter-control/flash.sh index e92d472f6..e82962073 100755 --- a/examples/osd/light-shutter-control/flash.sh +++ b/examples/osd/light-shutter-control/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -sudo avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U flash:w:er-example-server.osd-merkur.hex:a -U eeprom:w:er-example-server.osd-merkur.eep:a +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/light-shutter-control/pcintkey.c b/examples/osd/light-shutter-control/pcintkey.c index a6e90afa5..8bbf5fcee 100644 --- a/examples/osd/light-shutter-control/pcintkey.c +++ b/examples/osd/light-shutter-control/pcintkey.c @@ -55,9 +55,32 @@ ISR(PCINT0_vect) // } // } } + +/* Compatibility of old vs new definitions in io.h */ +#ifndef DDE0 +#define DDE0 DDRE0 +#define DDE1 DDRE1 +#define DDE2 DDRE2 +#define DDE3 DDRE3 +#define DDE4 DDRE4 +#define DDE5 DDRE5 +#define DDE6 DDRE6 +#define DDE7 DDRE7 +#endif +#ifndef DDF0 +#define DDF0 DDRF0 +#define DDF1 DDRF1 +#define DDF2 DDRF2 +#define DDF3 DDRF3 +#define DDF4 DDRF4 +#define DDF5 DDRF5 +#define DDF6 DDRF6 +#define DDF7 DDRF7 +#endif + /** * \brief This will intialize the KEY for button readings. -*/ + */ void key_init(void) { diff --git a/examples/osd/light-shutter-control/run.sh b/examples/osd/light-shutter-control/run.sh index 4b11e9d2a..5d5cbbbb4 100755 --- a/examples/osd/light-shutter-control/run.sh +++ b/examples/osd/light-shutter-control/run.sh @@ -1,8 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur -avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur -avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.hex -avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.eep +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/merkurboard/Makefile b/examples/osd/merkurboard/Makefile index 58d6ce4ac..9cd7198da 100644 --- a/examples/osd/merkurboard/Makefile +++ b/examples/osd/merkurboard/Makefile @@ -1,13 +1,6 @@ -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size-server er-example-server.osd-merkur.hex \ - er-example-server.osd-merkur.eep \ - avr-size-client er-example-client.osd-merkur.hex \ - er-example-client.osd-merkur.eep -endif +EXE=er-example-server er-example-client -all: er-example-server er-example-client $(PLATFORM_FILES) - -# use target "er-plugtest-server" explicitly when requried +all: $(EXE) CONTIKI=../../.. @@ -72,38 +65,15 @@ connect-router-native: $(CONTIKI)/examples/ipv6/native-border-router/border-rout connect-minimal: sudo ip address add fdfd::1/64 dev tap0 -avr-size-server: er-example-server.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur +avr-size-server: er-example-server.$(TARGET).sz -er-example-server.osd-merkur.hex: er-example-server.osd-merkur - avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur \ - er-example-server.osd-merkur.hex +avr-size-client: er-example-server.$(TARGET).sz -er-example-server.osd-merkur.eep: er-example-server.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - er-example-server.osd-merkur er-example-server.osd-merkur.eep +flash-server: er-example-server.$(TARGET).u er-example-server.$(TARGET).eu -flash-server: er-example-server.osd-merkur.hex er-example-server.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:er-example-server.osd-merkur.hex:a -U \ - eeprom:w:er-example-server.osd-merkur.eep:a - -avr-size-client: er-example-client.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 er-example-client.osd-merkur - -er-example-client.osd-merkur.hex: er-example-client.osd-merkur - avr-objcopy -j .text -j .data -O ihex er-example-client.osd-merkur \ - er-example-client.osd-merkur.hex - -er-example-client.osd-merkur.eep: er-example-client.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - er-example-client.osd-merkur er-example-client.osd-merkur.eep - -flash-client: er-example-client.osd-merkur.hex er-example-client.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:er-example-client.osd-merkur.hex:a -U \ - eeprom:w:er-example-client.osd-merkur.eep:a +flash-client: er-example-client.$(TARGET).u er-example-client.$(TARGET).eu .PHONY: flash-client avr-size-client flash-server avr-size-server +.PRECIOUS: er-example-server.$(TARGET).hex er-example-server.$(TARGET).eep \ + er-example-client.$(TARGET).hex er-example-client.$(TARGET).eep + diff --git a/examples/osd/merkurboard/flash.sh b/examples/osd/merkurboard/flash.sh index c75149555..824d375a0 100755 --- a/examples/osd/merkurboard/flash.sh +++ b/examples/osd/merkurboard/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -sudo make flash-server +make TARGET=osd-merkur-128 flash-server diff --git a/examples/osd/merkurboard/run.sh b/examples/osd/merkurboard/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/merkurboard/run.sh +++ b/examples/osd/merkurboard/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/native-border-router/Makefile b/examples/osd/native-border-router/Makefile index d781ed35c..442a39e78 100644 --- a/examples/osd/native-border-router/Makefile +++ b/examples/osd/native-border-router/Makefile @@ -1,5 +1,5 @@ -CONTIKI_PROJECT=border-router -all: $(CONTIKI_PROJECT) +EXE=border-router +all: $(EXE) APPS = slip-cmd CONTIKI=../../.. @@ -25,3 +25,11 @@ include $(CONTIKI)/Makefile.include connect-router: border-router.native sudo ./border-router.native aaaa::1/64 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep + diff --git a/examples/osd/pingtheplug/Makefile b/examples/osd/pingtheplug/Makefile index 02b345590..881d7002c 100644 --- a/examples/osd/pingtheplug/Makefile +++ b/examples/osd/pingtheplug/Makefile @@ -1,10 +1,6 @@ -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size er-example-server.osd-merkur.hex \ - er-example-server.osd-merkur.eep -endif +EXE=er-example-server -all: er-example-server $(PLATFORM_FILES) -# use this target explicitly if requried: er-plugtest-server +all: $(EXE) CONTIKI=../../.. @@ -41,25 +37,6 @@ APPS += json json-resource include $(CONTIKI)/Makefile.include -avr-size: er-example-server.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur - -er-example-server.osd-merkur.hex: er-example-server.osd-merkur - avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur \ - er-example-server.osd-merkur.hex - -er-example-server.osd-merkur.eep: er-example-server.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - er-example-server.osd-merkur er-example-server.osd-merkur.eep - -flash: er-example-server.osd-merkur.hex er-example-server.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:er-example-server.osd-merkur.hex:a -U \ - eeprom:w:er-example-server.osd-merkur.eep:a - -.PHONY: flash avr-size - $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -71,3 +48,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/pingtheplug/er-example-server.c b/examples/osd/pingtheplug/er-example-server.c index ea6357e87..2b62e47ec 100644 --- a/examples/osd/pingtheplug/er-example-server.c +++ b/examples/osd/pingtheplug/er-example-server.c @@ -678,7 +678,7 @@ AUTOSTART_PROCESSES(&rest_server_example, &sensors_process); PROCESS_THREAD(rest_server_example, ev, data) { static struct etimer ds_periodic_timer; - static int ext4=0; +// static int ext4=0; static int ext5=0; static int ext6=0; // ext4 = is_button_ext4(); diff --git a/examples/osd/pingtheplug/flash.sh b/examples/osd/pingtheplug/flash.sh index e92d472f6..e82962073 100755 --- a/examples/osd/pingtheplug/flash.sh +++ b/examples/osd/pingtheplug/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -sudo avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U flash:w:er-example-server.osd-merkur.hex:a -U eeprom:w:er-example-server.osd-merkur.eep:a +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/pingtheplug/pcintkey.c b/examples/osd/pingtheplug/pcintkey.c index 5fc065e24..f9553efd4 100644 --- a/examples/osd/pingtheplug/pcintkey.c +++ b/examples/osd/pingtheplug/pcintkey.c @@ -55,9 +55,32 @@ ISR(PCINT0_vect) // } // } } + +/* Compatibility of old vs new definitions in io.h */ +#ifndef DDE0 +#define DDE0 DDRE0 +#define DDE1 DDRE1 +#define DDE2 DDRE2 +#define DDE3 DDRE3 +#define DDE4 DDRE4 +#define DDE5 DDRE5 +#define DDE6 DDRE6 +#define DDE7 DDRE7 +#endif +#ifndef DDF0 +#define DDF0 DDRF0 +#define DDF1 DDRF1 +#define DDF2 DDRF2 +#define DDF3 DDRF3 +#define DDF4 DDRF4 +#define DDF5 DDRF5 +#define DDF6 DDRF6 +#define DDF7 DDRF7 +#endif + /** * \brief This will intialize the KEY for button readings. -*/ + */ void key_init(void) { diff --git a/examples/osd/pingtheplug/run.sh b/examples/osd/pingtheplug/run.sh index 4b11e9d2a..5d5cbbbb4 100755 --- a/examples/osd/pingtheplug/run.sh +++ b/examples/osd/pingtheplug/run.sh @@ -1,8 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur -avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur -avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.hex -avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.eep +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/pir-sensor/Makefile b/examples/osd/pir-sensor/Makefile index 8a253c40d..0675e5538 100644 --- a/examples/osd/pir-sensor/Makefile +++ b/examples/osd/pir-sensor/Makefile @@ -1,6 +1,6 @@ -all: er-example-server -# use this target explicitly if requried: er-plugtest-server +EXE=er-example-server +all: $(EXE) # variable for this Makefile # configure CoAP implementation (3|7|12|13) (er-coap-07 also supports CoAP draft 08) @@ -92,3 +92,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/pir-sensor/flash.sh b/examples/osd/pir-sensor/flash.sh index e92d472f6..e82962073 100755 --- a/examples/osd/pir-sensor/flash.sh +++ b/examples/osd/pir-sensor/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -sudo avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U flash:w:er-example-server.osd-merkur.hex:a -U eeprom:w:er-example-server.osd-merkur.eep:a +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/pir-sensor/run.sh b/examples/osd/pir-sensor/run.sh index 4b11e9d2a..5d5cbbbb4 100755 --- a/examples/osd/pir-sensor/run.sh +++ b/examples/osd/pir-sensor/run.sh @@ -1,8 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur -avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur -avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.hex -avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.eep +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/poti/Makefile b/examples/osd/poti/Makefile index 536488828..8593b01cb 100644 --- a/examples/osd/poti/Makefile +++ b/examples/osd/poti/Makefile @@ -1,10 +1,6 @@ -SERIAL=/dev/ttyUSB0 -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size poti.osd-merkur.hex \ - poti.osd-merkur.eep -endif +EXE=poti -all: poti $(PLATFORM_FILES) +all: $(EXE) CONTIKI=../../.. @@ -74,21 +70,9 @@ connect-router-native: $(CONTIKI)/examples/ipv6/native-border-router/border-rout connect-minimal: sudo ip address add fdfd::1/64 dev tap0 -avr-size: poti.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 poti.osd-merkur +avr-size: $(EXE).$(TARGET).sz -poti.osd-merkur.hex: poti.osd-merkur - avr-objcopy -j .text -j .data -O ihex poti.osd-merkur \ - poti.osd-merkur.hex - -poti.osd-merkur.eep: poti.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - poti.osd-merkur poti.osd-merkur.eep - -flash: poti.osd-merkur.hex poti.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P$(SERIAL) -b57600 -e -U \ - flash:w:poti.osd-merkur.hex:a -U \ - eeprom:w:poti.osd-merkur.eep:a +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu .PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/poti/flash.sh b/examples/osd/poti/flash.sh index 2b14c43f4..e82962073 100755 --- a/examples/osd/poti/flash.sh +++ b/examples/osd/poti/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -make flash TARGET=osd-merkur +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/poti/run.sh b/examples/osd/poti/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/poti/run.sh +++ b/examples/osd/poti/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/powerbox/Makefile b/examples/osd/powerbox/Makefile index fa0c805ea..72ffc56e5 100644 --- a/examples/osd/powerbox/Makefile +++ b/examples/osd/powerbox/Makefile @@ -1,8 +1,6 @@ -all: er-example-server -# use this target explicitly if requried: er-plugtest-server +EXE=er-example-server - -# variable for this Makefile +all: $(EXE) # for some platforms UIP_CONF_IPV6=1 @@ -59,3 +57,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/powerbox/flash.sh b/examples/osd/powerbox/flash.sh index e92d472f6..e82962073 100755 --- a/examples/osd/powerbox/flash.sh +++ b/examples/osd/powerbox/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -sudo avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U flash:w:er-example-server.osd-merkur.hex:a -U eeprom:w:er-example-server.osd-merkur.eep:a +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/powerbox/run.sh b/examples/osd/powerbox/run.sh index 4b11e9d2a..5d5cbbbb4 100755 --- a/examples/osd/powerbox/run.sh +++ b/examples/osd/powerbox/run.sh @@ -1,8 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur -avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur -avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.hex -avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.eep +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/pwm-example/Makefile b/examples/osd/pwm-example/Makefile index 8aa7ec9c1..c10f7ff31 100644 --- a/examples/osd/pwm-example/Makefile +++ b/examples/osd/pwm-example/Makefile @@ -1,10 +1,6 @@ -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size er-example-server.osd-merkur.hex \ - er-example-server.osd-merkur.eep -endif +EXE=er-example-server -all: er-example-server $(PLATFORM_FILES) -# use this target explicitly if requried: er-plugtest-server +all: $(EXE) CONTIKI=../../.. @@ -39,25 +35,6 @@ APPS += json json-resource include $(CONTIKI)/Makefile.include -avr-size: er-example-server.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur - -er-example-server.osd-merkur.hex: er-example-server.osd-merkur - avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur \ - er-example-server.osd-merkur.hex - -er-example-server.osd-merkur.eep: er-example-server.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - er-example-server.osd-merkur er-example-server.osd-merkur.eep - -flash: er-example-server.osd-merkur.hex er-example-server.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:er-example-server.osd-merkur.hex:a -U \ - eeprom:w:er-example-server.osd-merkur.eep:a - -.PHONY: flash avr-size - $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) @@ -69,3 +46,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/pwm-example/flash.sh b/examples/osd/pwm-example/flash.sh index e9cb40bfc..e82962073 100755 --- a/examples/osd/pwm-example/flash.sh +++ b/examples/osd/pwm-example/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -make TARGET=osd-merkur flash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/pwm-example/run.sh b/examples/osd/pwm-example/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/pwm-example/run.sh +++ b/examples/osd/pwm-example/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/rpl-border-router/Makefile b/examples/osd/rpl-border-router/Makefile index ce90a4eac..e57591e80 100644 --- a/examples/osd/rpl-border-router/Makefile +++ b/examples/osd/rpl-border-router/Makefile @@ -1,5 +1,5 @@ -CONTIKI_PROJECT=border-router -all: $(CONTIKI_PROJECT) +EXE=border-router +all: $(EXE) CONTIKI=../../.. @@ -47,3 +47,10 @@ connect-router: $(CONTIKI)/tools/tunslip6 connect-router-cooja: $(CONTIKI)/tools/tunslip6 sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 $(PREFIX) + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/rpl-border-router/flash.sh b/examples/osd/rpl-border-router/flash.sh index 07cfc9a65..e82962073 100755 --- a/examples/osd/rpl-border-router/flash.sh +++ b/examples/osd/rpl-border-router/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -sudo avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U flash:w:border-router.osd-merkur.hex:a -U eeprom:w:border-router.osd-merkur.eep:a +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/rpl-border-router/run.sh b/examples/osd/rpl-border-router/run.sh index 9833eba6b..dc2b12de9 100755 --- a/examples/osd/rpl-border-router/run.sh +++ b/examples/osd/rpl-border-router/run.sh @@ -1,8 +1,6 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur -avr-size -C --mcu=MCU=atmega128rfa1 border-router.osd-merkur -avr-objcopy -j .text -j .data -O ihex border-router.osd-merkur border-router.osd-merkur.hex -avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex border-router.osd-merkur border-router.osd-merkur.eep +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 avr-size diff --git a/examples/osd/servo-sensor/Makefile b/examples/osd/servo-sensor/Makefile index 0349fc11f..72ffc56e5 100644 --- a/examples/osd/servo-sensor/Makefile +++ b/examples/osd/servo-sensor/Makefile @@ -1,10 +1,6 @@ -all: er-example-server -# use this target explicitly if requried: er-plugtest-server +EXE=er-example-server - -# variable for this Makefile -# configure CoAP implementation (3|7|12|13) (er-coap-07 also supports CoAP draft 08) -WITH_COAP=13 +all: $(EXE) # for some platforms UIP_CONF_IPV6=1 @@ -61,3 +57,10 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/servo-sensor/flash.sh b/examples/osd/servo-sensor/flash.sh index b91668634..e82962073 100755 --- a/examples/osd/servo-sensor/flash.sh +++ b/examples/osd/servo-sensor/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U flash:w:er-example-server.osd-merkur.hex:a -U eeprom:w:er-example-server.osd-merkur.eep:a +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/servo-sensor/run.sh b/examples/osd/servo-sensor/run.sh index 4b11e9d2a..5d5cbbbb4 100755 --- a/examples/osd/servo-sensor/run.sh +++ b/examples/osd/servo-sensor/run.sh @@ -1,8 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur -avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur -avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.hex -avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.eep +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/slip-radio/Makefile b/examples/osd/slip-radio/Makefile index 9d6f8ca88..d6bb0802c 100644 --- a/examples/osd/slip-radio/Makefile +++ b/examples/osd/slip-radio/Makefile @@ -1,5 +1,5 @@ -CONTIKI_PROJECT=slip-radio -all: $(CONTIKI_PROJECT) +EXE=slip-radio +all: $(EXE) APPS = slip-cmd ifeq ($(TARGET),) @@ -26,3 +26,10 @@ endif CONTIKI_WITH_RPL = 0 CONTIKI_WITH_IPV6 = 1 include $(CONTIKI)/Makefile.include + +avr-size: $(EXE).$(TARGET).sz + +flash: $(EXE).$(TARGET).u $(EXE).$(TARGET).eu + +.PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/slip-radio/flash.sh b/examples/osd/slip-radio/flash.sh index 633f3f434..e82962073 100755 --- a/examples/osd/slip-radio/flash.sh +++ b/examples/osd/slip-radio/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -sudo avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U flash:w:slip-radio.osd-merkur.hex:a -U eeprom:w:slip-radio.osd-merkur.eep:a +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/slip-radio/run.sh b/examples/osd/slip-radio/run.sh index eebc9a53a..5d5cbbbb4 100755 --- a/examples/osd/slip-radio/run.sh +++ b/examples/osd/slip-radio/run.sh @@ -1,8 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur -avr-size slip-radio.osd-merkur -avr-objcopy -j .text -j .data -O ihex slip-radio.osd-merkur slip-radio.osd-merkur.hex -avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex slip-radio.osd-merkur slip-radio.osd-merkur.eep +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/wallclock-time/Makefile b/examples/osd/wallclock-time/Makefile index 5c0062751..46d8e4625 100644 --- a/examples/osd/wallclock-time/Makefile +++ b/examples/osd/wallclock-time/Makefile @@ -1,10 +1,6 @@ -ifeq ($(TARGET), osd-merkur) -PLATFORM_FILES= avr-size er-example-server.osd-merkur.hex \ - er-example-server.osd-merkur.eep -endif +EXE=wallclock -all: er-example-server $(PLATFORM_FILES) -# use target "er-plugtest-server" explicitly when requried +all: $(EXE) CONTIKI=../../.. @@ -28,62 +24,25 @@ APPS += er-coap APPS += rest-engine APPS += json json-resource time -# optional rules to get assembly -#CUSTOM_RULE_C_TO_OBJECTDIR_O = 1 -#CUSTOM_RULE_S_TO_OBJECTDIR_O = 1 - CONTIKI_WITH_IPV6 = 1 include $(CONTIKI)/Makefile.include -# minimal-net target is currently broken in Contiki -ifeq ($(TARGET), minimal-net) -CFLAGS += -DHARD_CODED_ADDRESS=\"fdfd::10\" -${info INFO: er-example compiling with large buffers} -CFLAGS += -DUIP_CONF_BUFFER_SIZE=1300 -CFLAGS += -DREST_MAX_CHUNK_SIZE=1024 -CFLAGS += -DCOAP_MAX_HEADER_SIZE=176 -CONTIKI_WITH_RPL=0 -endif - -# optional rules to get assembly -#$(OBJECTDIR)/%.o: asmdir/%.S -# $(CC) $(CFLAGS) -MMD -c $< -o $@ -# @$(FINALIZE_DEPENDENCY) -# -#asmdir/%.S: %.c -# $(CC) $(CFLAGS) -MMD -S $< -o $@ - -# border router rules -$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c +$(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) -connect-router: $(CONTIKI)/tools/tunslip6 +connect-router: $(CONTIKI)/tools/tunslip6 sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64 -connect-router-cooja: $(CONTIKI)/tools/tunslip6 +connect-router-cooja: $(CONTIKI)/tools/tunslip6 sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 -p 60001 aaaa::1/64 -connect-router-native: $(CONTIKI)/examples/ipv6/native-border-router/border-router.native - sudo $(CONTIKI)/exmples/ipv6/native-border-router/border-router.native -a 127.0.0.1 -p 60001 aaaa::1/64 - connect-minimal: - sudo ip address add fdfd::1/64 dev tap0 + sudo ip address add fdfd::1/64 dev tap0 -avr-size: er-example-server.osd-merkur - avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur +avr-size: $(EXE).$(TARGET).sz -er-example-server.osd-merkur.hex: er-example-server.osd-merkur - avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur \ - er-example-server.osd-merkur.hex - -er-example-server.osd-merkur.eep: er-example-server.osd-merkur - avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \ - --change-section-lma .eeprom=0 -O ihex \ - er-example-server.osd-merkur er-example-server.osd-merkur.eep - -flash: er-example-server.osd-merkur.hex er-example-server.osd-merkur.eep - avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U \ - flash:w:er-example-server.osd-merkur.hex:a -U \ - eeprom:w:er-example-server.osd-merkur.eep:a +# At some point we may want to include the eeprom file +flash: $(EXE).$(TARGET).u # $(EXE).$(TARGET).eu .PHONY: flash avr-size +.PRECIOUS: $(EXE).$(TARGET).hex $(EXE).$(TARGET).eep diff --git a/examples/osd/wallclock-time/flash.sh b/examples/osd/wallclock-time/flash.sh index e9cb40bfc..e82962073 100755 --- a/examples/osd/wallclock-time/flash.sh +++ b/examples/osd/wallclock-time/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -make TARGET=osd-merkur flash +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/wallclock-time/run.sh b/examples/osd/wallclock-time/run.sh index 0fceb01ce..5d5cbbbb4 100755 --- a/examples/osd/wallclock-time/run.sh +++ b/examples/osd/wallclock-time/run.sh @@ -1,5 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/osd/wallclock-time/er-example-server.c b/examples/osd/wallclock-time/wallclock.c similarity index 99% rename from examples/osd/wallclock-time/er-example-server.c rename to examples/osd/wallclock-time/wallclock.c index 709844d2d..9e0013b78 100644 --- a/examples/osd/wallclock-time/er-example-server.c +++ b/examples/osd/wallclock-time/wallclock.c @@ -134,6 +134,7 @@ PROCESS_THREAD(rest_server_example, ev, data) /* Initialize the OSD Hardware. */ hw_init (); + led_set (0); /* Initialize the REST engine. */ rest_init_engine (); diff --git a/examples/osd/wirelessplug/Makefile b/examples/osd/wirelessplug/Makefile index 17792e430..aeaa5e2ad 100644 --- a/examples/osd/wirelessplug/Makefile +++ b/examples/osd/wirelessplug/Makefile @@ -1,11 +1,6 @@ -all: er-example-server er-example-client -# use this target explicitly if requried: er-plugtest-server - - -# variable for this Makefile -# configure CoAP implementation (3|7|12|13) (er-coap-07 also supports CoAP draft 08) -WITH_COAP=13 +EXE=er-example-server er-example-client +all: $(EXE) # variable for Makefile.include WITH_UIP6=1 @@ -95,3 +90,16 @@ connect-router-cooja: $(CONTIKI)/tools/tunslip6 connect-minimal: sudo ip address add fdfd::1/64 dev tap0 + +avr-size-server: er-example-server.$(TARGET).sz + +avr-size-client: er-example-server.$(TARGET).sz + +flash-server: er-example-server.$(TARGET).u er-example-server.$(TARGET).eu + +flash-client: er-example-client.$(TARGET).u er-example-client.$(TARGET).eu + +.PHONY: flash-client avr-size-client flash-server avr-size-server +.PRECIOUS: er-example-server.$(TARGET).hex er-example-server.$(TARGET).eep \ + er-example-client.$(TARGET).hex er-example-client.$(TARGET).eep + diff --git a/examples/osd/wirelessplug/flash.sh b/examples/osd/wirelessplug/flash.sh index e92d472f6..e82962073 100755 --- a/examples/osd/wirelessplug/flash.sh +++ b/examples/osd/wirelessplug/flash.sh @@ -1,2 +1,2 @@ #!/bin/bash -sudo avrdude -pm128rfa1 -c arduino -P/dev/ttyUSB0 -b57600 -e -U flash:w:er-example-server.osd-merkur.hex:a -U eeprom:w:er-example-server.osd-merkur.eep:a +make TARGET=osd-merkur-128 flash diff --git a/examples/osd/wirelessplug/run.sh b/examples/osd/wirelessplug/run.sh index 4b11e9d2a..5d5cbbbb4 100755 --- a/examples/osd/wirelessplug/run.sh +++ b/examples/osd/wirelessplug/run.sh @@ -1,8 +1,5 @@ #!/bin/bash # For the ages-old bootloader (before 2014) you want to use # BOOTLOADER_GET_MAC=0x0001f3a0 as parameter to make below. -make clean TARGET=osd-merkur -make TARGET=osd-merkur -avr-size -C --mcu=MCU=atmega128rfa1 er-example-server.osd-merkur -avr-objcopy -j .text -j .data -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.hex -avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 -O ihex er-example-server.osd-merkur er-example-server.osd-merkur.eep +make clean TARGET=osd-merkur-128 +make TARGET=osd-merkur-128 diff --git a/examples/ravenusbstick/Makefile.ravenusbstick b/examples/ravenusbstick/Makefile.ravenusbstick index d00ba6cba..27b244b11 100644 --- a/examples/ravenusbstick/Makefile.ravenusbstick +++ b/examples/ravenusbstick/Makefile.ravenusbstick @@ -8,7 +8,7 @@ CONTIKI_WITH_IPV6=0 CONTIKI = ../.. -MODULES+=core/net/mac/sicslowmac core/net/mac core/net/llsec +MODULES+=core/net/mac/sicslowmac core/net core/net/mac core/net/llsec PROJECT_SOURCEFILES += fakeuip.c diff --git a/examples/rime/example-unicast.c b/examples/rime/example-unicast.c index 5d28ef66f..7ee764a54 100644 --- a/examples/rime/example-unicast.c +++ b/examples/rime/example-unicast.c @@ -39,11 +39,6 @@ #include "contiki.h" #include "net/rime/rime.h" - -#include "dev/button-sensor.h" - -#include "dev/leds.h" - #include /*---------------------------------------------------------------------------*/ @@ -56,7 +51,19 @@ recv_uc(struct unicast_conn *c, const linkaddr_t *from) printf("unicast message received from %d.%d\n", from->u8[0], from->u8[1]); } -static const struct unicast_callbacks unicast_callbacks = {recv_uc}; +/*---------------------------------------------------------------------------*/ +static void +sent_uc(struct unicast_conn *c, int status, int num_tx) +{ + const linkaddr_t *dest = packetbuf_addr(PACKETBUF_ADDR_RECEIVER); + if(linkaddr_cmp(dest, &linkaddr_null)) { + return; + } + printf("unicast message sent to %d.%d: status %d num_tx %d\n", + dest->u8[0], dest->u8[1], status, num_tx); +} +/*---------------------------------------------------------------------------*/ +static const struct unicast_callbacks unicast_callbacks = {recv_uc, sent_uc}; static struct unicast_conn uc; /*---------------------------------------------------------------------------*/ PROCESS_THREAD(example_unicast_process, ev, data) diff --git a/examples/rssi-scanner/rssi-scanner-cc2420.c b/examples/rssi-scanner/rssi-scanner-cc2420.c index fbbfddf00..94c9056b9 100644 --- a/examples/rssi-scanner/rssi-scanner-cc2420.c +++ b/examples/rssi-scanner/rssi-scanner-cc2420.c @@ -77,7 +77,7 @@ do_rssi(void) printf("RSSI:"); for(channel = 0; channel <= 85; ++channel) { set_frq(channel); - printf("%d ", cc2420_rssi() + 55); + printf("%d ", cc2420_rssi() + 100); } printf("\n"); } diff --git a/examples/servreg-hack/example-servreg-client.c b/examples/servreg-hack/example-servreg-client.c index 108d40aeb..4557fab71 100644 --- a/examples/servreg-hack/example-servreg-client.c +++ b/examples/servreg-hack/example-servreg-client.c @@ -54,7 +54,7 @@ set_global_address(void) { uip_ipaddr_t ipaddr; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); } diff --git a/examples/servreg-hack/example-servreg-server.c b/examples/servreg-hack/example-servreg-server.c index 01dd7175a..4ff70060c 100644 --- a/examples/servreg-hack/example-servreg-server.c +++ b/examples/servreg-hack/example-servreg-server.c @@ -53,7 +53,7 @@ PROCESS_THREAD(example_servreg_server_process, ev, data) PROCESS_BEGIN(); /* Set a global address. */ - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); diff --git a/examples/sky/Makefile b/examples/sky/Makefile index dd09f0792..6d17fd421 100644 --- a/examples/sky/Makefile +++ b/examples/sky/Makefile @@ -3,7 +3,7 @@ ifndef TARGET TARGET=sky endif -all: blink sky-collect #rt-leds test-button test-cfs tcprudolph0 +all: blink sky-collect #rt-leds test-button tcprudolph0 %.tgz: %.ihex mkdir $(basename $<) ; \ diff --git a/examples/telnet-server/Makefile.c64.defines b/examples/telnet-server/Makefile.c64.defines index bcd39d550..caf0dfa69 100644 --- a/examples/telnet-server/Makefile.c64.defines +++ b/examples/telnet-server/Makefile.c64.defines @@ -1 +1 @@ -DEFINES = CONNECTIONS=3,WITH_LOGGING,WITH_CLIENT,WITH_DNS +DEFINES = CONNECTIONS=3,WITH_LOGGING,WITH_CLIENT,WITH_DNS,WITH_PFS diff --git a/examples/udp-ipv6/udp-client.c b/examples/udp-ipv6/udp-client.c index 7f9b7659e..85854a48b 100644 --- a/examples/udp-ipv6/udp-client.c +++ b/examples/udp-ipv6/udp-client.c @@ -98,7 +98,7 @@ set_global_address(void) { uip_ipaddr_t ipaddr; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); } @@ -111,7 +111,7 @@ set_connection_address(uip_ipaddr_t *ipaddr) #if RESOLV_CONF_SUPPORTS_MDNS #define UDP_CONNECTION_ADDR contiki-udp-server.local #elif UIP_CONF_ROUTER -#define UDP_CONNECTION_ADDR aaaa:0:0:0:0212:7404:0004:0404 +#define UDP_CONNECTION_ADDR fd00:0:0:0:0212:7404:0004:0404 #else #define UDP_CONNECTION_ADDR fe80:0:0:0:6466:6666:6666:6666 #endif diff --git a/examples/udp-ipv6/udp-server.c b/examples/udp-ipv6/udp-server.c index c56720f9a..eeb7de700 100644 --- a/examples/udp-ipv6/udp-server.c +++ b/examples/udp-ipv6/udp-server.c @@ -99,7 +99,7 @@ PROCESS_THREAD(udp_server_process, ev, data) #endif #if UIP_CONF_ROUTER - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); #endif /* UIP_CONF_ROUTER */ diff --git a/examples/udp-stream/udp-stream.c b/examples/udp-stream/udp-stream.c index c10e8d6a5..875b594d8 100644 --- a/examples/udp-stream/udp-stream.c +++ b/examples/udp-stream/udp-stream.c @@ -74,7 +74,7 @@ set_global_address(void) int i; uint8_t state; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); @@ -102,7 +102,7 @@ create_rpl_dag(uip_ipaddr_t *ipaddr) rpl_set_root(RPL_DEFAULT_INSTANCE, ipaddr); dag = rpl_get_any_dag(); - uip_ip6addr(&prefix, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &prefix, 64); printf("created a new RPL dag\n"); } else { diff --git a/examples/webserver-ipv6/README.md b/examples/webserver-ipv6/README.md index ddeb5cb87..fae6057a1 100644 --- a/examples/webserver-ipv6/README.md +++ b/examples/webserver-ipv6/README.md @@ -41,7 +41,7 @@ On linux you can set up router advertisements as follows: - You might need to add a route: - ip -6 route add aaaa:0000:0000:0000:0206:98ff:fe00:0232/64 dev tap0 + ip -6 route add fd00:0000:0000:0000:0206:98ff:fe00:0232/64 dev tap0 - Then configure a global address by sending a router advertisement (RA) with a prefix option. You can use radvd for example to generate such a packet. diff --git a/examples/zolertia/z1/ipv6/z1-websense/Makefile b/examples/zolertia/z1/ipv6/z1-websense/Makefile index 717802ae9..8db74458e 100644 --- a/examples/zolertia/z1/ipv6/z1-websense/Makefile +++ b/examples/zolertia/z1/ipv6/z1-websense/Makefile @@ -18,10 +18,10 @@ $(CONTIKI)/tools/tunslip6: $(CONTIKI)/tools/tunslip6.c (cd $(CONTIKI)/tools && $(MAKE) tunslip6) connect-router: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 aaaa::1/64 + sudo $(CONTIKI)/tools/tunslip6 fd00::1/64 connect-router-cooja: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 aaaa::1/64 + sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 fd00::1/64 CUSTOM_RULE_LINK=1 %.$(TARGET): %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(LD) $(LDFLAGS) $(TARGET_STARTFILES) ${filter-out %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -o $@ -lm diff --git a/examples/zolertia/z1/ipv6/z1-websense/README.md b/examples/zolertia/z1/ipv6/z1-websense/README.md index af373adc6..82e7f34ee 100644 --- a/examples/zolertia/z1/ipv6/z1-websense/README.md +++ b/examples/zolertia/z1/ipv6/z1-websense/README.md @@ -19,8 +19,8 @@ To test the example in COOJA under Linux 3. You should now be able to browse to the nodes using your web browser: - Router: http://[aaaa::0212:7401:0001:0101]/ - Node 2: http://[aaaa::0212:7402:0002:0202]/ + Router: http://[fd00::0212:7401:0001:0101]/ + Node 2: http://[fd00::0212:7402:0002:0202]/ To run the example on real nodes under Linux diff --git a/examples/zolertia/z1/ipv6/z1-websense/websense-remote.c b/examples/zolertia/z1/ipv6/z1-websense/websense-remote.c index 7cfebd355..a6336260d 100644 --- a/examples/zolertia/z1/ipv6/z1-websense/websense-remote.c +++ b/examples/zolertia/z1/ipv6/z1-websense/websense-remote.c @@ -45,13 +45,13 @@ #include /*---------------------------------------------------------------------------*/ /* The address of the server to register the services for this node */ -#define SERVER "aaaa::1" +#define SERVER "fd00::1" /* This command registers two services (/0 and /1) to turn the leds on or off */ #define REGISTER_COMMAND "/r?p=0&d=Turn%20off%20leds&p=1&d=Turn%20on%20leds" /* The address of the other node to control */ -#define OTHER_NODE "aaaa::212:7403:3:303" +#define OTHER_NODE "fd00::212:7403:3:303" /* The commands to send to the other node */ #define SET_LEDS_ON "/1" diff --git a/examples/zolertia/z1/test-adxl345.c b/examples/zolertia/z1/test-adxl345.c index 259c46fde..a5e199bef 100644 --- a/examples/zolertia/z1/test-adxl345.c +++ b/examples/zolertia/z1/test-adxl345.c @@ -42,10 +42,7 @@ #include #include "contiki.h" -#include "serial-shell.h" -#include "shell-ps.h" -#include "shell-file.h" -#include "shell-text.h" +#include "dev/leds.h" #include "dev/adxl345.h" /*---------------------------------------------------------------------------*/ #define LED_INT_ONTIME (CLOCK_SECOND / 2) @@ -91,7 +88,7 @@ print_int(uint16_t reg) void accm_ff_cb(uint8_t reg) { - L_ON(LEDS_B); + leds_on(LEDS_BLUE); process_post(&led_process, led_off_event, NULL); printf("~~[%u] Freefall detected! (0x%02X) -- ", ((uint16_t)clock_time()) / 128, reg); @@ -105,11 +102,11 @@ accm_tap_cb(uint8_t reg) { process_post(&led_process, led_off_event, NULL); if(reg & ADXL345_INT_DOUBLETAP) { - L_ON(LEDS_G); + leds_on(LEDS_GREEN); printf("~~[%u] DoubleTap detected! (0x%02X) -- ", ((uint16_t)clock_time()) / 128, reg); } else { - L_ON(LEDS_R); + leds_on(LEDS_RED); printf("~~[%u] Tap detected! (0x%02X) -- ", ((uint16_t)clock_time()) / 128, reg); } @@ -122,46 +119,46 @@ PROCESS_THREAD(led_process, ev, data) { PROCESS_WAIT_EVENT_UNTIL(ev == led_off_event); etimer_set(&led_etimer, LED_INT_ONTIME); PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&led_etimer)); - L_OFF(LEDS_R + LEDS_G + LEDS_B); + leds_off(LEDS_RED + LEDS_GREEN + LEDS_BLUE); } PROCESS_END(); } /*---------------------------------------------------------------------------*/ /* Main process, setups */ -PROCESS_THREAD(accel_process, ev, data) { +PROCESS_THREAD(accel_process, ev, data) +{ PROCESS_BEGIN(); - { - int16_t x, y, z; - serial_shell_init(); - shell_ps_init(); - shell_file_init(); /* for printing out files */ - shell_text_init(); /* for binprint */ + int16_t x, y, z; - /* Register the event used for lighting up an LED when interrupt strikes. */ - led_off_event = process_alloc_event(); + /* Register the event used for lighting up an LED when interrupt strikes. */ + led_off_event = process_alloc_event(); - /* Start and setup the accelerometer with default values, eg no interrupts enabled. */ - accm_init(); + /* Start and setup the accelerometer with default values, eg no interrupts + * enabled. + */ + SENSORS_ACTIVATE(adxl345); - /* Register the callback functions for each interrupt */ - ACCM_REGISTER_INT1_CB(accm_ff_cb); - ACCM_REGISTER_INT2_CB(accm_tap_cb); + /* Register the callback functions for each interrupt */ + ACCM_REGISTER_INT1_CB(accm_ff_cb); + ACCM_REGISTER_INT2_CB(accm_tap_cb); - /* Set what strikes the corresponding interrupts. Several interrupts per pin is - possible. For the eight possible interrupts, see adxl345.h and adxl345 datasheet. */ - accm_set_irq(ADXL345_INT_FREEFALL, ADXL345_INT_TAP + ADXL345_INT_DOUBLETAP); + /* Set what strikes the corresponding interrupts. Several interrupts per + * pin is possible. For the eight possible interrupts, see adxl345.h and + * adxl345 datasheet. + */ + accm_set_irq(ADXL345_INT_FREEFALL, ADXL345_INT_TAP + ADXL345_INT_DOUBLETAP); - while(1) { - x = accm_read_axis(X_AXIS); - y = accm_read_axis(Y_AXIS); - z = accm_read_axis(Z_AXIS); - printf("x: %d y: %d z: %d\n", x, y, z); + while(1) { + x = adxl345.value(X_AXIS); + y = adxl345.value(Y_AXIS); + z = adxl345.value(Z_AXIS); + printf("x: %d y: %d z: %d\n", x, y, z); - etimer_set(&et, ACCM_READ_INTERVAL); - PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); - } + etimer_set(&et, ACCM_READ_INTERVAL); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); } + PROCESS_END(); } /*---------------------------------------------------------------------------*/ diff --git a/examples/zolertia/z1/test-tmp102.c b/examples/zolertia/z1/test-tmp102.c index 5d8be7a08..ab5e7aca8 100644 --- a/examples/zolertia/z1/test-tmp102.c +++ b/examples/zolertia/z1/test-tmp102.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Zolertia(TM) is a trademark of Advancare,SL + * Copyright (c) 2010-2016, Zolertia * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,9 +32,10 @@ /*---------------------------------------------------------------------------*/ /** * \file - * A quick program for testing the tmp102 driver in the Z1 platform + * A quick program for testing the tmp102 sensor in the Z1 platform * \author * Enric M. Calvo + * Antonio Lignan */ /*---------------------------------------------------------------------------*/ #include @@ -44,7 +45,7 @@ /*---------------------------------------------------------------------------*/ #define TMP102_READ_INTERVAL (CLOCK_SECOND / 2) /*---------------------------------------------------------------------------*/ -PROCESS(temp_process, "Test Temperature process"); +PROCESS(temp_process, "TMP102 Temperature sensor process"); AUTOSTART_PROCESSES(&temp_process); /*---------------------------------------------------------------------------*/ static struct etimer et; @@ -55,12 +56,12 @@ PROCESS_THREAD(temp_process, ev, data) int16_t temp; - tmp102_init(); + SENSORS_ACTIVATE(tmp102); while(1) { etimer_set(&et, TMP102_READ_INTERVAL); PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); - temp = tmp102_read_temp_x100(); + temp = tmp102.value(TMP102_READ); printf("Temp = %d\n", temp); } PROCESS_END(); diff --git a/examples/zolertia/zoul/Makefile b/examples/zolertia/zoul/Makefile index c4ad2affb..ddd89f4ca 100644 --- a/examples/zolertia/zoul/Makefile +++ b/examples/zolertia/zoul/Makefile @@ -5,10 +5,11 @@ CONTIKI_PROJECT += test-bmp085-bmp180 test-motion test-rotation-sensor CONTIKI_PROJECT += test-grove-light-sensor test-grove-loudness-sensor CONTIKI_PROJECT += test-weather-meter test-grove-gyro test-lcd test-iaq CONTIKI_PROJECT += test-pm10-sensor test-vac-sensor test-aac-sensor +CONTIKI_PROJECT += test-zonik CONTIKI_TARGET_SOURCEFILES += tsl2563.c sht25.c bmpx8x.c motion-sensor.c CONTIKI_TARGET_SOURCEFILES += adc-sensors.c weather-meter.c grove-gyro.c -CONTIKI_TARGET_SOURCEFILES += rgb-bl-lcd.c pm10-sensor.c iaq.c +CONTIKI_TARGET_SOURCEFILES += rgb-bl-lcd.c pm10-sensor.c iaq.c zonik.c relay.c all: $(CONTIKI_PROJECT) diff --git a/examples/zolertia/zoul/at-test/Makefile b/examples/zolertia/zoul/at-test/Makefile new file mode 100644 index 000000000..14ab8b54b --- /dev/null +++ b/examples/zolertia/zoul/at-test/Makefile @@ -0,0 +1,7 @@ +DEFINES+=PROJECT_CONF_H=\"project-conf.h\" +CONTIKI_PROJECT = at-master-test +APPS = at-master +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/zolertia/zoul/at-test/at-master-test.c b/examples/zolertia/zoul/at-test/at-master-test.c new file mode 100644 index 000000000..520c28bdb --- /dev/null +++ b/examples/zolertia/zoul/at-test/at-master-test.c @@ -0,0 +1,487 @@ +/* + * Copyright (c) 2016, Zolertia - http://www.zolertia.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 Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup zoul-AT-master-test + * @{ + * + * Test the Zoul hardware using AT commands + * @{ + * + * \author + * Antonio Lignan + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "cpu.h" +#include "at-master.h" +#include "sys/ctimer.h" +#include "sys/process.h" +#include "dev/adc.h" +#include "dev/leds.h" +#include "dev/watchdog.h" +#include "dev/sys-ctrl.h" +#include "dev/gpio.h" +#include "dev/ioc.h" +#include "net/rime/rime.h" +#include "lib/list.h" +#include "dev/sha256.h" +#include +#include +#include +/*---------------------------------------------------------------------------*/ +PROCESS(at_test_process, "AT test process"); +AUTOSTART_PROCESSES(&at_test_process); +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +static struct at_cmd at_cmd_test; +static struct at_cmd at_cmd_board; +static struct at_cmd at_cmd_led; +static struct at_cmd at_cmd_addr; +static struct at_cmd at_cmd_gpio; +static struct at_cmd at_cmd_read; +static struct at_cmd at_cmd_flop; +static struct at_cmd at_cmd_reset; +static struct at_cmd at_cmd_sha256; +static struct at_cmd at_cmd_adc; +/*---------------------------------------------------------------------------*/ +#define HWTEST_GPIO_INPUT 0 +#define HWTEST_GPIO_OUTPUT 1 +#define HWTEST_GPIO_OUTPUT_ODD 3 +#define HWTEST_GPIO_OUTPUT_LIST 4 +#define HWTEST_GPIO_OUTPUT_MASK 0x55 +#define HWTEST_GPIO_OUTPUT_ODD_MASK 0xAA +/*---------------------------------------------------------------------------*/ +typedef struct { + char *name; + uint8_t port; + uint8_t pin; +} gpio_list_t; +/*---------------------------------------------------------------------------*/ +static struct ctimer ct; +/*---------------------------------------------------------------------------*/ +static void +floppin(uint8_t port, uint8_t pin) +{ + uint8_t i; + GPIO_CLR_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + clock_delay_usec(500); + for(i = 0; i < 50; i++) { + GPIO_SET_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + clock_delay_usec(500); + GPIO_CLR_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + clock_delay_usec(500); + } +} +/*---------------------------------------------------------------------------*/ +#if DEBUG +static char * +pname(uint8_t num) +{ + if(num == GPIO_A_NUM) { + return "PA"; + } + if(num == GPIO_B_NUM) { + return "PB"; + } + if(num == GPIO_C_NUM) { + return "PC"; + } + if(num == GPIO_D_NUM) { + return "PD"; + } + return "INVALID"; +} +#endif +/*---------------------------------------------------------------------------*/ +static void +config_gpio(uint8_t port, uint8_t pin, uint8_t type) +{ + GPIO_SOFTWARE_CONTROL(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + if(type == HWTEST_GPIO_OUTPUT) { + GPIO_SET_OUTPUT(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + } else if(type == HWTEST_GPIO_INPUT) { + GPIO_SET_INPUT(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + } +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_test_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + AT_RESPONSE("Hello!"); + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_board_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + AT_RESPONSE(BOARD_STRING); + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_flop_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + /* Format: AT&FLOP=PN where P(ort)N(number) */ + uint8_t port; + uint8_t pin = atoi(&data[9]); + + if((pin < 0) || (pin > 9)) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if(strncmp(&data[8], "A", 1) == 0) { + port = GPIO_A_NUM; + } else if(strncmp(&data[8], "B", 1) == 0) { + port = GPIO_B_NUM; + } else if(strncmp(&data[8], "C", 1) == 0) { + port = GPIO_C_NUM; + } else if(strncmp(&data[8], "D", 1) == 0) { + port = GPIO_D_NUM; + } else { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + config_gpio(port, pin, HWTEST_GPIO_OUTPUT); + floppin(port, pin); + + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_address_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + static char _lladdr[17]; + snprintf(_lladdr, 17, "%02x%02x%02x%02x%02x%02x%02x%02x", + linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1], + linkaddr_node_addr.u8[2], linkaddr_node_addr.u8[3], + linkaddr_node_addr.u8[4], linkaddr_node_addr.u8[5], + linkaddr_node_addr.u8[6], linkaddr_node_addr.u8[7]); + + AT_RESPONSE(_lladdr); + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_reset_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + uint8_t reset_val = atoi(&data[9]); + /* AT&RESET=n, where n: + * 0 : CC2538 soft reset + */ + if((reset_val != 0) && (reset_val != 1)) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + /* Send the response and wait a second until executing the command */ + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); + + if(reset_val == 0) { + ctimer_set(&ct, CLOCK_SECOND, sys_ctrl_reset, NULL); + } +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_leds_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + /* Format: AT&LED=L,s where L(ed)=R/G/B, s(tate)=1/0*/ + uint8_t led; + uint8_t state = strncmp(&data[9], "1", 1) ? 0 : 1; + + if(strncmp(&data[8], ",", 1) != 0) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if(strncmp(&data[7], "R", 1) == 0) { + led = LEDS_RED; + } else if(strncmp(&data[7], "G", 1) == 0) { + led = LEDS_GREEN; + } else if(strncmp(&data[7], "B", 1) == 0) { + led = LEDS_BLUE; + } else { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if(state) { + leds_on(led); + } else { + leds_off(led); + } + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_gpio_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + /* Format: AT&GPIO=PN,s where P(ort)N(number), s(tate)=1/0 */ + uint8_t port; + uint8_t state = strncmp(&data[11], "1", 1) ? 0 : 1; + uint8_t pin = atoi(&data[9]); + + if(strncmp(&data[10], ",", 1) != 0) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if((pin < 0) || (pin > 7)) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if((state < 0) || (state > 1)) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if(strncmp(&data[8], "A", 1) == 0) { + port = GPIO_A_NUM; + } else if(strncmp(&data[8], "B", 1) == 0) { + port = GPIO_B_NUM; + } else if(strncmp(&data[8], "C", 1) == 0) { + port = GPIO_C_NUM; + } else if(strncmp(&data[8], "D", 1) == 0) { + port = GPIO_D_NUM; + } else { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + config_gpio(port, pin, HWTEST_GPIO_OUTPUT); + + if(state) { + GPIO_SET_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + } else { + GPIO_CLR_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + } + + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_adc_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + /* Format: AT&ADC=N where N is 4-7, it can be "*" to read all */ + uint8_t i, pin; + uint16_t res[4]; + char read_result[24]; + + if(strncmp(&data[7], "*", 1) == 0) { + pin = 8; + } else { + pin = atoi(&data[7]); + } + + if((pin < 4) || (pin > 8)) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if(pin < 8) { + config_gpio(GPIO_A_NUM, pin, HWTEST_GPIO_INPUT); + ioc_set_over(GPIO_A_NUM, pin, IOC_OVERRIDE_ANA); + res[pin - 4] = adc_get((SOC_ADC_ADCCON_CH_AIN0 + pin), + SOC_ADC_ADCCON_REF_AVDD5, + SOC_ADC_ADCCON_DIV_512); + res[pin - 4] = res[pin - 4] / 10; + PRINTF("ADC%u: %04d\n", pin, res[pin - 4]); + snprintf(read_result, 5, "%04d", res[pin - 4]); + } else { + for(i = 4; i < 8; i++) { + config_gpio(GPIO_A_NUM, i, HWTEST_GPIO_INPUT); + ioc_set_over(GPIO_A_NUM, i, IOC_OVERRIDE_ANA); + res[i - 4] = adc_get((SOC_ADC_ADCCON_CH_AIN0 + i), + SOC_ADC_ADCCON_REF_AVDD5, + SOC_ADC_ADCCON_DIV_512); + res[i - 4] = res[i - 4] / 10; + } + snprintf(read_result, 24, "%04d %04d %04d %04d", res[0], res[1], + res[2], res[3]); + } + + AT_RESPONSE(read_result); + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_read_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + /* Format: AT&READ=PN where P(ort)N(number), N can be "*" to read all */ + uint8_t port, pin; + char read_result[5]; + + if(strncmp(&data[9], "*", 1) == 0) { + pin = 0xFF; + } else { + pin = atoi(&data[9]); + } + + if((pin < 0) || (pin > 7)) { + if(pin != 0xFF) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + } + + if(pin < 8) { + pin = GPIO_PIN_MASK(pin); + } + + /* Exclude PA0-PA3 */ + if(strncmp(&data[8], "A", 1) == 0) { + port = GPIO_A_NUM; + if(pin < 0x1F) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } else { + if(pin == 0xFF) { + pin = 0xF0; + } + } + } else if(strncmp(&data[8], "B", 1) == 0) { + port = GPIO_B_NUM; + } else if(strncmp(&data[8], "C", 1) == 0) { + port = GPIO_C_NUM; + } else if(strncmp(&data[8], "D", 1) == 0) { + port = GPIO_D_NUM; + } else { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + config_gpio(port, pin, HWTEST_GPIO_INPUT); + snprintf(read_result, 5, "0x%02X", + (uint16_t)GPIO_READ_PIN(GPIO_PORT_TO_BASE(port), pin)); + AT_RESPONSE(read_result); + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +static void +at_cmd_sha256_callback(struct at_cmd *cmd, uint8_t len, char *data) +{ + /* Format: AT&SHA256=s, where s is a string up to 64 bytes */ + uint8_t i; + char tmp[4], sha256[32], sha256_res[64]; + static sha256_state_t state; + + crypto_init(); + if(sha256_init(&state) != CRYPTO_SUCCESS) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if(sha256_process(&state, &data[10], + len - (cmd->cmd_hdr_len)) != CRYPTO_SUCCESS) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + if(sha256_done(&state, sha256) != CRYPTO_SUCCESS) { + AT_RESPONSE(AT_DEFAULT_RESPONSE_ERROR); + return; + } + + crypto_disable(); + + PRINTF("Input: %s:\n", &data[10]); + snprintf(tmp, 3, "%02X", sha256[0]); + strncpy(sha256_res, tmp, 3); + for(i = 1; i < 32; i++) { + PRINTF("0x%02X ", sha256[i]); + snprintf(tmp, 3, "%02X", sha256[i]); + strcat(sha256_res, tmp); + } + PRINTF("\nSHA256: %s\n", sha256_res); + AT_RESPONSE(sha256_res); + AT_RESPONSE(AT_DEFAULT_RESPONSE_OK); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(at_test_process, ev, data) +{ + PROCESS_BEGIN(); + struct at_cmd *a; + + /* Initialize the driver, default is UART0 */ + at_init(0); + + /* Register a list of commands, is mandatory to start with "AT" */ + at_register(&at_cmd_test, &at_test_process, "AT", 2, 2, + at_cmd_test_callback); + at_register(&at_cmd_board, &at_test_process, "AT&V", 4, 4, + at_cmd_board_callback); + at_register(&at_cmd_led, &at_test_process, "AT&LED", 6, 10, + at_cmd_leds_callback); + at_register(&at_cmd_addr, &at_test_process, "AT&A", 4, 4, + at_cmd_address_callback); + at_register(&at_cmd_gpio, &at_test_process, "AT&GPIO=", 8, 12, + at_cmd_gpio_callback); + at_register(&at_cmd_read, &at_test_process, "AT&READ=", 8, 10, + at_cmd_read_callback); + at_register(&at_cmd_adc, &at_test_process, "AT&ADC=", 7, 8, + at_cmd_adc_callback); + at_register(&at_cmd_flop, &at_test_process, "AT&FLOP=", 8, 10, + at_cmd_flop_callback); + at_register(&at_cmd_reset, &at_test_process, "AT&RESET=", 9, 10, + at_cmd_reset_callback); + at_register(&at_cmd_sha256, &at_test_process, "AT&SHA256=", 10, 64, + at_cmd_sha256_callback); + + /* Print the command list */ + PRINTF("AT command list:\n"); + for(a = at_list(); a != NULL; a = list_item_next(a)) { + PRINTF("* HDR %s LEN %u MAX %u\n", a->cmd_header, a->cmd_hdr_len, + a->cmd_max_len); + } + + /* + * When an AT command is received over the serial line, the registered + * callbacks will be invoked, let the process spin until then + */ + while(1) { + PROCESS_YIELD(); + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + */ diff --git a/examples/zolertia/zoul/at-test/project-conf.h b/examples/zolertia/zoul/at-test/project-conf.h new file mode 100644 index 000000000..4a29f1d59 --- /dev/null +++ b/examples/zolertia/zoul/at-test/project-conf.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016, Zolertia - http://www.zolertia.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 Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup remote-examples + * @{ + * + * \defgroup zoul-AT-master-test + * + * Test the Zoul hardware over AT API + * @{ + * + * \file + * Test the Zoul hardware over AT API + * + * \author + * Antonio Lignan + */ +/*---------------------------------------------------------------------------*/ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +/* Drop maximum to PM1 to have the UART on all the time */ +#define LPM_CONF_MAX_PM 1 + +/* the radio is not used */ +#define CONTIKI_NO_NET 1 + +/* Override serial-line defaults */ +#define SERIAL_LINE_CONF_BUFSIZE 128 +#undef IGNORE_CHAR +#undef END +#define IGNORE_CHAR(c) (c == 0x0d) +#define END 0x0a + +#define NETSTACK_CONF_RDC nullrdc_driver + +#endif /* PROJECT_CONF_H_ */ + +/** @} */ diff --git a/examples/zolertia/zoul/cc1200-sniffer/Makefile b/examples/zolertia/zoul/cc1200-sniffer/Makefile new file mode 100644 index 000000000..5c2fa1675 --- /dev/null +++ b/examples/zolertia/zoul/cc1200-sniffer/Makefile @@ -0,0 +1,10 @@ +DEFINES+=PROJECT_CONF_H=\"project-conf.h\" +PROJECT_SOURCEFILES += stub-rdc.c + +CONTIKI_PROJECT = sniffer + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../../.. +CONTIKI_WITH_RIME = 1 +include $(CONTIKI)/Makefile.include diff --git a/examples/zolertia/zoul/cc1200-sniffer/Makefile.target b/examples/zolertia/zoul/cc1200-sniffer/Makefile.target new file mode 100644 index 000000000..75430a6e4 --- /dev/null +++ b/examples/zolertia/zoul/cc1200-sniffer/Makefile.target @@ -0,0 +1 @@ +TARGET = zoul diff --git a/examples/zolertia/zoul/cc1200-sniffer/README.md b/examples/zolertia/zoul/cc1200-sniffer/README.md new file mode 100644 index 000000000..95ec65193 --- /dev/null +++ b/examples/zolertia/zoul/cc1200-sniffer/README.md @@ -0,0 +1,35 @@ +CC1200 README +======================== + +The CC1200 sniffer is heavily based on the CC2538 sniffer, used with the +IEEE 802.15.4 Sensniff application by George Oikonomou. + +Sensniff requires [Wireshark](http://www.wireshark.org/). + +Get Wireshark +----------------- +The best way is to go to the Wireshark site and follow the instructions for your +specific OS, in a bundle this will install for Ubuntu/LInux systems: + +`sudo apt-get install wireshark` + +To allow non-super users to capture packets: + +`sudo dpkg-reconfigure wireshark` + +Flash the sniffer application to the Zoul +----------------- +make sniffer.upload + +Run Sensniff +----------------- +``` +git clone https://github.com/g-oikonomou/sensniff +cd sensniff/host +python sensniff.py --non-interactive -d /dev/ttyUSB0 -b 460800 +``` + +On another terminal run: + +`sudo wireshark -i /tmp/sensnifff` + diff --git a/examples/zolertia/zoul/cc1200-sniffer/netstack.c b/examples/zolertia/zoul/cc1200-sniffer/netstack.c new file mode 100644 index 000000000..3aeb6968e --- /dev/null +++ b/examples/zolertia/zoul/cc1200-sniffer/netstack.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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 + * Stub file overriding core/net/netstack.c. What we want to achieve + * here is call netstack_init from main without initialising the RDC, + * MAC and Network layers. It will just turn on the radio instead. + * + * \author + * George Oikonomou - + */ +#include "netstack.h" +/*---------------------------------------------------------------------------*/ +void +netstack_init(void) +{ + NETSTACK_RADIO.init(); + NETSTACK_RADIO.on(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/zolertia/zoul/cc1200-sniffer/project-conf.h b/examples/zolertia/zoul/cc1200-sniffer/project-conf.h new file mode 100644 index 000000000..fca02e711 --- /dev/null +++ b/examples/zolertia/zoul/cc1200-sniffer/project-conf.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup zoul-cc1200-sniffer + * @{ + * + * \file + * Project specific configuration defines for the CC1200 sniffer + */ +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + +#define CC1200_CONF_SNIFFER 1 +#define CC1200_RF_CONF_SNIFFER_UART 0 +#define CC1200_CONF_RF_CFG cc1200_802154g_863_870_fsk_50kbps + +#undef NETSTACK_CONF_RADIO +#define NETSTACK_CONF_RADIO cc1200_driver + +#define CC1200_CONF_USE_GPIO2 0 +#define CC1200_CONF_USE_RX_WATCHDOG 0 +#define ANTENNA_SW_SELECT_DEF_CONF ANTENNA_SW_SELECT_SUBGHZ + +#undef NETSTACK_CONF_RDC +#define NETSTACK_CONF_RDC stub_rdc_driver + +#define UART0_CONF_BAUD_RATE 460800 + +#endif /* PROJECT_CONF_H_ */ + +/** @} */ diff --git a/examples/zolertia/zoul/cc1200-sniffer/sniffer.c b/examples/zolertia/zoul/cc1200-sniffer/sniffer.c new file mode 100644 index 000000000..a0241f795 --- /dev/null +++ b/examples/zolertia/zoul/cc1200-sniffer/sniffer.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup zoul-examples + * @{ + * + * \defgroup zoul-cc1200-sniffer CC1200 Sniffer + * + * Sniffer for the Zolertia's Zoul CC1200 on-board radio + * + * This example is to be used combined with the sensniff host-side tool, + * which can be downloaded from: https://github.com/g-oikonomou/sensniff + * + * @{ + * + * \file + * Implementation of a Sniffer Process Thread + */ +#include "contiki.h" + +#define DEBUG DEBUG_NONE +#include "net/ip/uip-debug.h" +/*---------------------------------------------------------------------------*/ +PROCESS(sniffer_process, "Sniffer process"); +AUTOSTART_PROCESSES(&sniffer_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(sniffer_process, ev, data) +{ + PROCESS_BEGIN(); + PRINTF("Sniffer started\n"); + PROCESS_EXIT(); + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ + +/** + * @} + * @} + */ diff --git a/examples/zolertia/zoul/cc1200-sniffer/stub-rdc.c b/examples/zolertia/zoul/cc1200-sniffer/stub-rdc.c new file mode 100644 index 000000000..a8c54de6a --- /dev/null +++ b/examples/zolertia/zoul/cc1200-sniffer/stub-rdc.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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 + * Definition of a fake RDC driver to be used with passive + * examples. The sniffer will never send packets and it will never + * push incoming packets up the stack. We do this by defining this + * driver as our RDC. We then drop everything + * + * \author + * George Oikonomou - + */ +#include "net/mac/mac.h" +#include "net/mac/rdc.h" +/*---------------------------------------------------------------------------*/ +static void +send(mac_callback_t sent, void *ptr) +{ + if(sent) { + sent(ptr, MAC_TX_OK, 1); + } +} +/*---------------------------------------------------------------------------*/ +static void +send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *list) +{ + if(sent) { + sent(ptr, MAC_TX_OK, 1); + } +} +/*---------------------------------------------------------------------------*/ +static void +input(void) +{ +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +off(int keep_radio_on) +{ + return keep_radio_on; +} +/*---------------------------------------------------------------------------*/ +static unsigned short +cca(void) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ +} +/*---------------------------------------------------------------------------*/ +const struct rdc_driver stub_rdc_driver = { + "stub-rdc", + init, + send, + send_list, + input, + on, + off, + cca, +}; +/*---------------------------------------------------------------------------*/ diff --git a/examples/sky/test-deluge.c b/examples/zolertia/zoul/test-relay.c similarity index 55% rename from examples/sky/test-deluge.c rename to examples/zolertia/zoul/test-relay.c index 3bb9bb5e8..cd743919d 100644 --- a/examples/sky/test-deluge.c +++ b/examples/zolertia/zoul/test-relay.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Swedish Institute of Computer Science. + * Copyright (c) 2016, Zolertia * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,87 +29,61 @@ * This file is part of the Contiki operating system. * */ - /** + * \addtogroup zoul-examples + * @{ + * + * \defgroup zoul-relay-test A simple program to test a generic relay + * + * Demonstrates the use of a generic relay, connected by default at the ADC1 + * connector of the RE-Mote + * + * @{ + * * \file - * A test program for Deluge. + * A quick program to test a generic relay * \author - * Nicolas Tsiftes + * Antonio Lignan */ - -#include "contiki.h" -#include "cfs/cfs.h" -#include "deluge.h" -#include "sys/node-id.h" - -#include -#include - -#ifndef SINK_ID -#define SINK_ID 1 -#endif - -#ifndef FILE_SIZE -#define FILE_SIZE 1000 -#endif - -PROCESS(deluge_test_process, "Deluge test process"); -AUTOSTART_PROCESSES(&deluge_test_process); /*---------------------------------------------------------------------------*/ -PROCESS_THREAD(deluge_test_process, ev, data) +#include +#include "contiki.h" +#include "dev/relay.h" +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +PROCESS(remote_relay_process, "Generic relay test"); +AUTOSTART_PROCESSES(&remote_relay_process); +/*---------------------------------------------------------------------------*/ +static struct etimer et; +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(remote_relay_process, ev, data) { - int fd, r; - char buf[32]; - static struct etimer et; - PROCESS_BEGIN(); + SENSORS_ACTIVATE(relay); - memset(buf, 0, sizeof(buf)); - if(node_id == SINK_ID) { - strcpy(buf, "This is version 1 of the file"); - } else { - strcpy(buf, "This is version 0 of the file"); - } - - cfs_remove("test"); - fd = cfs_open("test", CFS_WRITE); - if(fd < 0) { - process_exit(NULL); - } - if(cfs_write(fd, buf, sizeof(buf)) != sizeof(buf)) { - cfs_close(fd); - process_exit(NULL); - } - - if(cfs_seek(fd, FILE_SIZE, CFS_SEEK_SET) != FILE_SIZE) { - printf("failed to seek to the end\n"); - } - - deluge_disseminate("test", node_id == SINK_ID); - cfs_close(fd); - + /* Activate the relay and wait for 5 seconds */ + relay.value(RELAY_ON); etimer_set(&et, CLOCK_SECOND * 5); - for(;;) { + printf("\nRelay: switch should be ON --> %u\n", relay.status(SENSORS_ACTIVE)); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + /* Now turn off and wait 5 seconds more */ + relay.value(RELAY_OFF); + etimer_set(&et, CLOCK_SECOND * 5); + printf("Relay: switch should be OFF --> %u\n\n", relay.status(SENSORS_ACTIVE)); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + /* Let it spin and toggle each second */ + while(1) { + etimer_set(&et, CLOCK_SECOND); PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); - if(node_id != SINK_ID) { - fd = cfs_open("test", CFS_READ); - if(fd < 0) { - printf("failed to open the test file\n"); - } else { - r = cfs_read(fd, buf, sizeof(buf)); - buf[sizeof(buf) - 1] = '\0'; - if(r <= 0) { - printf("failed to read data from the file\n"); - } else { - printf("File contents: %s\n", buf); - } - cfs_close(fd); - } - } - etimer_reset(&et); + relay.value(RELAY_TOGGLE); + printf("Relay: switch is now --> %u\n", relay.status(SENSORS_ACTIVE)); } - - PROCESS_END(); } /*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/examples/zolertia/zoul/test-zonik.c b/examples/zolertia/zoul/test-zonik.c new file mode 100644 index 000000000..622b73291 --- /dev/null +++ b/examples/zolertia/zoul/test-zonik.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2016, Zolertia - http://www.zolertia.com + * + * 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 remote-examples + * @{ + * \defgroup remote-zonik-test Zolertia Zonik sonometer test application + * + * Example of Zonik board implementation and simple operation: Infinite loop + * enablinkg the sensor and rading few times, acquiring the dBA of sensor + * The first value acquired is invalid, because it's in hw init state awaiting + * a valid internal reading.Once the driver is initialized, posterior readings + * are valid.Finally in the loop disables the board with standard call and + * shows the error, and loop again enabling it. + * + * @{ + * \file + * RE-Mote test application of Zolertia Zonik sound sensor + * \author + * Aitor Mejias + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "zonik.h" +#include "dev/i2c.h" +#include "dev/leds.h" +#include +#include +/*---------------------------------------------------------------------------*/ +#define MAX_VALID_READINGS 10L +#define MAX_INVALID_READINGS 3L +/*---------------------------------------------------------------------------*/ +PROCESS(test_remote_zonik_process, "Test Zonik driver process"); +AUTOSTART_PROCESSES(&test_remote_zonik_process); +/*---------------------------------------------------------------------------*/ +static struct etimer et; +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(test_remote_zonik_process, ev, data) +{ + static int16_t zonik_val; + static uint8_t i; + + PROCESS_BEGIN(); + + printf("Initial status of sensor is: 0x%04X\n", + zonik.status(SENSORS_ACTIVE)); + + while(1) { + /* Configure Zonik and activate the internal process readings */ + SENSORS_ACTIVATE(zonik); + + printf("Initialized. Sensor status: 0x%04X\n", + zonik.status(SENSORS_ACTIVE)); + + /* Read sensor value dBA multiple times */ + for(i=0; i + Bernhard Trinnes */ #ifndef CONTIKI_CONF_H_ #define CONTIKI_CONF_H_ /* Platform name, type, and MCU clock rate */ -#define PLATFORM_NAME "RFA1" -#define PLATFORM_TYPE ATMEGA128RFA1 +#define PLATFORM_NAME "guhRF" +#define PLATFORM_TYPE ATMEGA256RFR2 #ifndef F_CPU #define F_CPU 16000000UL #endif @@ -58,20 +59,27 @@ */ /* Clock ticks per second */ #define CLOCK_CONF_SECOND 128 - -typedef uint32_t clock_time_t; -#define CLOCK_LT(a,b) ((int32_t)((a)-(b)) < 0) - +#if 1 +/* 16 bit counter overflows every ~10 minutes */ +typedef unsigned short clock_time_t; +#define CLOCK_LT(a,b) ((signed short)((a)-(b)) < 0) +#define INFINITE_TIME 0xffff +#define RIME_CONF_BROADCAST_ANNOUNCEMENT_MAX_TIME INFINITE_TIME/CLOCK_CONF_SECOND /* Default uses 600 */ +#define COLLECT_CONF_BROADCAST_ANNOUNCEMENT_MAX_TIME INFINITE_TIME/CLOCK_CONF_SECOND /* Default uses 600 */ +#else +typedef unsigned long clock_time_t; +#define CLOCK_LT(a,b) ((signed long)((a)-(b)) < 0) +#define INFINITE_TIME 0xffffffff +#endif /* These routines are not part of the contiki core but can be enabled in cpu/avr/clock.c */ void clock_delay_msec(uint16_t howlong); void clock_adjust_ticks(clock_time_t howmany); -/* Michael Hartman's atmega128rfa1 board has an external 32768Hz crystal connected to TOSC1 and 2 pins similar to the Raven 1284p */ + /* and theoretically can use TIMER2 with it to keep time. Else TIMER0 is used. */ /* The sleep timer requires the crystal and adds a TIMER2 interrupt routine if not already define by clock.c */ #define AVR_CONF_USE32KCRYSTAL 0 -/* Michael Hartman's protobyte board has LED on PORTE1, used for radio on indication */ /* However this results in disabling UART0. */ #define RF230BB_CONF_LEDONPORTE1 0 @@ -121,10 +129,12 @@ typedef unsigned short uip_stats_t; * On the RF230 a reduced rx power threshold will not prevent autoack if enabled and requested. * These numbers applied to both Raven and Jackdaw give a maximum communication distance of about 15 cm * and a 10 meter range to a full-sensitivity RF230 sniffer. + #define RF230_MAX_TX_POWER 15 #define RF230_MIN_RX_POWER 30 + */ - /* The rf231 and atmega128rfa1 can use an rssi threshold for triggering rx_busy that saves 0.5ma in rx mode */ + /* The rf231 and ATMEGA256RFR2 can use an rssi threshold for triggering rx_busy that saves 0.5ma in rx mode */ /* 1 - 15 maps into -90 to -48 dBm; the register is written with RF230_MIN_RX_POWER/6 + 1. Undefine for -100dBm sensitivity */ //#define RF230_MIN_RX_POWER 0 @@ -134,7 +144,10 @@ typedef unsigned short uip_stats_t; /* TX routine does automatic cca and optional backoffs */ #define RDC_CONF_HARDWARE_CSMA 1 /* Allow MCU sleeping between channel checks */ -#define RDC_CONF_MCU_SLEEP 1 +#define RDC_CONF_MCU_SLEEP 1 + +/* External Amplifier installed */ +#define _EXT_PA_ 1 #if NETSTACK_CONF_WITH_IPV6 #define LINKADDR_CONF_SIZE 8 @@ -234,7 +247,7 @@ typedef unsigned short uip_stats_t; /* So without the header this needed for RPL mesh to form */ #define CONTIKIMAC_FRAMER_CONF_SHORTEST_PACKET_SIZE 43-18 //multicast RPL DIS length /* Not tested much yet */ -#define CONTIKIMAC_CONF_WITH_PHASE_OPTIMIZATION 0 +#define CONTIKIMAC_CONF_WITH_PHASE_OPTIMIZATION 0 #define CONTIKIMAC_CONF_COMPOWER 1 #define RIMESTATS_CONF_ENABLED 0 @@ -271,46 +284,6 @@ typedef unsigned short uip_stats_t; #define UIP_CONF_DS6_MADDR_NBU 0 #define UIP_CONF_DS6_AADDR_NBU 0 - -#elif 1 /* cx-mac radio cycling */ -/* RF230 does clear-channel assessment in extended mode (autoretries>0) */ -/* These values are guesses */ -#define RF230_CONF_FRAME_RETRIES 10 -#define RF230_CONF_CSMA_RETRIES 2 -#if RF230_CONF_CSMA_RETRIES -#define NETSTACK_CONF_MAC nullmac_driver -#else -#define NETSTACK_CONF_MAC csma_driver -#endif -#define NETSTACK_CONF_RDC cxmac_driver -#define NETSTACK_CONF_FRAMER framer_802154 -#define NETSTACK_CONF_RADIO rf230_driver -#define CHANNEL_802_15_4 26 -#define RF230_CONF_AUTOACK 1 -#define SICSLOWPAN_CONF_FRAG 1 -#define SICSLOWPAN_CONF_MAXAGE 3 -#define CXMAC_CONF_ANNOUNCEMENTS 0 -#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8 -/* 211 bytes per queue buffer. Burst mode will need 15 for a 1280 byte MTU */ -#define QUEUEBUF_CONF_NUM 15 -/* 54 bytes per queue ref buffer */ -#define QUEUEBUF_CONF_REF_NUM 2 -/* Allocate remaining RAM. Not much left due to queuebuf increase */ -#define UIP_CONF_MAX_CONNECTIONS 2 -#define UIP_CONF_MAX_LISTENPORTS 4 -#define UIP_CONF_UDP_CONNS 5 -#define NBR_TABLE_CONF_MAX_NEIGHBORS 4 -#define UIP_CONF_DS6_DEFRT_NBU 2 -#define UIP_CONF_DS6_PREFIX_NBU 3 -#define UIP_CONF_MAX_ROUTES 4 -#define UIP_CONF_DS6_ADDR_NBU 3 -#define UIP_CONF_DS6_MADDR_NBU 0 -#define UIP_CONF_DS6_AADDR_NBU 0 -//Below gives 10% duty cycle, undef for default 5% -//#define CXMAC_CONF_ON_TIME (RTIMER_ARCH_SECOND / 80) -//Below gives 50% duty cycle -//#define CXMAC_CONF_ON_TIME (RTIMER_ARCH_SECOND / 16) - #else #error Network configuration not specified! #endif /* Network setup */ diff --git a/platform/osd-merkur/contiki-main.c b/platform/RaspBee/contiki-main.c similarity index 98% rename from platform/osd-merkur/contiki-main.c rename to platform/RaspBee/contiki-main.c index 4be90c6e5..6c1f5c7e7 100644 --- a/platform/osd-merkur/contiki-main.c +++ b/platform/RaspBee/contiki-main.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -129,15 +130,15 @@ void rtimercycle(void) {rtimerflag=1;} typedef struct {const unsigned char B2;const unsigned char B1;const unsigned char B0;} __signature_t; #define SIGNATURE __signature_t __signature __attribute__((section (".signature"))) SIGNATURE = { - .B2 = 0x01,//SIGNATURE_2, //ATMEGA128rfa1 - .B1 = 0xA7,//SIGNATURE_1, //128KB flash + .B2 = 0x02,//SIGNATURE_2, //ATMEGA256rfr2 + .B1 = 0xA8,//SIGNATURE_1, //256KB flash .B0 = 0x1E,//SIGNATURE_0, //Atmel }; #endif #if 1 -/* JTAG+SPI enabled, External osc 1kck4ms1 , Boot 4096 words @ $1F000, TXC1K+4,1msec delay, Brownout 1.9 volts */ -FUSES ={.low = 0xF6, .high = 0x98, .extended = 0xfd,}; +/* JTAG+SPI enabled, External osc 1kck4ms1 , Boot 4096 words @ $1F000, TXC1K+4,1msec delay, Brownout 1.8 volts */ +FUSES ={.low = 0xF6, .high = 0x98, .extended = 0xfe,}; #define BOOTLOADER_START = 0x1F000 #else /* JTAG+SPI, Boot 4096 words @ $F000, Internal oscillator, startup 6 CK +0 ms, Brownout 1.8 volts */ @@ -145,10 +146,8 @@ FUSES ={.low = 0xC2, .high = 0x99, .extended = 0xfe,}; #endif #include "lib/sensors.h" -#include "dev/button-sensor.h" #include "dev/battery-sensor.h" -#include "dev/pir-sensor.h" -SENSORS(&button_sensor, &pir_sensor); + uint8_t rng_get_uint8(void) { diff --git a/platform/RaspBee/dev/Arduino.h b/platform/RaspBee/dev/Arduino.h new file mode 100644 index 000000000..e0ea47b10 --- /dev/null +++ b/platform/RaspBee/dev/Arduino.h @@ -0,0 +1,172 @@ +#ifndef Arduino_h +#define Arduino_h + +#include +#include +#include +#include + +#include +#include +#include + +#include "binary.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +#define HIGH 0x1 +#define LOW 0x0 + +#define INPUT 0x0 +#define OUTPUT 0x1 +#define INPUT_PULLUP 0x2 + +#define true 0x1 +#define false 0x0 + +#define PI 3.1415926535897932384626433832795 +#define HALF_PI 1.5707963267948966192313216916398 +#define TWO_PI 6.283185307179586476925286766559 +#define DEG_TO_RAD 0.017453292519943295769236907684886 +#define RAD_TO_DEG 57.295779513082320876798154814105 + +#define SERIAL 0x0 +#define DISPLAY 0x1 + +#define LSBFIRST 0 +#define MSBFIRST 1 + +#define CHANGE 1 +#define FALLING 2 +#define RISING 3 + +#define DEFAULT ADC_DEFAULT +#define EXTERNAL ADC_EXTERNAL + +// undefine stdlib's abs if encountered +#ifdef abs +#undef abs +#endif + +#define min(a,b) ((a)<(b)?(a):(b)) +#define max(a,b) ((a)>(b)?(a):(b)) +#define abs(x) ((x)>0?(x):-(x)) +#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) +#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) +#define radians(deg) ((deg)*DEG_TO_RAD) +#define degrees(rad) ((rad)*RAD_TO_DEG) +#define sq(x) ((x)*(x)) + +#define interrupts() sei() +#define noInterrupts() cli() + +#define lowByte(w) ((uint8_t) ((w) & 0xff)) +#define highByte(w) ((uint8_t) ((w) >> 8)) + +#define bitRead(value, bit) (((value) >> (bit)) & 0x01) +#define bitSet(value, bit) ((value) |= (1UL << (bit))) +#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) +#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) + + +typedef unsigned int word; + +#define bit(b) (1UL << (b)) + +typedef uint8_t boolean; +typedef uint8_t byte; + +void pinMode(uint8_t, uint8_t); +void digitalWrite(uint8_t, uint8_t); +int digitalRead(uint8_t); + +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout); + +void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); +uint8_t shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder); + +void attachInterrupt(uint8_t, void (*)(void), int mode); +void detachInterrupt(uint8_t); + +void setup(void); +void loop(void); + +// Get the bit location within the hardware port of the given virtual pin. +// This comes from the pins_*.c file for the active board configuration. + +#define analogInPinToBit(P) (P) + +// On the ATmega1280, the addresses of some of the port registers are +// greater than 255, so we can't store them in uint8_t's. +extern const uint16_t PROGMEM port_to_mode_PGM[]; +extern const uint16_t PROGMEM port_to_input_PGM[]; +extern const uint16_t PROGMEM port_to_output_PGM[]; + +extern const uint8_t PROGMEM digital_pin_to_port_PGM[]; +// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; +extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[]; + +// Get the bit location within the hardware port of the given virtual pin. +// This comes from the pins_*.c file for the active board configuration. +// +// These perform slightly better as macros compared to inline functions +// +#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) ) +#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) ) +#define analogInPinToBit(P) (P) +#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) ) +#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) ) +#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) ) + +#define NOT_A_PIN 0 +#define NOT_A_PORT 0 + +#ifdef ARDUINO_MAIN +#define PA 1 +#define PB 2 +#define PC 3 +#define PD 4 +#define PE 5 +#define PF 6 +#define PG 7 +#define PH 8 +#define PJ 10 +#define PK 11 +#define PL 12 +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#ifdef __cplusplus +// look at this again when considering implementing serial +//#include "WCharacter.h" +//#include "WString.h" +//#include "HardwareSerial.h" + +uint16_t makeWord(uint16_t w); +uint16_t makeWord(byte h, byte l); + +#define word(...) makeWord(__VA_ARGS__) + +unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout = 1000000L); + +void tone(uint8_t _pin, unsigned int frequency, unsigned long duration = 0); +void noTone(uint8_t _pin); + +// WMath prototypes +long random(long); +long random(long, long); +void randomSeed(unsigned int); +long map(long, long, long, long, long); + +#endif + +#include "pins_arduino.h" + +#include "dev/arduino/arduino-compat.h" + +#endif diff --git a/platform/RaspBee/dev/adc.c b/platform/RaspBee/dev/adc.c new file mode 100644 index 000000000..7efde72e1 --- /dev/null +++ b/platform/RaspBee/dev/adc.c @@ -0,0 +1,84 @@ +/* +* Copyright (c) 2012, BinaryLabs. +* 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. +* +* @(#)$Id: adc.c,v 1.1 2010/08/25 19:34:06 nifi Exp $ +*/ + +/** +* \file +* ADC file for Atmega128rfa1. +* \author +* Paulo Louro +*/ + +#include "adc.h" + +static uint8_t analog_reference = ADC_DEFAULT; + +/* + * For arduino interface for setting external reference voltage + * Note that applying an external voltage *and* then setting the analog + * reference to something internal will short the internal and the + * external reference voltage and most likely destroy the processor. + */ +void analogReference(uint8_t mode) +{ + analog_reference = mode; +} + +int readADC(uint8_t pin) +{ + int result = 0; + + adc_setup (analog_reference, pin); + result = adc_read (); + adc_fin (); + return result; +} + +/** +* \return Internal temperature in 0.01C, e.g. 25C is 2500 +*/ +int readInternalTemp(void) +{ + int reading = 0; + + ADCSRB |= _BV(MUX5); + ADMUX = _BV(REFS1) | _BV(REFS0) | 0b1001 ; + ADCSRA = _BV(ADEN) | _BV(ADPS0) | _BV(ADPS2) ; + + ADCSRA |= 1 << ADSC; + loop_until_bit_is_clear(ADCSRA,ADSC); + reading = ADC; + + ADCSRB=0; //disable ADC, need to write B first for MUX5 bit + ADCSRA=0; //disable ADC + ADMUX=0; //turn off internal vref + + return reading * 113 - 27280; +} diff --git a/platform/RaspBee/dev/adc.h b/platform/RaspBee/dev/adc.h new file mode 100644 index 000000000..e3ff516b1 --- /dev/null +++ b/platform/RaspBee/dev/adc.h @@ -0,0 +1,65 @@ +#ifndef __ADC_ARCH_H__ +#define __ADC_ARCH_H__ + +#include + +/* + * Reference voltage + * The default is 1.6V reference voltage + * The selected reference voltage is the maximum voltage that can be + * measured. + * Directly provide shifted variants so we don't need to shift. + */ +#define ADC_1_5 (2<<6) +#define ADC_1_6 (3<<6) +#define ADC_1_8 (1<<6) +#define ADC_EXTERNAL (0<<6) +#define ADC_DEFAULT ADC_1_6 + +/* sometimes it's desirable to decouple setup / finish from sampling */ + +static inline void adc_setup (uint8_t ref_volt, uint8_t pin) +{ + ADMUX = ref_volt | (pin & 0x7); + ADCSRA = _BV(ADEN) | _BV(ADPS0) | _BV(ADPS2); +} + +static inline int adc_read (void) +{ + ADCSRA |= (1 << ADSC); + loop_until_bit_is_clear (ADCSRA, ADSC); + return ADC; +} + +static inline void adc_fin (void) +{ + ADCSRA = 0; + ADMUX = 0; +} + +static inline void adc_init (void) +{ + uint8_t temp; + ADCSRC = 0; + ADCSRB = 0; + adc_fin (); + /* + * Disable JTAG interface + * Hardware manual about JTD bit: + * "In order to avoid unintentional disabling or enabling of the + * JTAG interface, a timed sequence must be followed when changing + * this bit: The application software must write this bit to the + * desired value twice within four cycles to change its value." + * 15.4.1 "MCUCR - MCU Control Register", p. 219 + */ + temp = MCUCR | (1 << JTD); + MCUCR = temp; + MCUCR = temp; +} + +int readADC(uint8_t pin); +long readVcc(); +int readInternalTemp(void); +void analogReference(uint8_t mode); + +#endif /* __ADC_ARCH_H__ */ diff --git a/platform/RaspBee/dev/batmon.c b/platform/RaspBee/dev/batmon.c new file mode 100644 index 000000000..5c61d125f --- /dev/null +++ b/platform/RaspBee/dev/batmon.c @@ -0,0 +1,55 @@ +#include "contiki.h" +#include "batmon.h" +#include + + + + +int8_t batmon_init() +{ + return 0; +} + +int8_t batmon_get_voltage(uint16_t* voltage) +{ + uint16_t volt = 0; + uint16_t resolution = 75; + uint16_t offset = 2550; + int8_t ctr = 0; + + BATMON = 0 | _BV(BATMON_HR); + _delay_us(2); + + if(BATMON & _BV(BATMON_OK)) + { + // voltage above 2.550 V + resolution = 75; + offset = 2550; + for(ctr=15; ctr>=0; ctr--) + { + BATMON = (BATMON & 0xF0) | (ctr); + _delay_us(2); + if(BATMON & _BV(BATMON_OK)) break; + } + } + else + { + // voltage below 2.550 V + resolution = 50; + offset = 1700; + + BATMON &= ~_BV(BATMON_HR); + + for(ctr=15; ctr>=0; ctr--) + { + BATMON = (BATMON & 0xF0) | (ctr); + _delay_us(2); + if(BATMON & _BV(BATMON_OK)) break; + } + } + + volt = resolution*ctr+offset; + *voltage=volt; + + return 0; +} diff --git a/platform/RaspBee/dev/batmon.h b/platform/RaspBee/dev/batmon.h new file mode 100644 index 000000000..c05f48200 --- /dev/null +++ b/platform/RaspBee/dev/batmon.h @@ -0,0 +1,8 @@ +#ifndef BATMON_H_ +#define BATMON_H_ + +int8_t batmon_init(); +int8_t batmon_get_voltage(uint16_t* voltage); + + +#endif /* BATMON_H_ */ diff --git a/platform/RaspBee/dev/battery-sensor.c b/platform/RaspBee/dev/battery-sensor.c new file mode 100644 index 000000000..1eb7906b4 --- /dev/null +++ b/platform/RaspBee/dev/battery-sensor.c @@ -0,0 +1,90 @@ +/* +* Copyright (c) 2012, BinaryLabs. +* 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. +* +* @(#)$Id: battery-sensor.h,v 1.1 2012/08/25 19:34:06 nifi Exp $ +*/ + +/** +* \file +* Battery sensor file for Atmega128rfa1. +* \author +* Paulo Louro +* Harald Pichler +*/ + +/** +*The atmel rf23x radios have a low voltage detector that can be configured in units of 75 millivolts. Here is example *code for the ATmega128rfa1, where the BATMON register is in extended io space [dak664] +*/ + +#include "dev/battery-sensor.h" +#include "dev/batmon.h" + +const struct sensors_sensor battery_sensor; +/*---------------------------------------------------------------------------*/ + +/** +* \return Voltage on battery measurement with BATMON register. +*/ +static int +value(int type) +{ + + uint16_t h; +/* + uint8_t p1; + BATMON = 16; //give BATMON time to stabilize at highest range and lowest voltage + +// Bandgap can't be measured against supply voltage in this chip. +// Use BATMON register instead + for ( p1=16; p1<31; p1++) { + BATMON = p1; + clock_delay_usec(100); // delay needed !! + if ((BATMON&(1< +*/ + +#ifndef __BATTERY_SENSOR_H__ +#define __BATTERY_SENSOR_H__ + +#include "lib/sensors.h" + +extern const struct sensors_sensor battery_sensor; + +#define BATTERY_SENSOR "Battery" + +#endif /* __BATTERY_SENSOR_H__ */ \ No newline at end of file diff --git a/platform/RaspBee/dev/binary.h b/platform/RaspBee/dev/binary.h new file mode 100644 index 000000000..af1498033 --- /dev/null +++ b/platform/RaspBee/dev/binary.h @@ -0,0 +1,515 @@ +#ifndef Binary_h +#define Binary_h + +#define B0 0 +#define B00 0 +#define B000 0 +#define B0000 0 +#define B00000 0 +#define B000000 0 +#define B0000000 0 +#define B00000000 0 +#define B1 1 +#define B01 1 +#define B001 1 +#define B0001 1 +#define B00001 1 +#define B000001 1 +#define B0000001 1 +#define B00000001 1 +#define B10 2 +#define B010 2 +#define B0010 2 +#define B00010 2 +#define B000010 2 +#define B0000010 2 +#define B00000010 2 +#define B11 3 +#define B011 3 +#define B0011 3 +#define B00011 3 +#define B000011 3 +#define B0000011 3 +#define B00000011 3 +#define B100 4 +#define B0100 4 +#define B00100 4 +#define B000100 4 +#define B0000100 4 +#define B00000100 4 +#define B101 5 +#define B0101 5 +#define B00101 5 +#define B000101 5 +#define B0000101 5 +#define B00000101 5 +#define B110 6 +#define B0110 6 +#define B00110 6 +#define B000110 6 +#define B0000110 6 +#define B00000110 6 +#define B111 7 +#define B0111 7 +#define B00111 7 +#define B000111 7 +#define B0000111 7 +#define B00000111 7 +#define B1000 8 +#define B01000 8 +#define B001000 8 +#define B0001000 8 +#define B00001000 8 +#define B1001 9 +#define B01001 9 +#define B001001 9 +#define B0001001 9 +#define B00001001 9 +#define B1010 10 +#define B01010 10 +#define B001010 10 +#define B0001010 10 +#define B00001010 10 +#define B1011 11 +#define B01011 11 +#define B001011 11 +#define B0001011 11 +#define B00001011 11 +#define B1100 12 +#define B01100 12 +#define B001100 12 +#define B0001100 12 +#define B00001100 12 +#define B1101 13 +#define B01101 13 +#define B001101 13 +#define B0001101 13 +#define B00001101 13 +#define B1110 14 +#define B01110 14 +#define B001110 14 +#define B0001110 14 +#define B00001110 14 +#define B1111 15 +#define B01111 15 +#define B001111 15 +#define B0001111 15 +#define B00001111 15 +#define B10000 16 +#define B010000 16 +#define B0010000 16 +#define B00010000 16 +#define B10001 17 +#define B010001 17 +#define B0010001 17 +#define B00010001 17 +#define B10010 18 +#define B010010 18 +#define B0010010 18 +#define B00010010 18 +#define B10011 19 +#define B010011 19 +#define B0010011 19 +#define B00010011 19 +#define B10100 20 +#define B010100 20 +#define B0010100 20 +#define B00010100 20 +#define B10101 21 +#define B010101 21 +#define B0010101 21 +#define B00010101 21 +#define B10110 22 +#define B010110 22 +#define B0010110 22 +#define B00010110 22 +#define B10111 23 +#define B010111 23 +#define B0010111 23 +#define B00010111 23 +#define B11000 24 +#define B011000 24 +#define B0011000 24 +#define B00011000 24 +#define B11001 25 +#define B011001 25 +#define B0011001 25 +#define B00011001 25 +#define B11010 26 +#define B011010 26 +#define B0011010 26 +#define B00011010 26 +#define B11011 27 +#define B011011 27 +#define B0011011 27 +#define B00011011 27 +#define B11100 28 +#define B011100 28 +#define B0011100 28 +#define B00011100 28 +#define B11101 29 +#define B011101 29 +#define B0011101 29 +#define B00011101 29 +#define B11110 30 +#define B011110 30 +#define B0011110 30 +#define B00011110 30 +#define B11111 31 +#define B011111 31 +#define B0011111 31 +#define B00011111 31 +#define B100000 32 +#define B0100000 32 +#define B00100000 32 +#define B100001 33 +#define B0100001 33 +#define B00100001 33 +#define B100010 34 +#define B0100010 34 +#define B00100010 34 +#define B100011 35 +#define B0100011 35 +#define B00100011 35 +#define B100100 36 +#define B0100100 36 +#define B00100100 36 +#define B100101 37 +#define B0100101 37 +#define B00100101 37 +#define B100110 38 +#define B0100110 38 +#define B00100110 38 +#define B100111 39 +#define B0100111 39 +#define B00100111 39 +#define B101000 40 +#define B0101000 40 +#define B00101000 40 +#define B101001 41 +#define B0101001 41 +#define B00101001 41 +#define B101010 42 +#define B0101010 42 +#define B00101010 42 +#define B101011 43 +#define B0101011 43 +#define B00101011 43 +#define B101100 44 +#define B0101100 44 +#define B00101100 44 +#define B101101 45 +#define B0101101 45 +#define B00101101 45 +#define B101110 46 +#define B0101110 46 +#define B00101110 46 +#define B101111 47 +#define B0101111 47 +#define B00101111 47 +#define B110000 48 +#define B0110000 48 +#define B00110000 48 +#define B110001 49 +#define B0110001 49 +#define B00110001 49 +#define B110010 50 +#define B0110010 50 +#define B00110010 50 +#define B110011 51 +#define B0110011 51 +#define B00110011 51 +#define B110100 52 +#define B0110100 52 +#define B00110100 52 +#define B110101 53 +#define B0110101 53 +#define B00110101 53 +#define B110110 54 +#define B0110110 54 +#define B00110110 54 +#define B110111 55 +#define B0110111 55 +#define B00110111 55 +#define B111000 56 +#define B0111000 56 +#define B00111000 56 +#define B111001 57 +#define B0111001 57 +#define B00111001 57 +#define B111010 58 +#define B0111010 58 +#define B00111010 58 +#define B111011 59 +#define B0111011 59 +#define B00111011 59 +#define B111100 60 +#define B0111100 60 +#define B00111100 60 +#define B111101 61 +#define B0111101 61 +#define B00111101 61 +#define B111110 62 +#define B0111110 62 +#define B00111110 62 +#define B111111 63 +#define B0111111 63 +#define B00111111 63 +#define B1000000 64 +#define B01000000 64 +#define B1000001 65 +#define B01000001 65 +#define B1000010 66 +#define B01000010 66 +#define B1000011 67 +#define B01000011 67 +#define B1000100 68 +#define B01000100 68 +#define B1000101 69 +#define B01000101 69 +#define B1000110 70 +#define B01000110 70 +#define B1000111 71 +#define B01000111 71 +#define B1001000 72 +#define B01001000 72 +#define B1001001 73 +#define B01001001 73 +#define B1001010 74 +#define B01001010 74 +#define B1001011 75 +#define B01001011 75 +#define B1001100 76 +#define B01001100 76 +#define B1001101 77 +#define B01001101 77 +#define B1001110 78 +#define B01001110 78 +#define B1001111 79 +#define B01001111 79 +#define B1010000 80 +#define B01010000 80 +#define B1010001 81 +#define B01010001 81 +#define B1010010 82 +#define B01010010 82 +#define B1010011 83 +#define B01010011 83 +#define B1010100 84 +#define B01010100 84 +#define B1010101 85 +#define B01010101 85 +#define B1010110 86 +#define B01010110 86 +#define B1010111 87 +#define B01010111 87 +#define B1011000 88 +#define B01011000 88 +#define B1011001 89 +#define B01011001 89 +#define B1011010 90 +#define B01011010 90 +#define B1011011 91 +#define B01011011 91 +#define B1011100 92 +#define B01011100 92 +#define B1011101 93 +#define B01011101 93 +#define B1011110 94 +#define B01011110 94 +#define B1011111 95 +#define B01011111 95 +#define B1100000 96 +#define B01100000 96 +#define B1100001 97 +#define B01100001 97 +#define B1100010 98 +#define B01100010 98 +#define B1100011 99 +#define B01100011 99 +#define B1100100 100 +#define B01100100 100 +#define B1100101 101 +#define B01100101 101 +#define B1100110 102 +#define B01100110 102 +#define B1100111 103 +#define B01100111 103 +#define B1101000 104 +#define B01101000 104 +#define B1101001 105 +#define B01101001 105 +#define B1101010 106 +#define B01101010 106 +#define B1101011 107 +#define B01101011 107 +#define B1101100 108 +#define B01101100 108 +#define B1101101 109 +#define B01101101 109 +#define B1101110 110 +#define B01101110 110 +#define B1101111 111 +#define B01101111 111 +#define B1110000 112 +#define B01110000 112 +#define B1110001 113 +#define B01110001 113 +#define B1110010 114 +#define B01110010 114 +#define B1110011 115 +#define B01110011 115 +#define B1110100 116 +#define B01110100 116 +#define B1110101 117 +#define B01110101 117 +#define B1110110 118 +#define B01110110 118 +#define B1110111 119 +#define B01110111 119 +#define B1111000 120 +#define B01111000 120 +#define B1111001 121 +#define B01111001 121 +#define B1111010 122 +#define B01111010 122 +#define B1111011 123 +#define B01111011 123 +#define B1111100 124 +#define B01111100 124 +#define B1111101 125 +#define B01111101 125 +#define B1111110 126 +#define B01111110 126 +#define B1111111 127 +#define B01111111 127 +#define B10000000 128 +#define B10000001 129 +#define B10000010 130 +#define B10000011 131 +#define B10000100 132 +#define B10000101 133 +#define B10000110 134 +#define B10000111 135 +#define B10001000 136 +#define B10001001 137 +#define B10001010 138 +#define B10001011 139 +#define B10001100 140 +#define B10001101 141 +#define B10001110 142 +#define B10001111 143 +#define B10010000 144 +#define B10010001 145 +#define B10010010 146 +#define B10010011 147 +#define B10010100 148 +#define B10010101 149 +#define B10010110 150 +#define B10010111 151 +#define B10011000 152 +#define B10011001 153 +#define B10011010 154 +#define B10011011 155 +#define B10011100 156 +#define B10011101 157 +#define B10011110 158 +#define B10011111 159 +#define B10100000 160 +#define B10100001 161 +#define B10100010 162 +#define B10100011 163 +#define B10100100 164 +#define B10100101 165 +#define B10100110 166 +#define B10100111 167 +#define B10101000 168 +#define B10101001 169 +#define B10101010 170 +#define B10101011 171 +#define B10101100 172 +#define B10101101 173 +#define B10101110 174 +#define B10101111 175 +#define B10110000 176 +#define B10110001 177 +#define B10110010 178 +#define B10110011 179 +#define B10110100 180 +#define B10110101 181 +#define B10110110 182 +#define B10110111 183 +#define B10111000 184 +#define B10111001 185 +#define B10111010 186 +#define B10111011 187 +#define B10111100 188 +#define B10111101 189 +#define B10111110 190 +#define B10111111 191 +#define B11000000 192 +#define B11000001 193 +#define B11000010 194 +#define B11000011 195 +#define B11000100 196 +#define B11000101 197 +#define B11000110 198 +#define B11000111 199 +#define B11001000 200 +#define B11001001 201 +#define B11001010 202 +#define B11001011 203 +#define B11001100 204 +#define B11001101 205 +#define B11001110 206 +#define B11001111 207 +#define B11010000 208 +#define B11010001 209 +#define B11010010 210 +#define B11010011 211 +#define B11010100 212 +#define B11010101 213 +#define B11010110 214 +#define B11010111 215 +#define B11011000 216 +#define B11011001 217 +#define B11011010 218 +#define B11011011 219 +#define B11011100 220 +#define B11011101 221 +#define B11011110 222 +#define B11011111 223 +#define B11100000 224 +#define B11100001 225 +#define B11100010 226 +#define B11100011 227 +#define B11100100 228 +#define B11100101 229 +#define B11100110 230 +#define B11100111 231 +#define B11101000 232 +#define B11101001 233 +#define B11101010 234 +#define B11101011 235 +#define B11101100 236 +#define B11101101 237 +#define B11101110 238 +#define B11101111 239 +#define B11110000 240 +#define B11110001 241 +#define B11110010 242 +#define B11110011 243 +#define B11110100 244 +#define B11110101 245 +#define B11110110 246 +#define B11110111 247 +#define B11111000 248 +#define B11111001 249 +#define B11111010 250 +#define B11111011 251 +#define B11111100 252 +#define B11111101 253 +#define B11111110 254 +#define B11111111 255 + +#endif diff --git a/platform/RaspBee/dev/button-sensor.c b/platform/RaspBee/dev/button-sensor.c new file mode 100644 index 000000000..b402a3658 --- /dev/null +++ b/platform/RaspBee/dev/button-sensor.c @@ -0,0 +1,87 @@ +/* Sensor routine */ + +#include "lib/sensors.h" +#include "dev/button-sensor.h" + +#include +#include +#include "led.h" // debug + +const struct sensors_sensor button_sensor; + +static struct timer debouncetimer; +static int status(int type); +static int enabled = 0; +struct sensors_sensor *sensors[1]; +unsigned char sensors_flags[1]; + +#define BUTTON_BIT INTF4 +#define BUTTON_CHECK_IRQ() (EIFR & BUTTON_BIT) ? 0 : 1 + +#define PRINTF(...) printf(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +ISR(INT4_vect) +{ + +// leds_toggle(LEDS_RED); + + if(BUTTON_CHECK_IRQ()) { + if(timer_expired(&debouncetimer)) { + led1_on(); + timer_set(&debouncetimer, CLOCK_SECOND / 4); + sensors_changed(&button_sensor); + led1_off(); + } + } + +} +/*---------------------------------------------------------------------------*/ + +static int +value(int type) +{ + return (PINE & _BV(PE4) ? 0 : 1) || !timer_expired(&debouncetimer); + + //return 0; +} + +static int +configure(int type, int c) +{ + switch (type) { + case SENSORS_ACTIVE: + if (c) { + if(!status(SENSORS_ACTIVE)) { + led1_on(); + timer_set(&debouncetimer, 0); + DDRE |= (0< +#include "contiki.h" +#include "dht11.h" +#include "led.h" // debug + +#define udelay(u) clock_delay_usec(u) +#define mdelay(u) clock_delay_msec(u) + +// todo: set DHT22 or DHT11 in project file +// define for DHT11 else for DHT22, RHT03 +// #define DHT11 1 + +uint8_t DHT_Read_Data(uint16_t *temperature, uint16_t *humidity){ + + //data[5] is 8byte table where data come from DHT are stored + //laststate holds laststate value + //counter is used to count microSeconds + uint8_t data[5], laststate = 0, counter = 0, j = 0, i = 0; + + //Clear array + data[0] = data[1] = data[2] = data[3] = data[4] = 0; + + uint8_t volatile sreg; + sreg = SREG; /* Save status register before disabling interrupts. */ + cli(); /* Disable interrupts. */ + + //Set pin Output + //Pin High + DHT_DRIVE(); + mdelay(100); //Wait for 100mS + + //Send Request Signal + //Pin Low + OUTP_0(); //20ms Low + mdelay(20); + //Pin High + OUTP_1(); + udelay(40); //40us High + + //Set pin Input to read Bus + //Set pin Input + DHT_RELEASE(); + laststate=DHT_INP(); //Read Pin value + + //Repeat for each Transistions + for (i=0; i254) break; + } + + if (counter>254) break; + + //laststate==_BV(DHT_PIN) checks if laststate was High + //ignore the first 2 transitions which are the DHT Response + //if (laststate==_BV(DHT_PIN) && (i > 2)) { + if ((i&0x01) && (i > 2)) { + //Save bits in segments of bytes + //Shift data[] value 1 position left + //Example. 01010100 if we shift it left one time it will be + //10101000 + + data[j/8]<<=1; + if (counter >= 15) { //If it was high for more than 40uS + //led1_on(); + data[j/8]|=1; //it means it is bit '1' so make a logic + //led1_off(); + } //OR with the value (save it) + j++; //making an OR by 1 to this value 10101000 + } //we will have the resault 10101001 + //1 in 8-bit binary is 00000001 + //j/8 changes table record every 8 bits which means a byte has been saved + //so change to next record. 0/8=0 1/8=0 ... 7/8=0 8/8=1 ... 15/8=1 16/8=2 + laststate=DHT_INP(); //save current state + counter=0; //reset counter + + } + SREG = sreg; /* Enable interrupts. */ + //printf("HUM %d %d %d %d %d %d",data[0],data[1],data[2],data[3],data[4],(uint8_t)(data[0] + data[1] + data[2] + data[3]) ); + //Check if data received are correct by checking the CheckSum + if ((uint8_t)(data[0] + data[1] + data[2] + data[3]) == data[4]) { +#ifdef DHT11 + *humidity = data[0]*100; + *temperature = data[2]*100; +#else + *humidity = ((uint16_t)data[0]<<8 | data[1])*10; + *temperature = ((uint16_t)data[2]<<8 | data[3])*10; +#endif + return 0; + }else{ + *humidity = 2; + *temperature = 2; +// uart_puts("\r\nCheck Sum Error"); + } + + return 0xff; // Check Sum Error +} diff --git a/platform/RaspBee/dev/dht11.h b/platform/RaspBee/dev/dht11.h new file mode 100644 index 000000000..6cf757e5d --- /dev/null +++ b/platform/RaspBee/dev/dht11.h @@ -0,0 +1,67 @@ +/* + DHT-11 Library + (c) Created by Charalampos Andrianakis on 18/12/11. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + +#include +#include +#include + +/* DHT 1-wire is at PortE.6 */ +#define DHT_PIN_READ PINE +#define DHT_PIN_MASK _BV(PE6) +#define DHT_PxOUT PORTE +#define DHT_PxDIR DDRE + +#define SET_PIN_INPUT() (DHT_PxDIR &= ~DHT_PIN_MASK) +#define SET_PIN_OUTPUT() (DHT_PxDIR |= DHT_PIN_MASK) + +#define OUTP_0() (DHT_PxOUT &= ~DHT_PIN_MASK) +#define OUTP_1() (DHT_PxOUT |= DHT_PIN_MASK) + +#define PIN_INIT() do{ \ + SET_PIN_INPUT(); \ + OUTP_0(); \ + } while(0) + + +/* Drive the one wire interface hight */ +#define DHT_DRIVE() do { \ + SET_PIN_OUTPUT(); \ + OUTP_1(); \ + } while (0) + +/* Release the one wire by turning on the internal pull-up. */ +#define DHT_RELEASE() do { \ + SET_PIN_INPUT(); \ + OUTP_1(); \ + } while (0) + +/* Read one bit. */ +#define DHT_INP() (DHT_PIN_READ & DHT_PIN_MASK) + +//The packet size is 40bit but each bit consists of low and high state +//so 40 x 2 = 80 transitions. Also we have 2 transistions DHT response +//and 2 transitions which indicates End Of Frame. In total 84 +#define MAXTIMINGS 84 + +//This is the main function which requests and reads the packet +uint8_t DHT_Read_Data(uint16_t *temperature, uint16_t *humidity); diff --git a/platform/RaspBee/dev/ds1820.c b/platform/RaspBee/dev/ds1820.c new file mode 100644 index 000000000..9de3fc8a9 --- /dev/null +++ b/platform/RaspBee/dev/ds1820.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2005, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * @(#)$Id: ds1820.c,v 1.5 2010/08/25 18:35:52 nifi Exp $ + */ +/* + * Device driver for the Dallas Semiconductor DS1820 chip. Heavily + * based on the application note 126 "1-Wire Communications Through + * Software". + * + * http://www.maxim-ic.com/appnotes.cfm/appnote_number/126 + */ + +/* + * For now we stuff in Moteiv Corporation's unique OUI. + * From http://www.ethereal.com/distribution/manuf.txt: + * 00:12:75 Moteiv # Moteiv Corporation + * + * The EUI-64 is a concatenation of the 24-bit OUI value assigned by + * the IEEE Registration Authority and a 40-bit extension identifier + * assigned by the organization with that OUI assignment. + */ + +#include +#include +#include "contiki.h" +#include "ds1820.h" + + +unsigned char ds1820_id[8]; +unsigned char ds1820_ok[8]; + +/* 1-wire is at PortE.3 */ +#define SERIAL_ID_PIN_READ PINE +//#define SERIAL_ID_PIN_MASK _BV(PE3) +#define SERIAL_ID_PIN_MASK _BV(PE4) +#define SERIAL_ID_PxOUT PORTE +#define SERIAL_ID_PxDIR DDRE + +#define SET_PIN_INPUT() (SERIAL_ID_PxDIR &= ~SERIAL_ID_PIN_MASK) +#define SET_PIN_OUTPUT() (SERIAL_ID_PxDIR |= SERIAL_ID_PIN_MASK) + +#define OUTP_0() (SERIAL_ID_PxOUT &= ~SERIAL_ID_PIN_MASK) +#define OUTP_1() (SERIAL_ID_PxOUT |= SERIAL_ID_PIN_MASK) + +#define PIN_INIT() do{ \ + SET_PIN_INPUT(); \ + OUTP_0(); \ + } while(0) + + +/* Drive the one wire interface low */ +#define OW_DRIVE() do { \ + SET_PIN_OUTPUT(); \ + OUTP_0(); \ + } while (0) + +/* Release the one wire by turning on the internal pull-up. */ +#define OW_RELEASE() do { \ + SET_PIN_INPUT(); \ + OUTP_1(); \ + } while (0) + +/* Read one bit. */ +#define INP() (SERIAL_ID_PIN_READ & SERIAL_ID_PIN_MASK) + + +/* + * Delay times in us. + */ +#define tA 6 /* min-5, recommended-6, max-15 */ +#define tB 64 /* min-59, recommended-64, max-N/A */ +#define tC 60 /* min-60, recommended-60, max-120 */ +#define tD 10 /* min-5.3, recommended-10, max-N/A */ +#define tE 9 /* min-0.3, recommended-9, max-9.3 */ +#define tF 55 /* min-50, recommended-55, max-N/A */ +#define tG 0 /* min-0, recommended-0, max-0 */ +#define tH 480 /* min-480, recommended-480, max-640 */ +#define tI 70 /* min-60.3, recommended-70, max-75.3 */ +#define tJ 410 /* min-410, recommended-410, max-N/A */ +/*---------------------------------------------------------------------------*/ +#define udelay(u) clock_delay_usec(u) +/*---------------------------------------------------------------------------*/ + +static int +owreset(void) +{ + int result; + + OW_DRIVE(); + udelay(tH); /* 480 < tH < 640 */ + OW_RELEASE(); /* Releases the bus */ + udelay(tI); + result = INP(); + udelay(tJ); + return result; +} +/*---------------------------------------------------------------------------*/ +static void +owwriteb(unsigned byte) +{ + int i = 7; + + do { + if(byte & 0x01) { + OW_DRIVE(); + udelay(tA); + OW_RELEASE(); /* Releases the bus */ + udelay(tB); + } else { + OW_DRIVE(); + udelay(tC); + OW_RELEASE(); /* Releases the bus */ + udelay(tD); + } + if(i == 0) { + return; + } + i--; + byte >>= 1; + } while(1); +} +/*---------------------------------------------------------------------------*/ +static unsigned +owreadb(void) +{ + unsigned result = 0; + int i = 7; + + do { + OW_DRIVE(); + udelay(tA); + OW_RELEASE(); /* Releases the bus */ + udelay(tE); + if (INP()){ + result |= 0x80; /* LSbit first */ + } + udelay(tF); + if(i == 0) { + return result; + } + i--; + result >>= 1; + } while(1); +} +/*---------------------------------------------------------------------------*/ +/* Polynomial ^8 + ^5 + ^4 + 1 */ +static unsigned +crc8_add(unsigned acc, unsigned byte) +{ + int i; + acc ^= byte; + for(i = 0; i < 8; i++) { + if(acc & 1) { + acc = (acc >> 1) ^ 0x8c; + } else { + acc >>= 1; + } + } + return acc; +} +/*---------------------------------------------------------------------------*/ +int +ds1820_init() +{ + int i; + unsigned family, crc, acc; + + PIN_INIT(); + + if(owreset() == 0) { /* Something pulled down 1-wire. */ + + owwriteb(0x33); /* Read ROM command. */ + family = owreadb(); + /* We receive 6 bytes in the reverse order, LSbyte first. */ + for(i = 7; i >= 2; i--) { + ds1820_id[i] = owreadb(); + } + crc = owreadb(); + + /* Verify family DS1820 and that CRC match. */ + if(family != 0x10) { + goto fail; + } + acc = crc8_add(0x0, family); + for(i = 7; i >= 2; i--) { + acc = crc8_add(acc, ds1820_id[i]); + } + if(acc == crc) { + ds1820_id[0] = 0x00; + ds1820_id[1] = 0x00; + ds1820_id[2] = 0x00; + return 1; /* Success! */ + } + } else { + } + + + fail: + memset(ds1820_id, 0x0, sizeof(ds1820_id)); + return 0; /* Fail! */ +} +/*---------------------------------------------------------------------------*/ +int +ds1820_temp() +{ + ds1820_convert(); +// wait max 750ms pin lo + clock_wait(CLOCK_SECOND); + ds1820_read(); + return 1; +} + +int +ds1820_convert() +{ + unsigned i; + + PIN_INIT(); + for(i=0;i<3;i++){ + if(owreset() == 0) { /* Something pulled down 1-wire. */ + owwriteb(0xCC); /* Skip ROM command. */ + owwriteb(0x44); /* Convert T command. */ + OW_RELEASE(); /* Releases the bus */ + return 1; + } else { + } + } + return 0; /* Fail! */ +} +/*---------------------------------------------------------------------------*/ +int +ds1820_read() +{ + int i; + unsigned crc, acc; + + if(owreset() == 0) { /* Something pulled down 1-wire. */ + owwriteb(0xCC); /* Skip ROM command. */ + owwriteb(0xBE); /* Read Scratchpad command. */ + /* We receive 8 bytes in the reverse order, LSbyte first. */ + for(i = 0; i < 8; i++) { + ds1820_id[i] = owreadb(); + } + crc = owreadb(); + + acc=0; + for(i = 0; i < 8; i++) { + acc = crc8_add(acc, ds1820_id[i]); + } + if(acc == crc) { + // store temp + for(i = 0; i < 8; i++) { + ds1820_ok[i]=ds1820_id[i]; + } + return 1; /* Success! */ + } else { + return 0; /* Fail! */ + } + } else { + return 0; /* Fail! */ + } + return 1; /* Fail! */ +} diff --git a/platform/RaspBee/dev/ds1820.h b/platform/RaspBee/dev/ds1820.h new file mode 100644 index 000000000..e4178d63e --- /dev/null +++ b/platform/RaspBee/dev/ds1820.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2005, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * @(#)$Id: ds1820.h,v 1.1 2006/06/17 22:41:16 adamdunkels Exp $ + */ +/* -*- C -*- */ +/* @(#)$Id: ds1820.h,v 1.1 2006/06/17 22:41:16 adamdunkels Exp $ */ + +#ifndef DS1820_H +#define DS1820_H + +extern unsigned char ds1820_id[8]; +extern unsigned char ds1820_ok[8]; +extern int ds1820_init(); +extern int ds1820_convert(); +extern int ds1820_read(); +extern int ds1820_temp(); +#endif /* DS1820_H */ diff --git a/platform/osd-merkur/dev/Suli.h b/platform/RaspBee/dev/hw-arduino.h similarity index 59% rename from platform/osd-merkur/dev/Suli.h rename to platform/RaspBee/dev/hw-arduino.h index 892c8cef7..bcd626ec6 100644 --- a/platform/osd-merkur/dev/Suli.h +++ b/platform/RaspBee/dev/hw-arduino.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Ralf Schlatterbeck Open Source Consulting + * Copyright (c) 2014, Ralf Schlatterbeck Open Source Consulting * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,77 +30,54 @@ */ /** - * \defgroup Suli compatibility + * \defgroup compatibility Arduino - Contiki * - * Seeed Unified Library Interface for Contiki OS - * See also https://github.com/Seeed-Studio/Suli - * - * Note: For now this only implements what we need to the LED_Strip example - * working. We're re-using existing Arduino wrappers where possible. + * This defines contiki-compatible hardware definitions for running + * arduino sketches (or just to call arduino-compatible function). + * For now only for osd hardware, a similar file should exist for each + * arduino-compatible hardware. * * @{ */ /** * \file - * Header file for Seeed compatibility + * Header file for arduino compatibility * \author * Ralf Schlatterbeck + * */ -#include - #ifdef __cplusplus -extern "C" { +extern "C"{ #endif -#define suli_delay_ms(ms) clock_delay_msec(ms) -#define suli_delay_us(us) clock_delay_usec(us) +#include "contiki.h" -/* These are used by Suli */ -typedef uint8_t uint8; -typedef uint16_t uint16; -typedef uint32_t uint32; -typedef int16_t int16; -typedef int32_t int32; +/* + * The OSD hardware only supports timer 3 for PWM, timer 2 is used by + * contiki for sleep/wakeup timing and is not usable for PWM. + */ +#define digitalPinToTimer(pin) \ + ( (pin) == 2 \ + ? TIMER3A \ + : ( (pin) == 3 \ + ? TIMER3B \ + : ((pin == 4) ? TIMER3C : NOT_ON_TIMER) \ + ) \ + ) -typedef int IO_T; // IO type -typedef int PIN_T; // pin name -typedef int DIR_T; // pin direction - -/* From Arduino.h */ -#define HAL_PIN_INPUT INPUT -#define HAL_PIN_OUTPUT OUTPUT -#define HAL_PIN_HIGH HIGH -#define HAL_PIN_LOW LOW - -static inline void suli_pin_init (IO_T *pio, PIN_T pin) -{ - *pio = pin; -} - -static inline void suli_pin_dir (IO_T *pio, DIR_T dir) -{ - pinMode (*pio, dir); -} - -static inline void suli_pin_write (IO_T *pio, int16 state) -{ - digitalWrite (*pio, state); -} - -static inline int16 suli_pin_read (IO_T *pio) -{ - return digitalRead (*pio); -} - -#ifdef __cplusplus -} // extern "C" -#endif +/* Only init timer 3 with phase correct pwm 8-bit and prescaler 64 */ +#define arduino_pwm_timer_init() \ + (hwtimer_ini (3, HWT_WGM_PWM_PHASE_8_BIT, HWT_CLOCK_PRESCALER_64, 0)) /* * VI settings, see coding style * ex:ts=8:et:sw=2 */ +#ifdef __cplusplus +} // extern "C" +#endif + /** @} */ diff --git a/platform/RaspBee/dev/i2c.c b/platform/RaspBee/dev/i2c.c new file mode 100644 index 000000000..0fa295849 --- /dev/null +++ b/platform/RaspBee/dev/i2c.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2014, Ingo Gulyas Intembsys + * 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 + * I2C driver for ATMEGA128rfa1 + * + * \author + * Ingo Gulyas Intembsys + * office@intembsys.at + * www.intembsys.at + */ + + +#include "i2c.h" +#include "contiki-conf.h" +#include +#include +#include +#include + +#if I2C_TD != 0 +#include +#include +#include "system_mgmt.h" +#define PRINTD(FORMAT,args...) {sleep_acquire_lock(); printf_P(PSTR(FORMAT),##args); sleep_release_lock();} +#else +#define PRINTD(...) +#endif + +#if WITH_RTDEBUG == 1 +#include "rtdebug.h" +#define RTDEBUG_PUSH(x) rtdebug_push(x) +#else +#warning "I2C Driver compiling without RTDEBUG!" +#define RTDEBUG_PUSH(x) +#endif + +#ifndef TIMEOUT_TIMER +#warning "I2C Driver compiling without TIMEOUT!" +#endif + + +static int8_t wait_job(); +static int8_t wait_stop(); + +static int8_t i2c_ioctl(const i2c_driver* const me, uint8_t cmd, uint8_t arg); +static int8_t i2c_read(const i2c_driver* const me, uint8_t cmd_flags, uint8_t* buffer, uint8_t len); +static int8_t i2c_write(const i2c_driver* const me, uint8_t cmd_flags, const uint8_t* data, uint8_t len); + + +// static linkage of member functions +i2c_driver i2c_drv = {i2c_ioctl, i2c_read, i2c_write}; +// lock spi if driver opened to prevent further opening access +static volatile bool i2c_lock = false; + + +/////////////////////////////////////////////////////////////// +// global functions +/////////////////////////////////////////////////////////////// + +i2c_driver* i2c_open(void) +{ + if(i2c_lock == true) + { + RTDEBUG_PUSH(RTDEBUG_CODE__I2C_OPEN__DEVICE_BUSY); + return NULL; + } + + i2c_lock = true; + power_twi_enable(); + I2C_INIT(); + + TWBR = I2C_FREQ_STANDARD; + TWSR &= ~((1< 0) && (buffer == NULL)) + { + RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__ERROR_NULLPOINTER); + return I2C_ERROR_DRIVER; + } + + do + { + if(cmd_flags & I2C_CMD_FLAG_START) + { + I2C_START(); + if(wait_job() != I2C_OK) + { + RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__START_TIMEOUT); + status = I2C_ERROR_TIMEOUT; + break; + } + if((I2C_STATUS() != I2C_STATUS_START) && (I2C_STATUS() != I2C_STATUS_START_REP)) + { + RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__START_ERROR); + status = I2C_ERROR_START; + break; + } + PRINTD("I2C-RD-START\n"); + } + + if(len == 0) break; + + for(i=0; i<(len-1); i++) + { + I2C_READ_BYTE_ACK(); + if(wait_job() != I2C_OK) + { + RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__READ_BYTE_ACK_TIMEOUT); + status = I2C_ERROR_TIMEOUT; + break; + } + if(I2C_STATUS() != I2C_STATUS_DATAR_ACK) + { + RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__READ_BYTE_ACK_ERROR); + status = I2C_ERROR_READ; + break; + } + buffer[i] = I2C_RX_REG; + PRINTD("I2C-RD-RACK: 0x%02X\n", buffer[i]); + } + + I2C_READ_BYTE_NACK(); + if(wait_job() != I2C_OK) + { + RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__READ_BYTE_NACK_TIMEOUT); + status = I2C_ERROR_TIMEOUT; + break; + } + if(I2C_STATUS() != I2C_STATUS_DATAR_NACK) + { + RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__READ_BYTE_NACK_ERROR); + status = I2C_ERROR_READ; + break; + } + buffer[i] = I2C_RX_REG; + PRINTD("I2C-RD-RNACK: 0x%02X\n", buffer[i]); + + } while (0); + + if(cmd_flags & I2C_CMD_FLAG_STOP) + { + I2C_STOP(); + if(wait_stop() != I2C_OK) + { + RTDEBUG_PUSH(RTDEBUG_CODE__I2C_READ__STOP_TIMEOUT); + status = I2C_ERROR_TIMEOUT; + } + PRINTD("I2C-RD_STOP\n"); + } + + return status; +} + +static int8_t i2c_write(const i2c_driver* const me, uint8_t cmd_flags, const uint8_t* data, uint8_t len) +{ + uint8_t i = 0; + int8_t status = I2C_OK; + + + if(me == NULL || i2c_lock == false) + { + RTDEBUG_PUSH(RTDEBUG_CODE__I2C_WRITE__DEVICE_CLOSED); + return I2C_ERROR_DRIVER; + } + + if((len > 0) && (data == NULL)) + { + RTDEBUG_PUSH(RTDEBUG_CODE__I2C_WRITE__ERROR_NULLPOINTER); + return I2C_ERROR_DRIVER; + } + + do + { + if(cmd_flags & I2C_CMD_FLAG_START) + { + I2C_START(); + if(wait_job() != I2C_OK) + { + RTDEBUG_PUSH(RTDEBUG_CODE__I2C_WRITE__START_TIMEOUT); + status = I2C_ERROR_TIMEOUT; + break; + } + if((I2C_STATUS() != I2C_STATUS_START) && (I2C_STATUS() != I2C_STATUS_START_REP)) + { + RTDEBUG_PUSH(RTDEBUG_CODE__I2C_WRITE__START_ERROR); + status = I2C_ERROR_START; + break; + } + PRINTD("I2C-WR-START\n"); + } + + + + for(i=0; i + +//////////////////////////////////////////////////////////////////////////////////////////// +// CONFIGURATION SECTION: + +#define I2C_TD 0 // compiler switch: i2c testdriver code + +#define I2C_PORT PORTD +#define I2C_DDR DDRD +#define I2C_SCL_PIN 0 +#define I2C_SDA_PIN 1 + +// END OF CONFIGURATION SECTION +//////////////////////////////////////////////////////////////////////////////////////////// + +#define I2C_INIT() ({I2C_DDR &= ~((1< CHECK F_CPU SETTINGS!" +#endif + + +#define I2C_STATUS_REG TWSR +#define I2C_TX_REG TWDR +#define I2C_RX_REG TWDR + +#define I2C_START() (TWCR = (1< +#include + +void key_init(void); +uint8_t is_button(void); + +#endif /* __KEY_H__ */ diff --git a/platform/RaspBee/dev/led.c b/platform/RaspBee/dev/led.c new file mode 100644 index 000000000..f9a7163d0 --- /dev/null +++ b/platform/RaspBee/dev/led.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2012 Bernhard Trinnes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holders nor the names of + * 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 OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * + * \brief + * This file provides RaspBee LED support. + * + * \author + * Bernhard Trinnes bernhard.trinnes@guh.guru + * + */ + +#include "led.h" + +/** + * \addtogroup relay + * \{ +*/ +/*---------------------------------------------------------------------------*/ + +/** + * \brief Turns LED1 on. +*/ +void +led1_on(void) +{ + PORTD &= ~(1< +*/ + +#include "contiki.h" +#include "Arduino.h" +#include "dev/optriac-sensor.h" + +#define PRINTF(...) printf(__VA_ARGS__) + +const struct sensors_sensor optriac_sensor; +static int status(int type); +static int enabled = 0; +static int optriac[2]={0,0}; +static int optriacpin[8]={OPTRIAC_PIN_1,OPTRIAC_PIN_2}; + +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + return optriac[type]; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int c) +{ + switch(type) { + case SENSORS_ACTIVE: + if(c) { + if(!status(SENSORS_ACTIVE)) { + pinMode(optriacpin[OPTRIAC_SENSOR_1], OUTPUT); + digitalWrite(optriacpin[OPTRIAC_SENSOR_1], LOW); + pinMode(optriacpin[OPTRIAC_SENSOR_2], OUTPUT); + digitalWrite(optriacpin[OPTRIAC_SENSOR_2], LOW); + + enabled = 1; + } + } else { + enabled = 1; + } + break; + case OPTRIAC_SENSOR_1: + case OPTRIAC_SENSOR_2: + + if(c==0){ + digitalWrite(optriacpin[type], LOW); + optriac[type]=0; + }else{ + digitalWrite(optriacpin[type], HIGH); + optriac[type]=1; + }; + break; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(optriac_sensor, OPTRIAC_SENSOR, value, configure, status); diff --git a/platform/RaspBee/dev/optriac-sensor.h b/platform/RaspBee/dev/optriac-sensor.h new file mode 100644 index 000000000..8cec46c14 --- /dev/null +++ b/platform/RaspBee/dev/optriac-sensor.h @@ -0,0 +1,54 @@ +/* +* Copyright (c), Harald Pichler. +* 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. +* +* @(#)$Id: servo-sensor.h,v 1.0 2013/02/20 19:34:06 nifi Exp $ +*/ + +/** +* \file +* Servo sensor header file for Atmega128rfa1. +* \author +* Harald Pichler +*/ + +#ifndef __OPTRIAC_SENSOR_H__ +#define __OPTRIAC_SENSOR_H__ + +#include "lib/sensors.h" + +extern const struct sensors_sensor optriac_sensor; + +#define OPTRIAC_SENSOR "TRIAC" +#define OPTRIAC_SENSOR_1 0 +#define OPTRIAC_SENSOR_2 1 + +/* default pins Arduino-Merkurboard */ +#define OPTRIAC_PIN_1 2 +#define OPTRIAC_PIN_2 3 + +#endif /* __OPTRIAC_SENSOR_H__ */ diff --git a/platform/osd-merkur/dev/pins_arduino.h b/platform/RaspBee/dev/pins_arduino.h similarity index 100% rename from platform/osd-merkur/dev/pins_arduino.h rename to platform/RaspBee/dev/pins_arduino.h diff --git a/platform/RaspBee/dev/pir-sensor.c b/platform/RaspBee/dev/pir-sensor.c new file mode 100644 index 000000000..37a97c025 --- /dev/null +++ b/platform/RaspBee/dev/pir-sensor.c @@ -0,0 +1,85 @@ +/* Sensor routine */ +#include "contiki.h" +#include "lib/sensors.h" +#include "dev/pir-sensor.h" + +#include +#include "led.h" // debug + +const struct sensors_sensor pir_sensor; + +static struct timer debouncetimer; +static int status(int type); +static int enabled = 0; +struct sensors_sensor *sensors[1]; +unsigned char sensors_flags[1]; + +#define PIR_BIT INTF6 +#define PIR_CHECK_IRQ() (EIFR & PIR_BIT) ? 0 : 1 + +#define PRINTF(...) printf(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +ISR(INT6_vect) +{ + +// leds_toggle(LEDS_YELLOW); + + if(PIR_CHECK_IRQ()) { + if(timer_expired(&debouncetimer)) { + // led1_on(); + timer_set(&debouncetimer, CLOCK_SECOND / 4); + sensors_changed(&pir_sensor); + // led1_off(); + } + } + +} +/*---------------------------------------------------------------------------*/ + +static int +value(int type) +{ + return (PORTE & _BV(PE6) ? 0 : 1) || !timer_expired(&debouncetimer); + //return 0; +} + +static int +configure(int type, int c) +{ + switch (type) { + case SENSORS_ACTIVE: + if (c) { + if(!status(SENSORS_ACTIVE)) { + // led1_on(); + timer_set(&debouncetimer, 0); + DDRE |= (0< +*/ + +#ifndef __PIR_SENSOR_H__ +#define __PIR_SENSOR_H__ + +#include "lib/sensors.h" + +extern const struct sensors_sensor pir_sensor; + +#define PIR_SENSOR "PIR" + +#endif /* __PIR_SENSOR_H__ */ \ No newline at end of file diff --git a/platform/RaspBee/dev/relay-sensor.c b/platform/RaspBee/dev/relay-sensor.c new file mode 100644 index 000000000..6415926c9 --- /dev/null +++ b/platform/RaspBee/dev/relay-sensor.c @@ -0,0 +1,109 @@ +/* +* Copyright (c) , Harald Pichler. +* 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. +* +* @(#)$Id: relay-sensor.c,v 1.0 2013/11/22 19:34:06 nifi Exp $ +*/ + +/** +* \file +* relay sensor header file for Atmega128rfa1. +* \author +* Harald Pichler +*/ + +#include "contiki.h" +#include "dev/relay.h" +#include "dev/relay-sensor.h" + +#define PRINTF(...) printf(__VA_ARGS__) + +const struct sensors_sensor relay_sensor; +static int status(int type); +static int enabled = 0; +static int relay[8]={0,0,0,0,0,0,0,0}; +static int relaypin[8]={RELAY_PIN_1,RELAY_PIN_2,RELAY_PIN_3,RELAY_PIN_4,RELAY_PIN_5,RELAY_PIN_6,RELAY_PIN_7,RELAY_PIN_8}; +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + return relay[type]; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int c) +{ + switch(type) { + case SENSORS_ACTIVE: + if(c) { + if(!status(SENSORS_ACTIVE)) { + relay_init(relaypin[RELAY_SENSOR_1]); + relay_init(relaypin[RELAY_SENSOR_2]); + relay_init(relaypin[RELAY_SENSOR_3]); + relay_init(relaypin[RELAY_SENSOR_4]); + relay_init(relaypin[RELAY_SENSOR_5]); + relay_init(relaypin[RELAY_SENSOR_6]); + relay_init(relaypin[RELAY_SENSOR_7]); + relay_init(relaypin[RELAY_SENSOR_8]); + enabled = 1; + } + } else { + enabled = 1; + } + break; + case RELAY_SENSOR_1: + case RELAY_SENSOR_2: + case RELAY_SENSOR_3: + case RELAY_SENSOR_4: + case RELAY_SENSOR_5: + case RELAY_SENSOR_6: + case RELAY_SENSOR_7: + case RELAY_SENSOR_8: + if(c==0){ + relay_off(relaypin[type]); + relay[type]=0; + }else{ + relay_on(relaypin[type]); + relay[type]=1; + }; + break; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(relay_sensor, RELAY_SENSOR, value, configure, status); diff --git a/platform/RaspBee/dev/relay-sensor.h b/platform/RaspBee/dev/relay-sensor.h new file mode 100644 index 000000000..88b9dd0f5 --- /dev/null +++ b/platform/RaspBee/dev/relay-sensor.h @@ -0,0 +1,66 @@ +/* +* Copyright (c), Harald Pichler. +* 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. +* +* @(#)$Id: relay-sensor.h,v 1.0 2013/11/22 19:34:06 nifi Exp $ +*/ + +/** +* \file +* Relay sensor header file for Atmega128rfa1. +* \author +* Harald Pichler +*/ + +#ifndef __RELAY_SENSOR_H__ +#define __RELAY_SENSOR_H__ + +#include "lib/sensors.h" + +extern const struct sensors_sensor relay_sensor; + +#define RELAY_SENSOR "RELAY" +#define RELAY_SENSOR_1 0 +#define RELAY_SENSOR_2 1 +#define RELAY_SENSOR_3 2 +#define RELAY_SENSOR_4 3 +#define RELAY_SENSOR_5 4 +#define RELAY_SENSOR_6 5 +#define RELAY_SENSOR_7 6 +#define RELAY_SENSOR_8 7 + +/* default pins Arduino-Merkurboard */ +#define RELAY_PIN_1 10 +#define RELAY_PIN_2 11 +#define RELAY_PIN_3 12 +#define RELAY_PIN_4 13 +#define RELAY_PIN_5 15 +#define RELAY_PIN_6 16 +#define RELAY_PIN_7 17 +#define RELAY_PIN_8 18 + +#endif /* __RELAY_SENSOR_H__ */ diff --git a/platform/RaspBee/dev/relay.c b/platform/RaspBee/dev/relay.c new file mode 100644 index 000000000..67d9c7f5b --- /dev/null +++ b/platform/RaspBee/dev/relay.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2012 harald pichler + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holders nor the names of + * 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 OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * + * \brief + * This file provides Raven LED support. + * + * \author + * Harald Pichler harald@the-develop.net + * + */ +#include "Arduino.h" +#include "relay.h" + +/** + * \addtogroup relay + * \{ +*/ +/*---------------------------------------------------------------------------*/ +/** + * \brief init RELAY PINS. +*/ +void +relay_init(uint8_t pin) +{ + pinMode(pin, OUTPUT); + digitalWrite(pin, LOW); +} +/** + * \brief Turns the RELAY on. +*/ + +void +relay_on(uint8_t pin) +{ + digitalWrite(pin, HIGH); +} + +/*---------------------------------------------------------------------------*/ + +/** + * \brief Turns the RELAY off +*/ +void +relay_off(uint8_t pin) +{ + digitalWrite(pin, LOW); +} diff --git a/platform/RaspBee/dev/relay.h b/platform/RaspBee/dev/relay.h new file mode 100644 index 000000000..3b9b48759 --- /dev/null +++ b/platform/RaspBee/dev/relay.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2012 Harald Pichler + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holders nor the names of + * 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 OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * + * \brief + * This file provides Raven LED support. + * + * \author + * Harald Pichler harald@the-develop.net + * + */ + +#ifndef __RELAY_H__ +#define __RELAY_H__ + +#include + +/** @name RELAY Functions */ +/** @{ */ +void relay_init(uint8_t pin); +void relay_on(uint8_t pin); +void relay_off(uint8_t pin); + +/** @} */ + +#endif /* __RELAY_H__ */ diff --git a/platform/RaspBee/dev/servo-sensor.c b/platform/RaspBee/dev/servo-sensor.c new file mode 100644 index 000000000..9da3caf80 --- /dev/null +++ b/platform/RaspBee/dev/servo-sensor.c @@ -0,0 +1,100 @@ +/* +* Copyright (c) , Harald Pichler. +* 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. +* +* @(#)$Id: servo-sensor.c,v 1.0 2013/02/20 19:34:06 nifi Exp $ +*/ + +/** +* \file +* Servo sensor header file for Atmega128rfa1. +* \author +* Harald Pichler +*/ + +#include "contiki.h" +#include "dev/servo.h" +#include "dev/servo-sensor.h" + +#define PRINTF(...) printf(__VA_ARGS__) + +const struct sensors_sensor servo_sensor; +static int status(int type); +static int enabled = 0; + +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + switch(type) { + case SERVO_SENSOR_A: + return servo_get(0);; + + /* Total Solar Radiation. */ + case SERVO_SENSOR_B: + return servo_get(1); + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int c) +{ + switch(type) { + case SENSORS_ACTIVE: + if(c) { + if(!status(SENSORS_ACTIVE)) { + servo_init(); + enabled = 1; + } + } else { + servo_off(); + enabled = 1; + } + break; + case SERVO_SENSOR_A: + servo_set(0,c); + break; + case SERVO_SENSOR_B: + servo_set(1,c); + break; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(servo_sensor, SERVO_SENSOR, value, configure, status); diff --git a/platform/RaspBee/dev/servo-sensor.h b/platform/RaspBee/dev/servo-sensor.h new file mode 100644 index 000000000..44e50c0f8 --- /dev/null +++ b/platform/RaspBee/dev/servo-sensor.h @@ -0,0 +1,50 @@ +/* +* Copyright (c), Harald Pichler. +* 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. +* +* @(#)$Id: servo-sensor.h,v 1.0 2013/02/20 19:34:06 nifi Exp $ +*/ + +/** +* \file +* Servo sensor header file for Atmega128rfa1. +* \author +* Harald Pichler +*/ + +#ifndef __SERVO_SENSOR_H__ +#define __SERVO_SENSOR_H__ + +#include "lib/sensors.h" + +extern const struct sensors_sensor servo_sensor; + +#define SERVO_SENSOR "Servo" +#define SERVO_SENSOR_A 0 +#define SERVO_SENSOR_B 1 + +#endif /* __SERVO_SENSOR_H__ */ diff --git a/platform/RaspBee/dev/servo.c b/platform/RaspBee/dev/servo.c new file mode 100644 index 000000000..874e98b89 --- /dev/null +++ b/platform/RaspBee/dev/servo.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2007, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * Device driver for the Sensirion SHT1x/SHT7x family of humidity and + * temperature sensors. + */ + +#include "contiki.h" +#include +#include + +#define DEBUG 0 + +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +/* + * servo device + */ + +unsigned int servoa=SERVO_INIT; +unsigned int servob=SERVO_INIT; + +void +servo_init(void) +{ + // Port E initialization + // Set Pin 3 and 4 to output mode for OCR1A and OCR2A + DDRE |= 1<<3 | 1<<4; + + // Timer/Counter 3 initialization + // Clock source: System Clock + // Clock value: 2000.000 kHz + // Mode: Ph. & fr. cor. PWM top=ICR1 + // OC3A output: Connected + // OC3B output: Connected + // OC3C output: Connected + // Noise Canceler: Off + // Input Capture on Falling Edge + // Timer3 Overflow Interrupt: Off + // Input Capture Interrupt: Off + // Compare A Match Interrupt: Off + // Compare B Match Interrupt: Off + // Compare C Match Interrupt: Off + + /* TCCR3A = [COM3A1|COM3A0|COM3B1|COM3B0||FOC3A|FOC3B|WGM31|WGM30] */ + /* 1 0 1 0 1 0 0 0 */ + TCCR3A=0xA8; + /* TCCR3B = [ ICNC3| ICES3| -| WGM33||WGM32| CS32| CS31| CS30] */ + /* 0 0 0 1 0 0 1 0 */ + TCCR3B=0x12; + TCNT3H=0x00; + TCNT3L=0x00; + // ICR3 has a computed value of 20,000 - see the chip manual for how this + // value was derived. + // 20000 == 0x4e20 so that's what goes into the high and low byte of the ICR3 register + // alternatively, Codevision would let you just do ICR3 = 20000; + ICR3H=0x4E; + ICR3L=0x20; + + // OCR3A will govern the steering servo, OCR3B will govern throttle + OCR3A = servoa; // set it to an initial position somewhere in the middle of the 1 to 2ms range + + // OCR3A will govern the steering servo, OCR3B will govern throttle + OCR3B = servob; // set it to an initial position somewhere in the middle of the 1 to 2ms range + // start with motor off - no duty cycle at all + OCR3CH=0x00; + OCR3CL=0x00; +} +/*---------------------------------------------------------------------------*/ +/* + * Power of device. + */ +void +servo_off(void) +{ + +} +/*---------------------------------------------------------------------------*/ +/* + * get servo position + */ +unsigned int +servo_get(unsigned int i) +{ + if(i==0) + return servoa; + if(i==1) + return servob; + return 0; +} +/*---------------------------------------------------------------------------*/ +/* + * Set servo position + */ +unsigned int +servo_set(unsigned i,unsigned int j) +{ + if(j > SERVO_MAX) + j=SERVO_MAX; + if(j < SERVO_MIN) + j=SERVO_MIN; + + if(i==0) + { + servoa=j; + OCR3A = servoa; + return 1; + } + if(i==1) + { + servob=j; + OCR3B = servob; + return 1; + } + + return 0; +} diff --git a/platform/RaspBee/dev/servo.h b/platform/RaspBee/dev/servo.h new file mode 100644 index 000000000..c6ae4ab57 --- /dev/null +++ b/platform/RaspBee/dev/servo.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2007, Swedish Institute of Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#ifndef SERVO_H +#define SERVO_H + +#define SERVO_MIN 575 +#define SERVO_MAX 2425 +#define SERVO_INIT 1500 + +void servo_init(void); +void servo_off(void); + +unsigned int servo_get(unsigned int i); +unsigned int servo_set(unsigned i,unsigned int j); + +#endif /* SHT11_H */ diff --git a/platform/RaspBee/dev/sg-ready.c b/platform/RaspBee/dev/sg-ready.c new file mode 100644 index 000000000..0f34d94b7 --- /dev/null +++ b/platform/RaspBee/dev/sg-ready.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2015 Bernhard Trinnes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holders nor the names of + * 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 OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * + * \brief + * Smart Grid Ready Module - guhRF + * + * \author + * Bernhard Trinnes bernhard.trinnes@guh.guru + * + */ + +#include "sg-ready.h" +#define LATCH_TIME 3000 // time in micro seconds + +#define RELAY1_ON (1< Pin high = Relay Open */ + if ((~PIND & RELAY1_FB) && (~PIND & RELAY2_FB)){ + state = 4; + }else if (~PIND & RELAY1_FB){ + state = 1; + } else if (~PIND & RELAY2_FB){ + state = 3; + } else { + state = 2; + } + return state; +} +/** + * \brief +*/ + +void +switch_difference(uint8_t old, uint8_t new) +{ + switch(old) { + case 1: + switch(new) { + case 2: + PORTB |= RELAY1_OFF; + PORTB &= ~(RELAY1_ON | RELAY2_ON | RELAY2_OFF); + clock_delay_usec (LATCH_TIME); + PORTB &= ~(RELAY1_OFF); + break; + case 3: + PORTB |= (RELAY1_OFF | RELAY2_ON ); + PORTB &= ~(RELAY1_ON | RELAY2_OFF); + clock_delay_usec (LATCH_TIME); + PORTB &= ~(RELAY1_OFF | RELAY2_ON); + break; + case 4: + PORTB |= RELAY2_ON; + PORTB &= ~(RELAY1_ON | RELAY1_OFF | RELAY2_OFF); + clock_delay_usec (LATCH_TIME); + PORTB &= ~(RELAY2_ON); + break; + } + break; + case 2: + switch(new) { + case 1: + PORTB |= RELAY1_ON; + PORTB &= ~(RELAY1_OFF | RELAY2_ON | RELAY2_OFF); + clock_delay_usec (LATCH_TIME); + PORTB &= ~(RELAY1_ON); + break; + case 3: + PORTB |= (RELAY2_ON); + PORTB &= ~(RELAY1_ON | RELAY1_OFF | RELAY2_OFF); + clock_delay_usec (LATCH_TIME); + PORTB &= ~(RELAY2_ON); + break; + case 4: + PORTB |= (RELAY1_ON | RELAY2_ON); + PORTB &= ~(RELAY1_OFF | RELAY2_OFF); + clock_delay_usec (LATCH_TIME); + PORTB &= ~(RELAY1_ON | RELAY2_ON); + break; + } + + break; + case 3: + switch(new) { + case 1: + PORTB |= (RELAY1_ON | RELAY2_OFF); + PORTB &= ~(RELAY1_OFF | RELAY2_ON); + clock_delay_usec (LATCH_TIME); + PORTB &= ~(RELAY1_ON | RELAY2_OFF); + break; + case 2: + PORTB |= RELAY2_OFF; + PORTB &= ~(RELAY1_ON | RELAY1_OFF | RELAY2_ON); + clock_delay_usec (LATCH_TIME); + PORTB &= ~(RELAY2_OFF); + break; + case 4: + PORTB |= RELAY1_ON; + PORTB &= ~(RELAY1_OFF | RELAY2_ON | RELAY2_OFF); + clock_delay_usec (LATCH_TIME); + PORTB &= ~(RELAY1_ON); + break; + } + break; + case 4: + switch(new) { + case 1: + PORTB |= RELAY2_OFF; + PORTB &= ~(RELAY1_ON | RELAY1_OFF | RELAY2_ON); + clock_delay_usec (LATCH_TIME); + PORTB &= ~(RELAY2_OFF); + break; + case 2: + PORTB |= (RELAY1_OFF | RELAY2_OFF); + PORTB &= ~(RELAY1_ON | RELAY2_ON ); + clock_delay_usec (LATCH_TIME); + PORTB &= ~(RELAY1_OFF | RELAY2_OFF); + break; + case 3: + PORTB |= RELAY1_OFF; + PORTB &= ~(RELAY1_ON | RELAY2_ON | RELAY2_OFF); + clock_delay_usec (LATCH_TIME); + PORTB &= ~(RELAY1_OFF); + break; + } + break; + } +} + diff --git a/platform/RaspBee/dev/sg-ready.h b/platform/RaspBee/dev/sg-ready.h new file mode 100644 index 000000000..81ba3f0c9 --- /dev/null +++ b/platform/RaspBee/dev/sg-ready.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015 Bernhard Trinnes + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of the copyright holders nor the names of + * 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 OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \file + * + * \brief + * + * + * \author + * Bernhard Trinnes bernhard.trinnes@guh.guru + * + */ + +#ifndef __SGREADY_H__ +#define __SGREADY_H__ + +#include + +/** @name Smart Grid Ready Functions */ +/** @{ */ +void relay_init(uint8_t pin); +void set_state(uint8_t pin); +uint8_t get_state(); +void switch_difference(uint8_t old, uint8_t new); + +/** @} */ + +#endif /* __SGREADY_H__ */ diff --git a/platform/RaspBee/dev/t4-servo-sensor.c b/platform/RaspBee/dev/t4-servo-sensor.c new file mode 100644 index 000000000..a35b2de02 --- /dev/null +++ b/platform/RaspBee/dev/t4-servo-sensor.c @@ -0,0 +1,101 @@ +/* +** Copyright (C) 2013-2014 Marcus Priesch, All rights reserved +** In Prandnern 31, A--2122 Riedenthal, Austria. office@priesch.co.at +** +** 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. +** +**++ +** Name +** t4-servo-sensor +** +** Purpose +** Implements a sensor around t4servo.c +** +** +** Revision Dates +** 31-Mar-2013 (MPR) Creation +** 12-Mar-2014 (MPR) Factored to support configurable amount of pwm's +** ««revision-date»»··· +**-- +*/ + +#include "contiki.h" +#include "dev/t4-servo.h" +#include "dev/t4-servo-sensor.h" + +const struct sensors_sensor t4_servo_sensor; + +static int status(int type); +static int enabled = 0; + +static int value (int channel) + { + if (channel >= SERVO_COUNT) + return -1; + else if (channel < 0) + return -2; + else + return t4_servo_get (channel); + } + +static int configure (int type, int c) // type, c: SENSORS_ACTIVE, 1 -> act. + // type, c: SENSORS_ACTIVE, 0 -> deact. + { + switch (type) + { + case SENSORS_ACTIVE : + if (c == 0) + { + t4_servo_off (); + } + else if (c == 1) + { + t4_servo_init (); + } + break; + + default : + if (type >= SERVO_COUNT) + return -1; + else + t4_servo_set (type, c); + break; + + } + return 0; + } + +static int status(int type) + { + switch (type) + { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + } + return 0; + } + +SENSORS_SENSOR(t4_servo_sensor, T4_SENSOR_NAME, value, configure, status); diff --git a/platform/RaspBee/dev/t4-servo-sensor.h b/platform/RaspBee/dev/t4-servo-sensor.h new file mode 100644 index 000000000..099bb4c66 --- /dev/null +++ b/platform/RaspBee/dev/t4-servo-sensor.h @@ -0,0 +1,52 @@ +/* +** Copyright (C) 2013-2014 Marcus Priesch, All rights reserved +** In Prandnern 31, A--2122 Riedenthal, Austria. office@priesch.co.at +** +** 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. +** +**++ +** Name +** t4-servo-sensor +** +** Purpose +** Implements a sensor around t4servo.c +** +** +** Revision Dates +** 31-Mar-2013 (MPR) Creation +** 12-Mar-2014 (MPR) Factored to support configurable amount of pwm's + ««revision-date»»··· +**-- +*/ + +#ifndef __T4_SERVO_SENSOR_H__ +#define __T4_SERVO_SENSOR_H__ + +#include "lib/sensors.h" +#include "t4-servo-config.h" + +extern const struct sensors_sensor t4_servo_sensor; + +#endif /* __T4_SERVO_SENSOR_H__ */ diff --git a/platform/RaspBee/dev/t4-servo.c b/platform/RaspBee/dev/t4-servo.c new file mode 100644 index 000000000..45f74ad9b --- /dev/null +++ b/platform/RaspBee/dev/t4-servo.c @@ -0,0 +1,139 @@ +/* +** Copyright (C) 2013-2014 Marcus Priesch, All rights reserved +** In Prandnern 31, A--2122 Riedenthal, Austria. office@priesch.co.at +** +** 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. +** +**++ +** Name +** t4-servo +** +** Purpose +** Implements software pwm on any portpins via timer 4 +** +** +** Revision Dates +** 31-Mar-2013 (MPR) Creation +** 12-Mar-2014 (MPR) Factored to support configurable amount of pwm's +** ««revision-date»»··· +**-- +*/ + +#include "t4-servo.h" +#include "t4-servo-config.h" +#include "t4-servo-hardware.h" +#include +#include + +// static servo_channel_type servo_channels [SERVO_COUNT]; + +// timer 4: CTC OCR4A +#define WGM4 0x4 + +void t4_servo_init (void) +{ + unsigned char channel; + + for (channel = 0; channel < SERVO_COUNT; channel ++) + { + _SFR_IO8 (servo_channels [channel].ddr ) |= servo_channels [channel].pin; + _SFR_IO8 (servo_channels [channel].port) &= ~(servo_channels [channel].pin); + } + + cli (); + TCCR4A = 0x00; + TCCR4A_struct.wgm4 = WGM4 & 0x3; + TCCR4B_struct.wgm4 = (WGM4 & 0xc) >> 2; + TCCR4B_struct.cs4 = 0x1; // No prescaler + TCCR4C = 0x00; + OCR4A = (T4_VALUE); + TIMSK4_struct.ocie4a = 1; + TIMSK4_struct.toie4 = 1; + sei(); +} + +void t4_servo_off (void) + { + TIMSK4_struct.toie4 = 0; + TIMSK4_struct.ocie4a = 0; + } + +int t4_servo_get (unsigned int channel) + { + if (channel >= SERVO_COUNT) + return -1; + //printf ("t4_servo_get: %d, %d\n", channel, servo_channels [channel].duty); + return servo_channels [channel].duty; + } + +int t4_servo_set (unsigned int channel, unsigned char duty) + { + //printf ("t4_servo_set: %d, %d\n", channel, duty); + + if (channel >= SERVO_COUNT) + return -1; + + if (duty > SERVO_MAX) + return -2; + + if (duty < SERVO_MIN) + return -3; + + servo_channels [channel].duty = duty; + return 0; + } + +ISR (TIMER4_COMPA_vect, ISR_NOBLOCK) + { + unsigned char channel; + static unsigned int tick_count = 0; + + cli (); + for (channel = 0; channel < SERVO_COUNT; channel ++) + { + if (tick_count < servo_channels [channel].duty) + { + // turn on +// _SFR_IO8 (servo_channels [channel].ddr ) |= servo_channels [channel].pin; + _SFR_IO8 (servo_channels [channel].port) |= servo_channels [channel].pin; + } + else + { + // turn off + _SFR_IO8 (servo_channels [channel].port) &= ~(servo_channels [channel].pin); +// _SFR_IO8 (servo_channels [channel].ddr ) |= servo_channels [channel].pin; + } + } + + tick_count ++; + + if (tick_count >= (SERVO_MAX + SERVO_OFFSET)) + { + tick_count = 0; + } + sei(); + + } + diff --git a/platform/RaspBee/dev/t4-servo.h b/platform/RaspBee/dev/t4-servo.h new file mode 100644 index 000000000..5acdc4013 --- /dev/null +++ b/platform/RaspBee/dev/t4-servo.h @@ -0,0 +1,61 @@ +/* +** Copyright (C) 2013-2014 Marcus Priesch, All rights reserved +** In Prandnern 31, A--2122 Riedenthal, Austria. office@priesch.co.at +** +** 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. +** +**++ +** Name +** t4-servo +** +** Purpose +** Implements software pwm on any portpins via timer 4 +** +** +** Revision Dates +** 31-Mar-2013 (MPR) Creation +** 12-Mar-2014 (MPR) Factored to support configurable amount of pwm's + ««revision-date»»··· +**-- +*/ + +#ifndef __T4_SERVO_H__ +#define __T4_SERVO_H__ + +typedef struct struct_servo_channel +{ + unsigned char port; + unsigned char ddr; + unsigned char pin; + unsigned char duty; +} servo_channel_type; + +void t4_servo_init(void); +void t4_servo_off(void); + +int t4_servo_get(unsigned int channel); +int t4_servo_set(unsigned int channel, unsigned char duty); + +#endif /* __T4_SERVO_H__ */ diff --git a/platform/RaspBee/dev/temperature-sensor.c b/platform/RaspBee/dev/temperature-sensor.c new file mode 100644 index 000000000..c85896178 --- /dev/null +++ b/platform/RaspBee/dev/temperature-sensor.c @@ -0,0 +1,66 @@ +/* +* Copyright (c) 2012, BinaryLabs. +* 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. +* +* @(#)$Id: temperature-sensor.c,v 1.1 2010/08/25 19:34:06 nifi Exp $ +*/ + +/** +* \file +* Temperature sensor header file for Atmega128rfa1. +* \author +* Paulo Louro +*/ + +#include "contiki.h" +#include "dev/temperature-sensor.h" + +#define PRINTF(...) printf(__VA_ARGS__) + + +const struct sensors_sensor temperature_sensor; + +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + return readInternalTemp(); +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int c) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(temperature_sensor, TEMPERATURE_SENSOR, value, configure, status); \ No newline at end of file diff --git a/platform/RaspBee/dev/temperature-sensor.h b/platform/RaspBee/dev/temperature-sensor.h new file mode 100644 index 000000000..6cf5dbf26 --- /dev/null +++ b/platform/RaspBee/dev/temperature-sensor.h @@ -0,0 +1,49 @@ +/* +* Copyright (c) 2012, BinaryLabs. +* 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. +* +* @(#)$Id: temperature-sensor.h,v 1.1 2012/08/25 19:34:06 nifi Exp $ +*/ + +/** +* \file +* Temperature sensor header file for Atmega128rfa1. +* \author +* Paulo Louro +*/ + +#ifndef __TEMPERATURE_SENSOR_H__ +#define __TEMPERATURE_SENSOR_H__ + +#include "lib/sensors.h" +#include "dev/adc.h" + +extern const struct sensors_sensor temperature_sensor; + +#define TEMPERATURE_SENSOR "Temperature" + +#endif /* __TEMPERATURE_SENSOR_H__ */ \ No newline at end of file diff --git a/platform/RaspBee/dev/wiring_digital.c b/platform/RaspBee/dev/wiring_digital.c new file mode 100644 index 000000000..75b6745d6 --- /dev/null +++ b/platform/RaspBee/dev/wiring_digital.c @@ -0,0 +1,104 @@ +/* + wiring_digital.c - digital input and output functions + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + Modified 28 September 2010 by Mark Sproul + + $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $ +*/ + +#define ARDUINO_MAIN +#include "wiring_private.h" +#include "pins_arduino.h" + +void pinMode(uint8_t pin, uint8_t mode) +{ + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + volatile uint8_t *reg, *out; + + if (port == NOT_A_PIN) return; + + // JWS: can I let the optimizer do this? + reg = portModeRegister(port); + out = portOutputRegister(port); + + if (mode == INPUT) { + uint8_t oldSREG = SREG; + cli(); + *reg &= ~bit; + *out &= ~bit; + SREG = oldSREG; + } else if (mode == INPUT_PULLUP) { + uint8_t oldSREG = SREG; + cli(); + *reg &= ~bit; + *out |= bit; + SREG = oldSREG; + } else { + uint8_t oldSREG = SREG; + cli(); + *reg |= bit; + SREG = oldSREG; + } +} + +void digitalWrite(uint8_t pin, uint8_t val) +{ + uint8_t timer = digitalPinToTimer(pin); + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + volatile uint8_t *out; + + if (port == NOT_A_PIN) return; + + // If the pin that support PWM output, we need to turn it off + // before doing a digital write. + if (timer != NOT_ON_TIMER) turnOffPWM(timer); + + out = portOutputRegister(port); + + uint8_t oldSREG = SREG; + cli(); + + if (val == LOW) { + *out &= ~bit; + } else { + *out |= bit; + } + + SREG = oldSREG; +} + +int digitalRead(uint8_t pin) +{ + uint8_t timer = digitalPinToTimer(pin); + uint8_t bit = digitalPinToBitMask(pin); + uint8_t port = digitalPinToPort(pin); + + if (port == NOT_A_PIN) return LOW; + + // If the pin that support PWM output, we need to turn it off + // before getting a digital reading. + if (timer != NOT_ON_TIMER) turnOffPWM(timer); + + if (*portInputRegister(port) & bit) return HIGH; + return LOW; +} diff --git a/platform/RaspBee/dev/wiring_private.h b/platform/RaspBee/dev/wiring_private.h new file mode 100644 index 000000000..37c263352 --- /dev/null +++ b/platform/RaspBee/dev/wiring_private.h @@ -0,0 +1,69 @@ +/* + wiring_private.h - Internal header file. + Part of Arduino - http://www.arduino.cc/ + + Copyright (c) 2005-2006 David A. Mellis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General + Public License along with this library; if not, write to the + Free Software Foundation, Inc., 59 Temple Place, Suite 330, + Boston, MA 02111-1307 USA + + $Id: wiring.h 239 2007-01-12 17:58:39Z mellis $ +*/ + +#ifndef WiringPrivate_h +#define WiringPrivate_h + +#include +#include +#include +#include + +#include "Arduino.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +#ifndef cbi +#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) +#endif +#ifndef sbi +#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) +#endif + +#define EXTERNAL_INT_0 0 +#define EXTERNAL_INT_1 1 +#define EXTERNAL_INT_2 2 +#define EXTERNAL_INT_3 3 +#define EXTERNAL_INT_4 4 +#define EXTERNAL_INT_5 5 +#define EXTERNAL_INT_6 6 +#define EXTERNAL_INT_7 7 + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#define EXTERNAL_NUM_INTERRUPTS 8 +#elif defined(__AVR_ATmega128RFA1__) || (__AVR_ATmega256RFR2__) +#define EXTERNAL_NUM_INTERRUPTS 8 +#else +#define EXTERNAL_NUM_INTERRUPTS 2 +#endif + +typedef void (*voidFuncPtr)(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif diff --git a/platform/osd-merkur/node-id.c b/platform/RaspBee/node-id.c similarity index 100% rename from platform/osd-merkur/node-id.c rename to platform/RaspBee/node-id.c diff --git a/platform/osd-merkur/node-id.h b/platform/RaspBee/node-id.h similarity index 100% rename from platform/osd-merkur/node-id.h rename to platform/RaspBee/node-id.h diff --git a/platform/osd-merkur/params.c b/platform/RaspBee/params.c similarity index 100% rename from platform/osd-merkur/params.c rename to platform/RaspBee/params.c diff --git a/platform/RaspBee/params.h b/platform/RaspBee/params.h new file mode 100644 index 000000000..68c717dec --- /dev/null +++ b/platform/RaspBee/params.h @@ -0,0 +1,105 @@ +#ifndef PARAMS_H_ +#define PARAMS_H_ +/* PARAMETER_STORAGE = + * 0 Hard coded, minmal program and eeprom usage. + * 1 Stored in fixed eeprom locations, rewritten from flash if corrupt. + * This allows parameter changes using a hardware programmer or custom application code. + * Corruption test is based on channel verify so get the channel before anything else! + * 2 Obtained from eeprom using the general settings manager and read from program flash if not present. + * Useful for for testing builds without wearing out flash memory. + * 3 Obtained from eeprom using the settings manager and rewritten from flash if not present. + * This ensures all parameters are present in upper eeprom flash. + * + * Note the parameters in this file can be changed without forcing a complete rebuild. + */ +// default settings +#define CHANNEL_802_15_4 26 // default frequency (11-26) + +// end default settings + +#define CONTIKI_CONF_RANDOM_MAC 1 //adds 78 bytes +#define CONTIKI_CONF_SETTINGS_MANAGER 0 //adds 1696 bytes +#define BOOTLOADER_GET_MAC 0 // get mac form boolaoder, need bootlaoder bonsai, PARAMETER_STORAGE 0 + +#if CONTIKI_CONF_SETTINGS_MANAGER +//#define PARAMETER_STORAGE 2 +#define PARAMETER_STORAGE 2 +#else +//#define PARAMETER_STORAGE 1 +#define PARAMETER_STORAGE 1 // get mac form boolaoder, need bootlaoder bonsai, PARAMETER_STORAGE 0 +#endif + +/* Include settings.h, then dummy out the write routines */ +#include "settings.h" +#if PARAMETER_STORAGE==2 +#define settings_add(...) 0 +#define settings_add_uint8(...) 0 +#define settings_add_uint16(...) 0 +#endif + +#if AVR_WEBSERVER +/* Webserver builds can set some defaults in httpd-fsdata.c via makefsdata.h */ +extern uint8_t eemem_mac_address[8]; +extern uint8_t eemem_server_name[16]; +extern uint8_t eemem_domain_name[30]; +#endif +#ifdef SERVER_NAME +#define PARAMS_SERVERNAME SERVER_NAME +#else +#define PARAMS_SERVERNAME "ATMEGA256rfr2" +#endif +#ifdef DOMAIN_NAME +#define PARAMS_DOMAINNAME DOMAIN_NAME +#else +#define PARAMS_DOMAINNAME "localhost" +#endif +#ifdef NODE_ID +#define PARAMS_NODEID NODE_ID +#else +#define PARAMS_NODEID 0 +#endif +#ifdef IEEE802154_PANADDR +#define PARAMS_PANADDR IEEE802154_PANADDR +#else +#define PARAMS_PANADDR 0 +#endif +#ifdef RF230_MAX_TX_POWER +#define PARAMS_TXPOWER RF230_MAX_TX_POWER +#else +#define PARAMS_TXPOWER 0 +#endif +#ifdef EUI64_ADDRESS +#define PARAMS_EUI64ADDR EUI64_ADDRESS +#else +/* This form of of EUI64 mac allows full 6LoWPAN header compression from mac address */ +#if UIP_CONF_LL_802154 +//#define PARAMS_EUI64ADDR {0x02, 0xNN, 0xNN, 0xNN, 0xNN, 0xNN, 0xNN, 0xNN} +//#define PARAMS_EUI64ADDR {0x00, 0x21, 0x2e, 0xff, 0xff, 0x00, 0x1E, 0xFB} +#define PARAMS_EUI64ADDR {0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x01} +#else +//#define PARAMS_EUI64ADDR {0x02, 0xNN, 0xNN, 0xff, 0xfe, 0xNN, 0xNN, 0xNN} +#define PARAMS_EUI64ADDR {0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x03} +#endif +/* This form of of EUI64 mac allows 16 bit 6LoWPAN header compression on multihops */ +//#define PARAMS_EUI64ADDR {0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0xNN, 0xNN} +#endif + +uint8_t params_get_eui64(uint8_t *eui64); +#if PARAMETER_STORAGE==0 +/* Hard coded program flash parameters */ +#define params_get_servername(...) +#define params_get_nodeid(...) PARAMS_NODEID +#define params_get_channel(...) CHANNEL_802_15_4 +#define params_get_panid(...) IEEE802154_PANID +#define params_get_panaddr(...) PARAMS_PANADDR +#define params_get_txpower(...) PARAMS_TXPOWER +#else +/* Parameters stored in eeprom */ +uint16_t params_get_nodeid(void); +uint8_t params_get_channel(void); +uint16_t params_get_panid(void); +uint16_t params_get_panaddr(void); +uint8_t params_get_txpower(void); +#endif + +#endif /* PARAMS_H_ */ diff --git a/platform/osd-merkur/slip_uart0.c b/platform/RaspBee/slip_uart0.c similarity index 100% rename from platform/osd-merkur/slip_uart0.c rename to platform/RaspBee/slip_uart0.c diff --git a/platform/apple2enh/Makefile.apple2enh b/platform/apple2enh/Makefile.apple2enh index b59c82e44..01734c6ea 100644 --- a/platform/apple2enh/Makefile.apple2enh +++ b/platform/apple2enh/Makefile.apple2enh @@ -55,14 +55,14 @@ endif disk: all cp $(CONTIKI)/tools/$(TARGET)/prodos.dsk contiki.dsk - java -jar $(AC) -p contiki.dsk contiki.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p contiki.dsk contiki.system sys < $(CC65_TARGET_DIR)/util/loader.system java -jar $(AC) -cc65 contiki.dsk contiki bin < $(CONTIKI_PROJECT).$(TARGET) java -jar $(AC) -p contiki.dsk contiki.cfg bin 0 < $(CONTIKI)/tools/$(TARGET)/sample.cfg java -jar $(AC) -p contiki.dsk cs8900a.eth rel 0 < cs8900a.eth java -jar $(AC) -p contiki.dsk lan91c96.eth rel 0 < lan91c96.eth java -jar $(AC) -p contiki.dsk w5100.eth rel 0 < w5100.eth ifeq ($(findstring WITH_MOUSE,$(DEFINES)),WITH_MOUSE) - java -jar $(AC) -p contiki.dsk contiki.mou rel 0 < $(CC65_HOME)/mou/a2e.stdmou.mou + java -jar $(AC) -p contiki.dsk contiki.mou rel 0 < $(CC65_TARGET_DIR)/drv/mou/a2e.stdmou.mou endif ifeq ($(HTTPD-CFS),1) java -jar $(AC) -p contiki.dsk index.htm bin 0 < httpd-cfs/index.htm diff --git a/platform/apple2enh/lib/pfs.S b/platform/apple2enh/lib/pfs.S index ed44dfc1e..5c2ac488c 100644 --- a/platform/apple2enh/lib/pfs.S +++ b/platform/apple2enh/lib/pfs.S @@ -66,7 +66,7 @@ read_count_out: .word $0000 ;TRANS_COUNT close_param: .byte $01 ;PARAM_COUNT close_fd: .byte $00 ;REF_NUM ;--------------------------------------------------------------------- - .segment "INIT" + .segment "ONCE" init_pfs: ; Allow exec() to keep file open diff --git a/platform/atarixl/Makefile.atarixl b/platform/atarixl/Makefile.atarixl index b6f103b88..64ade5a13 100644 --- a/platform/atarixl/Makefile.atarixl +++ b/platform/atarixl/Makefile.atarixl @@ -55,7 +55,7 @@ disk: all cp $(CONTIKI)/tools/$(TARGET)/sample.cfg atr/contiki.cfg cp cs8900a.eth atr/cs8900a.eth ifeq ($(findstring WITH_MOUSE,$(DEFINES)),WITH_MOUSE) - cp $(CC65_HOME)/mou/atrxst.mou atr/contiki.mou + cp $(CC65_TARGET_DIR)/drv/mou/atrxst.mou atr/contiki.mou endif ifeq ($(HTTPD-CFS),1) cp httpd-cfs/index.htm atr/index.htm diff --git a/platform/avr-atmega128rfa1/Makefile.avr-atmega128rfa1 b/platform/avr-atmega128rfa1/Makefile.avr-atmega128rfa1 index f99e85291..2fd8a9ac2 100644 --- a/platform/avr-atmega128rfa1/Makefile.avr-atmega128rfa1 +++ b/platform/avr-atmega128rfa1/Makefile.avr-atmega128rfa1 @@ -9,7 +9,7 @@ CONTIKI_TARGET_SOURCEFILES += button-sensor.c sensors.c slip_uart0.c slip.c CONTIKIAVR=$(CONTIKI)/cpu/avr CONTIKIBOARD=. -CONTIKI_PLAT_DEFS = -DF_CPU=8000000UL -DAUTO_CRC_PADDING=2 +CONTIKI_PLAT_DEFS = -DF_CPU=16000000UL -DAUTO_CRC_PADDING=2 MCU=atmega128rfa1 @@ -31,4 +31,4 @@ AVRDUDE_MCU=m128rfa1 include $(CONTIKIAVR)/Makefile.avr include $(CONTIKIAVR)/radio/Makefile.radio -MODULES += core/net/mac core/net core/net/mac/sicslowmac core/net/mac/contikimac +MODULES += core/net/mac core/net core/net/mac/sicslowmac core/net/mac/contikimac core/net/llsec diff --git a/platform/avr-atmega128rfa1/apps/raven-ipso/raven-ipso.c b/platform/avr-atmega128rfa1/apps/raven-ipso/raven-ipso.c index 214a64efe..04802951a 100644 --- a/platform/avr-atmega128rfa1/apps/raven-ipso/raven-ipso.c +++ b/platform/avr-atmega128rfa1/apps/raven-ipso/raven-ipso.c @@ -95,7 +95,7 @@ raven_ping6(void) /* ping ipv6.google.com*/ uip_ip6addr(&ping_addr,0x2001,0x420,0x5FFF,0x7D,0x2D0,0xB7FF,0xFE23,0xE6DB); //uip_ip6addr(&ping_addr, 0x2001, 0x4860, 0, 0x2001, 0, 0, 0, 0x68); - //uip_ip6addr(&ping_addr, 0xaaaa, 0, 0, 0, 0, 0, 0, 1); + //uip_ip6addr(&ping_addr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 1); UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 1; diff --git a/platform/avr-atmega128rfa1/contiki-conf.h b/platform/avr-atmega128rfa1/contiki-conf.h index 9dfbd9518..dddc6c81d 100644 --- a/platform/avr-atmega128rfa1/contiki-conf.h +++ b/platform/avr-atmega128rfa1/contiki-conf.h @@ -45,7 +45,7 @@ #define PLATFORM_NAME "RFA1" #define PLATFORM_TYPE ATMEGA128RFA1 #ifndef F_CPU -#define F_CPU 8000000UL +#define F_CPU 16000000UL #endif #include @@ -151,10 +151,10 @@ typedef unsigned short uip_stats_t; #define UIP_CONF_LLH_LEN 0 /* 10 bytes per stateful address context - see sicslowpan.c */ -/* Default is 1 context with prefix aaaa::/64 */ +/* Default is 1 context with prefix fd00::/64 */ /* These must agree with all the other nodes or there will be a failure to communicate! */ #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 1 -#define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=0xaa;addr_contexts[0].prefix[1]=0xaa;} +#define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=UIP_DS6_DEFAULT_PREFIX_0;addr_contexts[0].prefix[1]=UIP_DS6_DEFAULT_PREFIX_1;} #define SICSLOWPAN_CONF_ADDR_CONTEXT_1 {addr_contexts[1].prefix[0]=0xbb;addr_contexts[1].prefix[1]=0xbb;} #define SICSLOWPAN_CONF_ADDR_CONTEXT_2 {addr_contexts[2].prefix[0]=0x20;addr_contexts[2].prefix[1]=0x01;addr_contexts[2].prefix[2]=0x49;addr_contexts[2].prefix[3]=0x78,addr_contexts[2].prefix[4]=0x1d;addr_contexts[2].prefix[5]=0xb1;} diff --git a/platform/avr-atmega128rfa1/contiki-main.c b/platform/avr-atmega128rfa1/contiki-main.c index 8d2d8f9b7..ec22d58f6 100644 --- a/platform/avr-atmega128rfa1/contiki-main.c +++ b/platform/avr-atmega128rfa1/contiki-main.c @@ -340,7 +340,7 @@ uint8_t i; #if 0 { uip_ip6addr_t ipaddr; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); // uip_ds6_prefix_add(&ipaddr,64,0); } diff --git a/platform/avr-raven/apps/raven-ipso/raven-ipso.c b/platform/avr-raven/apps/raven-ipso/raven-ipso.c index 2b51ac519..5779e814b 100644 --- a/platform/avr-raven/apps/raven-ipso/raven-ipso.c +++ b/platform/avr-raven/apps/raven-ipso/raven-ipso.c @@ -95,7 +95,7 @@ raven_ping6(void) /* ping ipv6.google.com*/ uip_ip6addr(&ping_addr,0x2001,0x420,0x5FFF,0x7D,0x2D0,0xB7FF,0xFE23,0xE6DB); //uip_ip6addr(&ping_addr, 0x2001, 0x4860, 0, 0x2001, 0, 0, 0, 0x68); - //uip_ip6addr(&ping_addr, 0xaaaa, 0, 0, 0, 0, 0, 0, 1); + //uip_ip6addr(&ping_addr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 1); UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 1; diff --git a/platform/avr-raven/contiki-conf.h b/platform/avr-raven/contiki-conf.h index aa97db2e5..45ea5fb22 100644 --- a/platform/avr-raven/contiki-conf.h +++ b/platform/avr-raven/contiki-conf.h @@ -138,15 +138,12 @@ typedef unsigned short uip_stats_t; /* Network setup. The new NETSTACK interface requires RF230BB (as does ip4) */ #if RF230BB -#undef PACKETBUF_CONF_HDR_SIZE //Use the packetbuf default for header size /* TX routine passes the cca/ack result in the return parameter */ #define RDC_CONF_HARDWARE_ACK 1 /* TX routine does automatic cca and optional backoff */ #define RDC_CONF_HARDWARE_CSMA 1 /* Allow MCU sleeping between channel checks */ #define RDC_CONF_MCU_SLEEP 0 -#else -#define PACKETBUF_CONF_HDR_SIZE 0 //RF230 combined driver/mac handles headers internally #endif /*RF230BB */ #if NETSTACK_CONF_WITH_IPV6 @@ -167,10 +164,10 @@ typedef unsigned short uip_stats_t; #define UIP_CONF_LLH_LEN 0 /* 10 bytes per stateful address context - see sicslowpan.c */ -/* Default is 1 context with prefix aaaa::/64 */ +/* Default is 1 context with prefix fd00::/64 */ /* These must agree with all the other nodes or there will be a failure to communicate! */ #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 1 -#define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=0xaa;addr_contexts[0].prefix[1]=0xaa;} +#define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=UIP_DS6_DEFAULT_PREFIX_0;addr_contexts[0].prefix[1]=UIP_DS6_DEFAULT_PREFIX_1;} #define SICSLOWPAN_CONF_ADDR_CONTEXT_1 {addr_contexts[1].prefix[0]=0xbb;addr_contexts[1].prefix[1]=0xbb;} #define SICSLOWPAN_CONF_ADDR_CONTEXT_2 {addr_contexts[2].prefix[0]=0x20;addr_contexts[2].prefix[1]=0x01;addr_contexts[2].prefix[2]=0x49;addr_contexts[2].prefix[3]=0x78,addr_contexts[2].prefix[4]=0x1d;addr_contexts[2].prefix[5]=0xb1;} diff --git a/platform/avr-raven/contiki-raven-default-init-net.c b/platform/avr-raven/contiki-raven-default-init-net.c index 61fc23213..ca29e34fb 100644 --- a/platform/avr-raven/contiki-raven-default-init-net.c +++ b/platform/avr-raven/contiki-raven-default-init-net.c @@ -44,7 +44,7 @@ init_net(void) /* uip_ipaddr_t ipprefix; - uip_ip6addr(&ipprefix, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipprefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_netif_addr_add(&ipprefix, UIP_DEFAULT_PREFIX_LEN, 0, AUTOCONF); uip_nd6_prefix_add(&ipprefix, UIP_DEFAULT_PREFIX_LEN, 0); diff --git a/platform/avr-raven/contiki-raven-main.c b/platform/avr-raven/contiki-raven-main.c index 723bd9436..274bdf2ff 100644 --- a/platform/avr-raven/contiki-raven-main.c +++ b/platform/avr-raven/contiki-raven-main.c @@ -357,7 +357,7 @@ uint8_t i; #if 0 { uip_ip6addr_t ipaddr; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); // uip_ds6_prefix_add(&ipaddr,64,0); } diff --git a/platform/avr-ravenusb/Makefile.avr-ravenusb b/platform/avr-ravenusb/Makefile.avr-ravenusb index b6301b329..6c702a261 100644 --- a/platform/avr-ravenusb/Makefile.avr-ravenusb +++ b/platform/avr-ravenusb/Makefile.avr-ravenusb @@ -71,5 +71,5 @@ MODULES+=core/net/mac core/net/mac/sicslowmac \ core/net/llsec else vpath %.c $(CONTIKI)/core/net/ipv6 -CONTIKI_SOURCEFILES += sicslowpan.c linkaddr.c +CONTIKI_SOURCEFILES += sicslowpan.c linkaddr.c link-stats.c nbr-table.c endif diff --git a/platform/avr-ravenusb/cdc_task.c b/platform/avr-ravenusb/cdc_task.c index 8caabc772..de30d8d65 100644 --- a/platform/avr-ravenusb/cdc_task.c +++ b/platform/avr-ravenusb/cdc_task.c @@ -611,7 +611,7 @@ extern uip_ds6_netif_t uip_ds6_if; uip_ds6_route_t *route; for(route = uip_ds6_route_head(); route != NULL; - route = uip_ds6_route_next(r)) { + route = uip_ds6_route_next(route)) { ipaddr_add(&route->ipaddr); PRINTF_P(PSTR("/%u (via "), route->length); ipaddr_add(uip_ds6_route_nexthop(route)); diff --git a/platform/avr-ravenusb/contiki-conf.h b/platform/avr-ravenusb/contiki-conf.h index c6cab8c54..8eab7cce9 100644 --- a/platform/avr-ravenusb/contiki-conf.h +++ b/platform/avr-ravenusb/contiki-conf.h @@ -204,11 +204,6 @@ extern void mac_log_802_15_4_rx(const uint8_t* buffer, size_t total_len); /* Network setup. The new NETSTACK interface requires RF230BB (as does ip4) */ /* These mostly have no effect when the Jackdaw is a repeater (CONTIKI_NO_NET=1 using fakeuip.c) */ -#if RF230BB -#else -#define PACKETBUF_CONF_HDR_SIZE 0 //RF230 combined driver/mac handles headers internally -#endif /*RF230BB */ - #if NETSTACK_CONF_WITH_IPV6 #define LINKADDR_CONF_SIZE 8 #define UIP_CONF_ICMP6 1 @@ -236,10 +231,10 @@ extern void mac_log_802_15_4_rx(const uint8_t* buffer, size_t total_len); #define UIP_CONF_BUFSIZE UIP_LINK_MTU + UIP_LLH_LEN + 4 /* +4 for vlan on macosx */ /* 10 bytes per stateful address context - see sicslowpan.c */ -/* Default is 1 context with prefix aaaa::/64 */ +/* Default is 1 context with prefix fd00::/64 */ /* These must agree with all the other nodes or there will be a failure to communicate! */ #//define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 1 -#define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=0xaa;addr_contexts[0].prefix[1]=0xaa;} +#define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=UIP_DS6_DEFAULT_PREFIX_0;addr_contexts[0].prefix[1]=UIP_DS6_DEFAULT_PREFIX_1;} #define SICSLOWPAN_CONF_ADDR_CONTEXT_1 {addr_contexts[1].prefix[0]=0xbb;addr_contexts[1].prefix[1]=0xbb;} #define SICSLOWPAN_CONF_ADDR_CONTEXT_2 {addr_contexts[2].prefix[0]=0x20;addr_contexts[2].prefix[1]=0x01;addr_contexts[2].prefix[2]=0x49;addr_contexts[2].prefix[3]=0x78,addr_contexts[2].prefix[4]=0x1d;addr_contexts[2].prefix[5]=0xb1;} diff --git a/platform/avr-rcb/contiki-conf.h b/platform/avr-rcb/contiki-conf.h index 298a33cd0..68ce8f3b6 100644 --- a/platform/avr-rcb/contiki-conf.h +++ b/platform/avr-rcb/contiki-conf.h @@ -85,7 +85,6 @@ void clock_adjust_ticks(clock_time_t howmany); #define CLIF #define LINKADDR_CONF_SIZE 8 -#define PACKETBUF_CONF_HDR_SIZE 48 /* Choose a buffersize != 0 for the messages which should be sended over the wireless interface */ /* Uncomment this lines to activate the specific drivers */ //#define NETSTACK_CONF_NETWORK rime_driver diff --git a/platform/avr-rss2/Makefile.avr-rss2 b/platform/avr-rss2/Makefile.avr-rss2 new file mode 100644 index 000000000..2655b8b4a --- /dev/null +++ b/platform/avr-rss2/Makefile.avr-rss2 @@ -0,0 +1,61 @@ +CONTIKI_TARGET_DIRS = . apps net loader dev + +CONTIKI_CORE=contiki-main +CONTIKI_TARGET_MAIN = ${CONTIKI_CORE}.o +CONTIKI_TARGET_SOURCEFILES += contiki-main.c params.c battery-sensor.c i2c.c + +CONTIKI_TARGET_SOURCEFILES += sensors.c button-sensor.c slip_uart0.c slip.c leds.c temp_mcu-sensor.c light-sensor.c adc.c cfs-eeprom.c eeprom.c pulse-sensor.c + +CONTIKI_TARGET_SOURCEFILES += temp-sensor.c + +CONTIKI_TARGET_SOURCEFILES += enc28j60_avr.c +CONTIKI_TARGET_SOURCEFILES += co2_sa_kxx-sensor.c + +CONTIKIAVR=$(CONTIKI)/cpu/avr +CONTIKIBOARD=. + + +ifdef $(MCU) +MCU=$(MCU) +else +MCU=atmega256rfr2 +endif + +ifeq ($(MCU),atmega128rfa1) +CONTIKI_PLAT_DEFS = -DF_CPU=8000000UL -DAUTO_CRC_PADDING=2 +BOOTLOADER_START = 0x1E000 +endif + +ifeq ($(MCU),atmega128rfr2) +CONTIKI_PLAT_DEFS = -DF_CPU=8000000UL -DAUTO_CRC_PADDING=2 +BOOTLOADER_START = 0x1E000 +endif + +ifeq ($(MCU),atmega256rfr2) +CONTIKI_PLAT_DEFS = -DF_CPU=16000000UL -DAUTO_CRC_PADDING=2 +BOOTLOADER_START = 0x3E000 +endif + +AVRDUDE_PROGRAMMER=jtag2 + +# For usb devices, you may either use PORT=usb, or (e.g. if you have more than one +# programmer connected) you can use the following trick to find out the serial number: +# +# The example is for an JTAGICE mkII used to program an ATmega128: +# avrdude -v -P usb:xxxx -c jtag2 -p atmega128 +AVRDUDE_PORT=usb:00B000000D79 + +# Additional avrdude options +# Verify off +AVRDUDE_OPTIONS=-V +AVRDUDE_MCU=m256rfr2 + +include $(CONTIKIAVR)/Makefile.avr +include $(CONTIKIAVR)/radio/Makefile.radio + +#MODULES += core/net/mac core/net core/net/mac/sicslowmac core/net/mac/contikimac core/net/llsec core/net/rime + +MODULES += core/net/mac core/net core/net/mac/sicslowmac core/net/mac/contikimac core/net/llsec + + + diff --git a/platform/avr-rss2/README.md b/platform/avr-rss2/README.md new file mode 100644 index 000000000..05d448fc6 --- /dev/null +++ b/platform/avr-rss2/README.md @@ -0,0 +1,175 @@ +Getting Started with Contiki using avr-rss2 +=========================================== +This guide's aim is to help you start using Contiki for RSS2 boards +The platform supports different AtMega-RF boards: + +* Based on MCU AtMega128RFR2 +* Based on MCU AtMega256RFR2 +* Based on MCU AtMega128RFA1 + +Boards all looks the same. AtMega256RFR2 boards are labeled with "Made in EU". +The platform and CPU code, are common for both boards, can be found under +`$(CONTIKI)/platfrom/avr-rssa`. The port was developed and tested with RSS2. +This guide assumes that you have basic understanding of how to use the +command line and perform basic admin tasks on UNIX family OSs. You should +also have understanding about the Contiki OS design as well have C +programming skills. + +Board Features +---------------- +* Chip Antenna. Supercardiod. +* Robust radio performance. Up to 300 meter line-of-sight. +* Unique EUI64 address via chip combined with EEPROM +* Onboard temp sensor DS18B20, +* Light Sensor. +* 32kHz RTC xtal +* Comparator chip and input. +* SW FET, (relay) for power on/off of sensors. +* DC input via LDO up to 25V. +* Standard. 6-pin TTL-USB header for FTDI cable for UART. +* PCB formfactor for cheap project box G.40X IP54 +* Power/current: + * RX ~10mA (Full RPC AtMegaXXRFR2). + * Sleep ~45uA @ 16MHz XTAL + * Sleep ~15uA @ 8MHz using internal oscillator +* Preprogammed bootloader. +* CE certified by test institute. + +UART +---- +The board has one UART via the 6-pin TTL-USB adapter, The recommended +baudrate is 38400 bps. This speed gives the lowest error with respect +of the used clock frequency used internally. A possible hi-speed is +250000 bps wich gives 0% Error with 16MHz clock. + +Port Features +-------------- +The platform has the following key features: +* Standard, E64 address from built-in chip. +* First hooks for RPC (Reduced Power Consumption) for AtMegaXXXRFR2. + +Toolchain needs +--------------- +The Atmel toolcahin is available in most operating system. +Note. The native OS packages does not yet support the new +AtMega256RfR2 MCU. + +We'll use toolchain from Atmels web-site. You might also consider +Instant Contiki. + + +###### For Linux + +1. See http://www.atmel.com/tools/ATMELAVRTOOLCHAINFORLINUX.aspx +2. Download the proper 8-bit platform 32 or 64 bit. +3. Unpack under `/usr/local` +4. Add to your search PATH. For example add to `.bashrc`: `export PATH=$PATH:/usr/local/avr8-gnu-toolchain-linux_x86_64/bin` (for 64 bit systems) or `export PATH=$PATH:/usr/local/avr8-gnu-toolchain-linux_x86/bin` (for 32 birt systems). +5. For flash programming you'll need `avrdude`. It can be installed with the command +`apt-get install avrdude` + +###### For Windows + +Goes here + +Contiki build TARGET +-------------------- + make TARGET=avr-rss2 + +For AtMega128RFR2 boards: + + make TARGET=avr-rss2 MCU=atmega128rfr2 + +For AtMega128RFA1 boards: + + make TARGET=avr-rss2 MCU=atmega128rfa1 + +Flashing +-------- +Programming using avrdude using serial bootloader. (TTL-USB cable) +Press the RESET button. The bootloader with wait for boot commands +for 3 seconds. + +Flashing commnad line example 256k MCU: + + avrdude -p m256rfr2 -c stk500v2 -P /dev/ttyUSB0 -b 38400 -e -U flash:w:hello-world.avr-rss2 + +Flashing commnad line example 128k MCU: + + avrdude -p m128rfa1 -c avr109 -P /dev/ttyUSB0 -b 38400 -e -U flash:w:hello-world.avr-rss2 + +Older boards may use the avr109 boot loader. The `stk500v2` uses the yellow +lED while the avr109 uses the red LED. + +Tested applications and examples +--------------------------------- +* `hello-world` +* `ipv6/rpl-udp` +* `ipv6/simple-udp-rpl` +* `rime` +* `ipv6/multicast` +* `examples/powertrace` +* `example-shell` + +Note that the shell example needs file `symbols.c` to be added to project also seems like +in `core/dev/serial-line.c` the function `process_poll` must be replaced with `process_post`: + + /* Wake up consumer process */ + - process_poll(&serial_line_process); + + process_post(&serial_line_process, 0, 0); + + +Platform tutorial applications +----------------------------- +Example to read out various sensors, leds, serial numbers, and so on: +[platform/avr-rss2/examples/hello-sensors/](examples/hello-sensors/). + +The previous example uses the `sensd` data encoding. An example that uses UDP through 6lowpan is here: +[platform/avr-rss2/examples/ipv6/rpl-udp-report](examples/ipv6/rpl-udp-report). + +An Ethernet gateway with ip64 NAT, based on Contiki `core/net/ip64` code: +[platform/avr-rss2/examples/ipv6/rpl-border-router/](examples/ipv6/rpl-border-router/). + +Regressions tests +----------------- +Travis compile regression test for the platform: +[regression-tests/23-compile-avr](../../regression-tests/23-compile-avr). + +This port adds newer version of `avr-gcc` compiler (4.9.2), to support +testing of newer Atmel MCU as Atmega256RFR2. + + +Board approvals +--------------- +Summary: +* R&TTE 73/23/EEC, 89/336/EEC and 99/5/EC +* Safety: EN 60950-1:2006 + A12: 2011 +* RF: ETSI EN 300 328 V1.7.1 (2006-10) +* EMC: ETSI EN 301 489-1 V1.9.2 (2011-09), ETSI EN 301 489-17 V2.2.1 (2012-09) +* EMF: EN 62479:2010 +* Human exposure to electromagnetic fields: EN 62479:2010 + +Commercial availability +------------------------ +Through vendor and though resellers. Note board is will only available +were CE approval is covered. This may be further restricted by WEEE. +Contact vendor. For research legislation is more relaxed in most +countries. + +References +---------- +AtMega64/128/256/RFR2 chip documentation available via Atmel. +Schematics and boards description. Available via Radio-Senors +Smart Reduced Power Consumption Techniques. AT02594 available via Atmel. + +ToDo +----- +API for radio power saving settings introduced Atmels app note AT02594. +Also function for the desensitizing RPC resister. + +Vendor info +----------- +http://radio-sensors.com/ + +Maintainer +---------- +Robert Olsson diff --git a/platform/avr-rss2/apps/sniffer/Makefile b/platform/avr-rss2/apps/sniffer/Makefile new file mode 100644 index 000000000..63412a817 --- /dev/null +++ b/platform/avr-rss2/apps/sniffer/Makefile @@ -0,0 +1,11 @@ +DEFINES+=PROJECT_CONF_H=\"project-conf.h\" +PROJECT_SOURCEFILES += stub-rdc.c + +CONTIKI_PROJECT = sniffer + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../../.. + +CONTIKI_WITH_RIME = 1 +include $(CONTIKI)/Makefile.include diff --git a/platform/avr-rss2/apps/sniffer/README.md b/platform/avr-rss2/apps/sniffer/README.md new file mode 100644 index 000000000..b9332893b --- /dev/null +++ b/platform/avr-rss2/apps/sniffer/README.md @@ -0,0 +1,29 @@ +Sniffer application mote side +============================= +This put the radio in sniff mode and should capure all traffic used +on the set channel. + +Default channel +--------------- +26 + +Bulld +----- +make TARGET=avr-rss2 + +Default serial port speed +------------------------- +38400 bps + +More info & uasage +------------------ +Look in the host directory + +Contiki support +--------------- +The code promisc for support is needed. This also adds the sensniff +format. + +References +---------- +https://github.com/g-oikonomou/sensniff diff --git a/platform/avr-rss2/apps/sniffer/project-conf.h b/platform/avr-rss2/apps/sniffer/project-conf.h new file mode 100644 index 000000000..d56b19e7d --- /dev/null +++ b/platform/avr-rss2/apps/sniffer/project-conf.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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 + * Project specific configuration defines for the sniffer example. + * + * \author + * George Oikonomou - + * Robert Olsson - + */ + +#ifndef PROJECT_CONF_H_ +#define PROJECT_CONF_H_ + + +#define NETSTACK_CONF_MAC nullmac_driver +/* Can see other channels. Interesting. */ +/* #define NETSTACK_CONF_MAC csma_driver */ +#define NETSTACK_CONF_RDC stub_rdc_driver + + +#endif /* PROJECT_CONF_H_ */ diff --git a/platform/avr-rss2/apps/sniffer/sniffer-example-coap.pcapng b/platform/avr-rss2/apps/sniffer/sniffer-example-coap.pcapng new file mode 100644 index 000000000..e69de29bb diff --git a/platform/avr-rss2/apps/sniffer/sniffer.c b/platform/avr-rss2/apps/sniffer/sniffer.c new file mode 100644 index 000000000..be572bce1 --- /dev/null +++ b/platform/avr-rss2/apps/sniffer/sniffer.c @@ -0,0 +1,67 @@ +/* + * 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. + * + */ + +/* + Author: Robert Olsson +*/ + +#include "contiki.h" +#include "net/rime/rime.h" +#include "random.h" +#include "dev/button-sensor.h" +#include "dev/leds.h" +#include +/*---------------------------------------------------------------------------*/ + +PROCESS(sniffer_process, "Sniffer process"); +AUTOSTART_PROCESSES(&sniffer_process); + +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(sniffer_process, ev, data) +{ + PROCESS_BEGIN(); + + /* + To get rf230bb radio in sniff mode we need to have radio in RX_ON. + The promisc commands fixes this for us. No need to set PAN and + address or MAC to zero is this case. Se Atmel datasheet. There is + a chance other radios works the same way. + */ + + rf230_set_promiscuous_mode(1); + + printf("Sniffer started\n"); + + while(1) { + PROCESS_YIELD(); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/avr-rss2/apps/sniffer/stub-rdc.c b/platform/avr-rss2/apps/sniffer/stub-rdc.c new file mode 100644 index 000000000..a4db0710d --- /dev/null +++ b/platform/avr-rss2/apps/sniffer/stub-rdc.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. 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 + * Definition of a fake RDC driver to be used with passive + * examples. The sniffer will never send packets and it will never + * push incoming packets up the stack. We do this by defining this + * driver as our RDC. We then drop everything + * + * \author + * George Oikonomou - + */ + +#include "net/mac/mac.h" +#include "net/mac/rdc.h" +/*---------------------------------------------------------------------------*/ +static void +send(mac_callback_t sent, void *ptr) +{ + if(sent) { + sent(ptr, MAC_TX_OK, 1); + } +} +/*---------------------------------------------------------------------------*/ +static void +send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *list) +{ + if(sent) { + sent(ptr, MAC_TX_OK, 1); + } +} +/*---------------------------------------------------------------------------*/ +static void +input(void) +{ +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +off(int keep_radio_on) +{ + return keep_radio_on; +} +/*---------------------------------------------------------------------------*/ +static unsigned short +cca(void) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ +} +/*---------------------------------------------------------------------------*/ +const struct rdc_driver stub_rdc_driver = { + "stub-rdc", + init, + send, + send_list, + input, + on, + off, + cca, +}; +/*---------------------------------------------------------------------------*/ diff --git a/platform/avr-rss2/contiki-conf.h b/platform/avr-rss2/contiki-conf.h new file mode 100644 index 000000000..3e1f5dfc2 --- /dev/null +++ b/platform/avr-rss2/contiki-conf.h @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2006, Technical University of Munich + * 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 + * Configuration for RSS2 (radio-sensors.com) platform + */ + +#ifndef CONTIKI_CONF_H_ +#define CONTIKI_CONF_H_ + +/* include the project config */ +/* PROJECT_CONF_H might be defined in the project Makefile */ +#ifdef PROJECT_CONF_H +#include PROJECT_CONF_H +#endif + +/* Platform name, type, and MCU clock rate */ +#define PLATFORM_NAME "rss2" +#define PLATFORM_TYPE ATMEGA256RFR2 +#ifndef F_CPU +#define F_CPU 8000000UL +#endif + +#include + +#ifndef NETSTACK_CONF_MAC +#define NETSTACK_CONF_MAC csma_driver +#endif + +#ifndef NETSTACK_CONF_RDC +#define NETSTACK_CONF_RDC contikimac_driver +#endif + +#ifndef NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE +#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8 +#endif + +#ifndef NETSTACK_CONF_FRAMER +#if NETSTACK_CONF_WITH_IPV6 +#define NETSTACK_CONF_FRAMER contikimac_framer +#else +#define NETSTACK_CONF_FRAMER framer_802154 +#endif +#endif + +#ifndef NETSTACK_CONF_RADIO +#define NETSTACK_CONF_RADIO rf230_driver +#endif + +#ifndef CHANNEL_802_15_4 +#define CHANNEL_802_15_4 26 +#endif + +/* AUTOACK receive mode gives better rssi measurements, even if ACK is never requested */ +#ifndef RF230_CONF_AUTOACK +#define RF230_CONF_AUTOACK 1 +#endif + +#define MCUCSR MCUSR + +/* The AVR tick interrupt usually is done with an 8 bit counter around 128 Hz. + * 125 Hz needs slightly more overhead during the interrupt, as does a 32 bit + * clock_time_t. + */ +/* Clock ticks per second */ + +#define CLOCK_CONF_SECOND 128 +typedef unsigned long clock_time_t; +#define CLOCK_LT(a, b) ((signed long)((a) - (b)) < 0) +#define INFINITE_TIME 0xffffffff +/* These routines are not part of the contiki core but can be enabled in cpu/avr/clock.c */ +void clock_delay_msec(uint16_t howlong); +void clock_adjust_ticks(clock_time_t howmany); + +/* The radio needs to interrupt during an rtimer interrupt */ +#define RTIMER_CONF_NESTED_INTERRUPTS 1 + +/* RSS2 boards has a 32768Hz on TIMER2 */ +#define AVR_CONF_USE32KCRYSTAL 1 +#define SLIP_PORT RS232_PORT_0 + +/* Pre-allocated memory for loadable modules heap space (in bytes)*/ +/* Default is 4096. Currently used only when elfloader is present. Not tested on Raven */ +/* #define MMEM_CONF_SIZE 256 */ + +/* Starting address for code received via the codeprop facility. Not tested. */ +typedef unsigned long off_t; +/* #define EEPROMFS_ADDR_CODEPROP 0x8000 */ + +/* Logging adds 200 bytes to program size. RS232 output slows down webserver. */ +/* #define LOG_CONF_ENABLED 1 */ + +/* RADIOSTATS is used in rf230bb, clock.c and the webserver cgi to report radio usage */ +/* It has less overhead than ENERGEST */ +#define RADIOSTATS 1 + +/* More extensive stats, via main loop printfs or webserver status pages */ +#define ENERGEST_CONF_ON 1 + +/* Packet statistics */ +typedef unsigned short uip_stats_t; +#define UIP_STATISTICS 0 + +/* Available watchdog timeouts depend on mcu. Default is WDTO_2S. -1 Disables the watchdog. */ +/* AVR Studio simulator tends to reboot due to clocking the WD 8 times too fast */ +/* #define WATCHDOG_CONF_TIMEOUT -1 */ + +/* Debugflow macro, useful for tracing path through mac and radio interrupts */ +/* #define DEBUGFLOWSIZE 128 */ + +/* Define MAX_*X_POWER to reduce tx power and ignore weak rx packets for testing a miniature multihop network. + * Leave undefined for full power and sensitivity. + * tx=0 (3dbm, default) to 15 (-17.2dbm) + * RF230_CONF_AUTOACK sets the extended mode using the energy-detect register with rx=0 (-91dBm) to 84 (-7dBm) + * else the rssi register is used having range 0 (91dBm) to 28 (-10dBm) + * For simplicity RF230_MIN_RX_POWER is based on the energy-detect value and divided by 3 when autoack is not set. + * On the RF230 a reduced rx power threshold will not prevent autoack if enabled and requested. + * These numbers applied to both Raven and Jackdaw give a maximum communication distance of about 15 cm + * and a 10 meter range to a full-sensitivity RF230 sniffer. + *#define RF230_MAX_TX_POWER 15 + *#define RF230_MIN_RX_POWER 30 + */ +/* The rf231 and atmega128rfa1 can use an rssi threshold for triggering rx_busy that saves 0.5ma in rx mode */ +/* 1 - 15 maps into -90 to -48 dBm; the register is written with RF230_MIN_RX_POWER/6 + 1. Undefine for -100dBm sensitivity */ +/* #define RF230_MIN_RX_POWER 0 */ + +/* Network setup */ +/* TX routine passes the cca/ack result in the return parameter */ +#define RDC_CONF_HARDWARE_ACK 1 +/* TX routine does automatic cca and optional backoffs */ +#define RDC_CONF_HARDWARE_CSMA 1 +/* Allow MCU sleeping between channel checks */ +#define RDC_CONF_MCU_SLEEP 1 + +#if NETSTACK_CONF_WITH_IPV6 +#define LINKADDR_CONF_SIZE 8 +#define UIP_CONF_ICMP6 1 +#define UIP_CONF_UDP 1 +#ifndef UIP_CONF_TCP +#define UIP_CONF_TCP 1 +#endif +#define NETSTACK_CONF_NETWORK sicslowpan_driver +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 +#else +/* ip4 should build but is largely untested */ +#define LINKADDR_CONF_SIZE 2 +#define NETSTACK_CONF_NETWORK rime_driver +#endif + +#define UIP_CONF_LL_802154 1 +#define UIP_CONF_LLH_LEN 0 + +/* 10 bytes per stateful address context - see sicslowpan.c */ +/* Default is 1 context with prefix aaaa::/64 */ +/* These must agree with all the other nodes or there will be a failure to communicate! */ +#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 1 +#define SICSLOWPAN_CONF_ADDR_CONTEXT_0 { addr_contexts[0].prefix[0] = 0xaa; addr_contexts[0].prefix[1] = 0xaa; } +#define SICSLOWPAN_CONF_ADDR_CONTEXT_1 { addr_contexts[1].prefix[0] = 0xbb; addr_contexts[1].prefix[1] = 0xbb; } +#define SICSLOWPAN_CONF_ADDR_CONTEXT_2 { addr_contexts[2].prefix[0] = 0x20; addr_contexts[2].prefix[1] = 0x01; addr_contexts[2].prefix[2] = 0x49; addr_contexts[2].prefix[3] = 0x78, addr_contexts[2].prefix[4] = 0x1d; addr_contexts[2].prefix[5] = 0xb1; } + +/* Take the default TCP maximum segment size for efficiency and simpler wireshark captures */ +/* Use this to prevent 6LowPAN fragmentation (whether or not fragmentation is enabled) */ +/* #define UIP_CONF_TCP_MSS 48 */ + +#define UIP_CONF_IP_FORWARD 0 +#define UIP_CONF_FWCACHE_SIZE 0 + +#define UIP_CONF_IPV6_CHECKS 1 +#define UIP_CONF_IPV6_QUEUE_PKT 1 +#define UIP_CONF_IPV6_REASSEMBLY 0 + +#define UIP_CONF_UDP_CHECKSUMS 1 +#define UIP_CONF_TCP_SPLIT 1 +#define UIP_CONF_DHCP_LIGHT 1 + +#if 0 /* No radio cycling */ + +#define NETSTACK_CONF_MAC nullmac_driver +#define NETSTACK_CONF_RDC sicslowmac_driver +#define NETSTACK_CONF_FRAMER framer_802154 +/* 1 + Number of auto retry attempts 0-15 (0 implies don't use extended TX_ARET_ON mode) */ +#define RF230_CONF_FRAME_RETRIES 2 +/* Number of csma retry attempts 0-5 in extended tx mode (7 does immediate tx with no csma) */ +#define RF230_CONF_CSMA_RETRIES 5 +/* Default is one RAM buffer for received packets. More than one may benefit multiple TCP connections or ports */ +#define RF230_CONF_RX_BUFFERS 3 +#define SICSLOWPAN_CONF_FRAG 1 +/* Most browsers reissue GETs after 3 seconds which stops fragment reassembly so a longer MAXAGE does no good */ +#define SICSLOWPAN_CONF_MAXAGE 3 +/* How long to wait before terminating an idle TCP connection. Smaller to allow faster sleep. Default is 120 seconds */ +/* If wait is too short the connection can be reset as a result of multiple fragment reassembly timeouts */ +#define UIP_CONF_WAIT_TIMEOUT 20 +/* 54 bytes per queue ref buffer */ +#define QUEUEBUF_CONF_REF_NUM 2 +/* Allocate remaining RAM as desired */ +/* 30 bytes per TCP connection */ +/* 6LoWPAN does not do well with concurrent TCP streams, as new browser GETs collide with packets coming */ +/* from previous GETs, causing decreased throughput, retransmissions, and timeouts. Increase to study this. */ +/* ACKs to other ports become interleaved with computation-intensive GETs, so ACKs are particularly missed. */ +/* Increasing the number of packet receive buffers in RAM helps to keep ACKs from being lost */ +#define UIP_CONF_MAX_CONNECTIONS 4 +/* 2 bytes per TCP listening port */ +#define UIP_CONF_MAX_LISTENPORTS 4 +/* 25 bytes per UDP connection */ +#define UIP_CONF_UDP_CONNS 10 +/* See uip-ds6.h */ +#define NBR_TABLE_CONF_MAX_NEIGHBORS 20 +#define UIP_CONF_DS6_DEFRT_NBU 2 +#define UIP_CONF_DS6_PREFIX_NBU 3 +#define UIP_CONF_MAX_ROUTES 20 +#define UIP_CONF_DS6_ADDR_NBU 3 +#define UIP_CONF_DS6_MADDR_NBU 0 +#define UIP_CONF_DS6_AADDR_NBU 0 + +#elif 1 /* Contiki-mac radio cycling */ +/* #define NETSTACK_CONF_MAC nullmac_driver */ +/* csma needed for burst mode at present. Webserver won't work without it */ +/* #define NETSTACK_CONF_MAC csma_driver */ +/* #define NETSTACK_CONF_RDC contikimac_driver */ +/* Default is two CCA separated by 500 usec */ + +/* So without the header this needed for RPL mesh to form */ +#define CONTIKIMAC_FRAMER_CONF_SHORTEST_PACKET_SIZE (43 - 18) /* multicast RPL DIS length */ +/* Not tested much yet */ +#define CONTIKIMAC_CONF_WITH_PHASE_OPTIMIZATION 0 +#define CONTIKIMAC_CONF_COMPOWER 1 +#define RIMESTATS_CONF_ENABLED 0 + +/* A 0 here means non-extended mode; 1 means extended mode with no retry, >1 for retrys */ +/* Contikimac strobes on its own, but hardware retries are faster */ +#define RF230_CONF_FRAME_RETRIES 1 +/* Long csma backoffs will compromise radio cycling; set to 0 for 1 csma */ +#define RF230_CONF_CSMA_RETRIES 0 +#define SICSLOWPAN_CONF_FRAG 1 +#define SICSLOWPAN_CONF_MAXAGE 3 +/* 54 bytes per queue ref buffer */ +#define QUEUEBUF_CONF_REF_NUM 2 +/* Allocate remaining RAM. Not much left due to queuebuf increase */ +#define UIP_CONF_MAX_CONNECTIONS 2 +#define UIP_CONF_MAX_LISTENPORTS 4 +#define UIP_CONF_UDP_CONNS 5 +#define NBR_TABLE_CONF_MAX_NEIGHBORS 20 +#define UIP_CONF_DS6_DEFRT_NBU 2 +#define UIP_CONF_DS6_PREFIX_NBU 3 +#define UIP_CONF_MAX_ROUTES 4 +#define UIP_CONF_DS6_ADDR_NBU 3 +#define UIP_CONF_DS6_MADDR_NBU 0 +#define UIP_CONF_DS6_AADDR_NBU 0 + +#elif 0 /* cx-mac radio cycling */ +/* RF230 does clear-channel assessment in extended mode (autoretries>0) */ +/* These values are guesses */ +#define RF230_CONF_FRAME_RETRIES 10 +#define RF230_CONF_CSMA_RETRIES 2 +#if RF230_CONF_CSMA_RETRIES +#define NETSTACK_CONF_MAC nullmac_driver +#else +#define NETSTACK_CONF_MAC csma_driver +#endif +#define NETSTACK_CONF_RDC cxmac_driver +#define NETSTACK_CONF_FRAMER framer_802154 +#define SICSLOWPAN_CONF_FRAG 1 +#define SICSLOWPAN_CONF_MAXAGE 3 +#define CXMAC_CONF_ANNOUNCEMENTS 0 +/* 54 bytes per queue ref buffer */ +#define QUEUEBUF_CONF_REF_NUM 2 +/* Allocate remaining RAM. Not much left due to queuebuf increase */ +#define UIP_CONF_MAX_CONNECTIONS 2 +#define UIP_CONF_MAX_LISTENPORTS 4 +#define UIP_CONF_UDP_CONNS 5 +#define NBR_TABLE_CONF_MAX_NEIGHBORS 4 +#define UIP_CONF_DS6_DEFRT_NBU 2 +#define UIP_CONF_DS6_PREFIX_NBU 3 +#define UIP_CONF_MAX_ROUTES 4 +#define UIP_CONF_DS6_ADDR_NBU 3 +#define UIP_CONF_DS6_MADDR_NBU 0 +#define UIP_CONF_DS6_AADDR_NBU 0 +/* Below gives 10% duty cycle, undef for default 5% */ +/* #define CXMAC_CONF_ON_TIME (RTIMER_ARCH_SECOND / 80) */ +/* Below gives 50% duty cycle */ +/* #define CXMAC_CONF_ON_TIME (RTIMER_ARCH_SECOND / 16) */ + +#else +/* #error Network configuration not specified! */ +#endif /* Network setup */ + +#ifndef QUEUEBUF_CONF_NUM +#define QUEUEBUF_CONF_NUM 15 +#endif + +/* ************************************************************************** */ +/* #pragma mark RPL Settings */ +/* ************************************************************************** */ +#if UIP_CONF_IPV6_RPL + +#define UIP_CONF_ROUTER 1 +#define UIP_CONF_ND6_SEND_RA 0 +#define UIP_CONF_ND6_REACHABLE_TIME 600000 +#define UIP_CONF_ND6_RETRANS_TIMER 10000 + +/* For slow slip connections, to prevent buffer overruns */ +/* #define UIP_CONF_RECEIVE_WINDOW 300 */ +#undef UIP_CONF_FWCACHE_SIZE +#define UIP_CONF_BUFFER_SIZE 600 /* DHCPv4 packets by ip64 module */ +#define UIP_CONF_FWCACHE_SIZE 30 +#define UIP_CONF_BROADCAST 1 +#define UIP_ARCH_IPCHKSUM 1 +#define UIP_CONF_PINGADDRCONF 0 +#define UIP_CONF_LOGGING 0 + +#endif /* RPL */ + +#define CCIF +#define CLIF +#ifndef CC_CONF_INLINE +#define CC_CONF_INLINE inline +#endif + +#endif /* CONTIKI_CONF_H_ */ diff --git a/platform/avr-rss2/contiki-main.c b/platform/avr-rss2/contiki-main.c new file mode 100644 index 000000000..8abac4d04 --- /dev/null +++ b/platform/avr-rss2/contiki-main.c @@ -0,0 +1,640 @@ +/* + * Copyright (c) 2006, Technical University of Munich + * 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. + * + * Reworked for avr-rss2 platform. Robert Olsson + */ + +#define PRINTF(FORMAT, args ...) printf_P(PSTR(FORMAT),##args) + +#define ANNOUNCE_BOOT 1 /* adds about 600 bytes to program size */ +#if ANNOUNCE_BOOT +#define PRINTA(FORMAT, args ...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTA(...) +#endif + +#define DEBUG 0 +#if DEBUG +#define PRINTD(FORMAT, args ...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTD(...) +#endif + +#include +#include +#include +#include +#include +#include + +#include "loader/symbols-def.h" +#include "loader/symtab.h" + +#include "params.h" +#include "rss2.h" +#include "leds.h" +#include "i2c.h" +#include "radio/rf230bb/rf230bb.h" +#include "net/mac/frame802154.h" +#include "net/mac/framer-802154.h" +#include "net/ipv6/sicslowpan.h" + +#include "contiki.h" +#include "contiki-net.h" +#include "contiki-lib.h" + +#include "dev/rs232.h" +#include "dev/serial-line.h" +#include "dev/slip.h" + +#if AVR_WEBSERVER +#include "httpd-fs.h" +#include "httpd-cgi.h" +#endif + +#ifdef COFFEE_FILES +#include "cfs/cfs.h" +#include "cfs/cfs-coffee.h" +#endif + +#if UIP_CONF_ROUTER && 0 +#include "net/routing/rimeroute.h" +#include "net/rime/rime-udp.h" +#endif + +#include "net/rime/rime.h" + +/* Track interrupt flow through mac, rdc and radio driver */ +/* #define DEBUGFLOWSIZE 32 */ +#if DEBUGFLOWSIZE +uint8_t debugflowsize, debugflow[DEBUGFLOWSIZE]; +#define DEBUGFLOW(c) if(debugflowsize < (DEBUGFLOWSIZE - 1)) debugflow[debugflowsize++] = c +#else +#define DEBUGFLOW(c) +#endif + +/* Get periodic prints from idle loop, from clock seconds or rtimer interrupts */ +/* Use of rtimer will conflict with other rtimer interrupts such as contikimac radio cycling */ +/* STAMPS will print ENERGEST outputs if that is enabled. */ +#define PERIODICPRINTS 1 +#if PERIODICPRINTS +/* #define PINGS 64 */ +#define ROUTES 600 +#define STAMPS 60 +#define STACKMONITOR 1024 +uint32_t clocktime; +#define TESTRTIMER 0 +#if TESTRTIMER +uint8_t rtimerflag = 1; +struct rtimer rt; +void +rtimercycle(void) +{ + rtimerflag = 1; +} +#endif +#endif + +uint16_t node_id; /* Can be set by cooja */ + +uint16_t ledtimer_red, ledtimer_yellow; +uint16_t i2c_probed; /* i2c devices we have probed */ + + +/*-------------------------------------------------------------------------*/ +/*----------------------Configuration of the .elf file---------------------*/ +#if 1 +/* The proper way to set the signature is */ +#include +#else +/* Older avr-gcc's may not define the needed SIGNATURE bytes. Do it manually if you get an error */ +typedef struct {const unsigned char B2; + const unsigned char B1; + const unsigned char B0; +} __signature_t; +#define SIGNATURE __signature_t __signature __attribute__((section(".signature"))) +SIGNATURE = { + .B2 = 0x01, /* SIGNATURE_2, //ATMEGA128rfa1 */ + .B1 = 0xA7, /* SIGNATURE_1, //128KB flash */ + .B0 = 0x1E, /* SIGNATURE_0, //Atmel */ +}; +#endif + +#if 1 +/* JTAG, SPI enabled, Internal RC osc, Boot flash size 4K, 6CK+65msec delay, brownout disabled */ +FUSES = { .low = 0xe2, .high = 0x99, .extended = 0xff, }; +#else +/* JTAG+SPI, Boot 4096 words @ $F000, Internal oscillator, startup 6 CK +0 ms, Brownout 1.8 volts */ +FUSES = { .low = 0xC2, .high = 0x99, .extended = 0xfe, }; +#endif + +uint8_t +rng_get_uint8(void) +{ +#if 1 + /* Upper two RSSI reg bits (RND_VALUE) are random in rf231 */ + uint8_t j; + j = (PHY_RSSI & 0xc0) + ((PHY_RSSI >> 2) & 0x30) + ((PHY_RSSI >> 4) & 0x0c) + ((PHY_RSSI >> 6) & 0x03); +#else +/* Get a pseudo random number using the ADC */ + uint8_t i, j; + ADCSRA = 1 << ADEN; /* Enable ADC, not free running, interrupt disabled, fastest clock */ + for(i = 0; i < 4; i++) { + ADMUX = 0; /* toggle reference to increase noise */ + ADMUX = 0x1E; /* Select AREF as reference, measure 1.1 volt bandgap reference. */ + ADCSRA |= 1 << ADSC; /* Start conversion */ + while(ADCSRA & (1 << ADSC)) ; /* Wait till done */ + j = (j << 2) + ADC; + } + ADCSRA = 0; /* Disable ADC */ +#endif + PRINTD("rng issues %d\n", j); + return j; +} +/*-------------------------Low level initialization------------------------*/ +/*------Done in a subroutine to keep main routine stack usage small--------*/ +void +initialize(void) +{ + watchdog_init(); + watchdog_start(); + leds_init(); + serial_line_init(); + + rs232_init(RS232_PORT_0, USART_BAUD_38400, USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8); + rs232_redirect_stdout(RS232_PORT_0); + +#if 0 + /* Do it my way... */ + //UBRR0L = 8; UBRR0H = 0; UCSR0A = (0 << U2X0); // 115.2k err=-3.5% + //UBRR0L = 16; UBRR0H = 0; UCSR0A = (1 << U2X0); // 115.2k 2.1% + //UBRR0L = 3; UBRR0H = 0; UCSR0A = (1 << U2X0); // 500k 0% +#endif + + rs232_set_input(RS232_PORT_0, serial_line_input_byte); + + clock_init(); + + if(MCUSR & (1 << PORF)) { + PRINTD("Power-on reset.\n"); + } + if(MCUSR & (1 << EXTRF)) { + PRINTD("External reset!\n"); + } + if(MCUSR & (1 << BORF)) { + PRINTD("Brownout reset!\n"); + } + if(MCUSR & (1 << WDRF)) { + PRINTD("Watchdog reset!\n"); + } + if(MCUSR & (1 << JTRF)) { + PRINTD("JTAG reset!\n"); + } + + i2c_init(100000); /* 100 bit/s */ + +#if STACKMONITOR + /* Simple stack pointer highwater monitor. Checks for magic numbers in the main + * loop. In conjuction with PERIODICPRINTS, never-used stack will be printed + * every STACKMONITOR seconds. + */ + { + extern uint16_t __bss_end; + uint16_t p = (uint16_t)&__bss_end; + do { + *(uint16_t *)p = 0x4242; + p += 10; + } while(p < SP - 10); /* don't overwrite our own stack */ + } +#endif + +#define CONF_CALIBRATE_OSCCAL 0 +#if CONF_CALIBRATE_OSCCAL + void calibrate_rc_osc_32k(); + { + extern uint8_t osccal_calibrated; + uint8_t i; + PRINTD("\nBefore calibration OSCCAL=%x\n", OSCCAL); + for(i = 0; i < 10; i++) { + calibrate_rc_osc_32k(); + PRINTD("Calibrated=%x\n", osccal_calibrated); +/* #include */ +/* #define delay_us( us ) ( _delay_loop_2(1+(us*F_CPU)/4000000UL) ) */ +/* delay_us(50000); */ + } + clock_init(); + } +#endif + + PRINTA("\n*******Booting %s*******\n", CONTIKI_VERSION_STRING); + +/* rtimers needed for radio cycling */ + rtimer_init(); + + /* Initialize process subsystem */ + process_init(); + + /* etimers must be started before ctimer_init */ + process_start(&etimer_process, NULL); + ctimer_init(); + + /* Start radio and radio receive process */ + NETSTACK_RADIO.init(); + +/* Get a random seed for the 802.15.4 packet sequence number. + * Some layers will ignore duplicates found in a history (e.g. Contikimac) + * causing the initial packets to be ignored after a short-cycle restart. + */ + random_init(rng_get_uint8()); + + /* Set addresses BEFORE starting tcpip process */ + + linkaddr_t addr; + char eui64[8]; + + printf("I2C: "); + i2c_probed = i2c_probe(); + printf("\n"); + + if( i2c_probed & I2C_AT24MAC ) { + i2c_at24mac_read((char *)&eui64, 1); + linkaddr_set_node_addr((linkaddr_t *) &eui64); + node_id = (eui64[1] << 8) + eui64[7]; + } + else { + printf("Random EUI64 address generated\n"); + eui64[0] = 0xfc; /* Atmels OUI */ + eui64[1] = 0xc2; + eui64[2] = 0x3d; + eui64[3] = 0; + eui64[4] = 0; + eui64[5] = 0; + eui64[6] = node_id >> 8; + eui64[7] = node_id & 0xff; + linkaddr_set_node_addr((linkaddr_t *)&eui64); + } + + /* memcpy(&uip_lladdr.addr, &addr.u8, sizeof(linkaddr_t)); */ + +#if NETSTACK_CONF_WITH_IPV6 + memcpy(&addr.u8, &eui64, sizeof(linkaddr_t)); + memcpy(&uip_lladdr.addr, &addr.u8, sizeof(linkaddr_t)); +#endif + + rf230_set_pan_addr(params_get_panid(), params_get_panaddr(), (uint8_t *)&addr.u8); + rf230_set_channel(params_get_channel()); + rf230_set_txpower(params_get_txpower()); + +#if NETSTACK_CONF_WITH_IPV6 + PRINTA("EUI-64 MAC: %x-%x-%x-%x-%x-%x-%x-%x\n", addr.u8[0], addr.u8[1], addr.u8[2], addr.u8[3], addr.u8[4], addr.u8[5], addr.u8[6], addr.u8[7]); +#else + PRINTA("MAC address "); + uint8_t i; + addr.u8[0] = eui64[1] ; + addr.u8[1] = eui64[7]; + + for(i = sizeof(linkaddr_t); i > 0; i--) { + PRINTA("%x:", addr.u8[i - 1]); + } + PRINTA("\n"); +#endif + + /* Initialize stack protocols */ + queuebuf_init(); + NETSTACK_RDC.init(); + NETSTACK_MAC.init(); + NETSTACK_NETWORK.init(); + +#if ANNOUNCE_BOOT + PRINTA("MAC=%s, RDC=%s, NETWORK=%s, channel=%-u, check-rate-Hz=%-u, tx-power=%-u\n", NETSTACK_MAC.name, + NETSTACK_RDC.name, NETSTACK_NETWORK.name, rf230_get_channel(), + CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1 : NETSTACK_RDC.channel_check_interval()), + rf230_get_txpower()); +#if UIP_CONF_IPV6_RPL + PRINTA("RPL Enabled\n"); +#endif +#if UIP_CONF_ROUTER + PRINTA("Routing Enabled\n"); +#endif + +#endif /* ANNOUNCE_BOOT */ + +#if NETSTACK_CONF_WITH_IPV6 || NETSTACK_CONF_WITH_IPV4 + process_start(&tcpip_process, NULL); +#endif + + /* Autostart other processes */ + autostart_start(autostart_processes); + + /*---If using coffee file system create initial web content if necessary---*/ +#if COFFEE_FILES + int fa = cfs_open("/index.html", CFS_READ); + if(fa < 0) { /* Make some default web content */ + PRINTA("No index.html file found, creating upload.html!\n"); + PRINTA("Formatting FLASH file system for coffee..."); + cfs_coffee_format(); + PRINTA("Done!\n"); + fa = cfs_open("/index.html", CFS_WRITE); + int r = cfs_write(fa, &"It works!", 9); + if(r < 0) { + PRINTA("Can''t create /index.html!\n"); + } + cfs_close(fa); +/* fa = cfs_open("upload.html"), CFW_WRITE); */ +/*
*/ + } +#endif /* COFFEE_FILES */ + +/* Add addresses for testing */ +#if 0 + { + uip_ip6addr_t ipaddr; + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); +/* uip_ds6_prefix_add(&ipaddr,64,0); */ + } +#endif +/*--------------------------Announce the configuration---------------------*/ +#if ANNOUNCE_BOOT +#if AVR_WEBSERVER + { uint8_t i; + char buf[80]; + unsigned int size; + + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + if(uip_ds6_if.addr_list[i].isused) { + httpd_cgi_sprint_ip6(uip_ds6_if.addr_list[i].ipaddr, buf); + PRINTA("IPv6 Address: %s\n", buf); + } + } + cli(); + eeprom_read_block(buf, eemem_server_name, sizeof(eemem_server_name)); + sei(); + buf[sizeof(eemem_server_name)] = 0; + PRINTA("%s", buf); + cli(); + eeprom_read_block(buf, eemem_domain_name, sizeof(eemem_domain_name)); + sei(); + buf[sizeof(eemem_domain_name)] = 0; + size = httpd_fs_get_size(); +#ifndef COFFEE_FILES + PRINTA(".%s online with fixed %u byte web content\n", buf, size); +#elif COFFEE_FILES == 1 + PRINTA(".%s online with static %u byte EEPROM file system\n", buf, size); +#elif COFFEE_FILES == 2 + PRINTA(".%s online with dynamic %u KB EEPROM file system\n", buf, size >> 10); +#elif COFFEE_FILES == 3 + PRINTA(".%s online with static %u byte program memory file system\n", buf, size); +#elif COFFEE_FILES == 4 + PRINTA(".%s online with dynamic %u KB program memory file system\n", buf, size >> 10); +#endif /* COFFEE_FILES */ + } +#else + PRINTA("Online\n"); +#endif +#endif /* ANNOUNCE_BOOT */ + + ledtimer_red = 1000; + leds_on(LEDS_RED); +} + + +#if ROUTES && NETSTACK_CONF_WITH_IPV6 +static void +ipaddr_add(const uip_ipaddr_t *addr) +{ + uint16_t a; + int8_t i, f; + for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0) { + PRINTF("::"); + } + } else { + if(f > 0) { + f = -1; + } else if(i > 0) { + PRINTF(":"); + } + PRINTF("%x", a); + } + } +} +#endif +/*-------------------------------------------------------------------------*/ +/*------------------------- Main Scheduler loop----------------------------*/ +/*-------------------------------------------------------------------------*/ +int +main(void) +{ +#if NETSTACK_CONF_WITH_IPV6 + uip_ds6_nbr_t *nbr; +#endif /* NETSTACK_CONF_WITH_IPV6 */ + initialize(); + + while(1) { + process_run(); + watchdog_periodic(); + + /* Turn off LED's */ + if(ledtimer_red) { + if(--ledtimer_red == 0) { + leds_off(LEDS_RED); + } + } + if(ledtimer_yellow) { + if(--ledtimer_yellow == 0) { + leds_off(LEDS_YELLOW); + } + } + leds_off(LEDS_RED); + leds_off(LEDS_YELLOW); + +#if 0 +/* Various entry points for debugging in the AVR Studio simulator. + * Set as next statement and step into the routine. + */ + NETSTACK_RADIO.send(packetbuf_hdrptr(), 42); + process_poll(&rf230_process); + packetbuf_clear(); + len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE); + packetbuf_set_datalen(42); + NETSTACK_RDC.input(); +#endif + +#if 0 +/* Clock.c can trigger a periodic PLL calibration in the RF230BB driver. + * This can show when that happens. + */ + extern uint8_t rf230_calibrated; + if(rf230_calibrated) { + PRINTD("\nRF230 calibrated!\n"); + rf230_calibrated = 0; + } +#endif + +/* Set DEBUGFLOWSIZE in contiki-conf.h to track path through MAC, RDC, and RADIO */ +#if DEBUGFLOWSIZE + if(debugflowsize) { + debugflow[debugflowsize] = 0; + PRINTF("%s", debugflow); + debugflowsize = 0; + } +#endif + +#if PERIODICPRINTS +#if TESTRTIMER +/* Timeout can be increased up to 8 seconds maximum. + * A one second cycle is convenient for triggering the various debug printouts. + * The triggers are staggered to avoid printing everything at once. + */ + if(rtimerflag) { + rtimer_set(&rt, RTIMER_NOW() + RTIMER_ARCH_SECOND * 1UL, 1, (void *)rtimercycle, NULL); + rtimerflag = 0; +#else + if(clocktime != clock_seconds()) { + clocktime = clock_seconds(); +#endif + +#if STAMPS + if((clocktime % STAMPS) == 0) { +#if ENERGEST_CONF_ON +#include "lib/print-stats.h" + print_stats(); +#elif RADIOSTATS + extern volatile unsigned long radioontime; + PRINTF("%u(%u)s\n", clocktime, radioontime); +#else + PRINTF("%us\n", clocktime); +#endif + } +#endif +#if TESTRTIMER + clocktime += 1; +#endif + +#if PINGS && NETSTACK_CONF_WITH_IPV6 + extern void raven_ping6(void); + if((clocktime % PINGS) == 1) { + PRINTF("**Ping\n"); + raven_ping6(); + } +#endif + +#if ROUTES && NETSTACK_CONF_WITH_IPV6 + if((clocktime % ROUTES) == 2) { + + extern uip_ds6_netif_t uip_ds6_if; + + uint8_t i, j; + PRINTF("\nAddresses [%u max]\n", UIP_DS6_ADDR_NB); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + if(uip_ds6_if.addr_list[i].isused) { + ipaddr_add(&uip_ds6_if.addr_list[i].ipaddr); + PRINTF("\n"); + } + } + PRINTF("\nNeighbors [%u max]\n", NBR_TABLE_MAX_NEIGHBORS); + j = 0; + for(nbr = nbr_table_head(ds6_neighbors); + nbr != NULL; + nbr = nbr_table_next(ds6_neighbors, nbr)) { + ipaddr_add(&nbr->ipaddr); + PRINTF("\n"); + j++; + } + if(!j) { + PRINTF(" "); + } + PRINTF("\nRoutes [%u max]\n", UIP_DS6_ROUTE_NB); + { + uip_ds6_route_t *r; + j = 0; + for(r = uip_ds6_route_head(); + r != NULL; + r = uip_ds6_route_next(r)) { + ipaddr_add(&r->ipaddr); + PRINTF("/%u (via ", r->length); + ipaddr_add(uip_ds6_route_nexthop(r)); + PRINTF(") %lus\n", r->state.lifetime); + j++; + } + } + if(!j) { + PRINTF(" "); + } + PRINTF("\n---------\n"); + } +#endif + +#if STACKMONITOR + if((clocktime % STACKMONITOR) == 3) { + extern uint16_t __bss_end; + uint16_t p = (uint16_t)&__bss_end; + do { + if(*(uint16_t *)p != 0x4242) { + PRINTF("Never-used stack > %d bytes\n", p - (uint16_t)&__bss_end); + break; + } + p += 10; + } while(p < RAMEND - 10); + } +#endif + } +#endif /* PERIODICPRINTS */ + +#if RF230BB && 0 + extern uint8_t rf230processflag; + if(rf230processflag) { + PRINTF("rf230p%d", rf230processflag); + rf230processflag = 0; + } +#endif + +#if RF230BB && 0 + extern uint8_t rf230_interrupt_flag; + if(rf230_interrupt_flag) { + /* if (rf230_interrupt_flag!=11) { */ + PRINTF("**RI%u", rf230_interrupt_flag); + /* } */ + rf230_interrupt_flag = 0; + } +#endif + } + return 0; +} +/*---------------------------------------------------------------------------*/ + +void +log_message(char *m1, char *m2) +{ + PRINTF("%s%s\n", m1, m2); +} diff --git a/platform/avr-rss2/dev/adc.c b/platform/avr-rss2/dev/adc.c new file mode 100644 index 000000000..cb82d16b7 --- /dev/null +++ b/platform/avr-rss2/dev/adc.c @@ -0,0 +1,76 @@ +/* Copyright Robert Olsson */ + +#include +#include +#include +#include +#include +#include +#include "params.h" +#include "rss2.h" +#include "contiki.h" +#include "adc.h" +#include "rss2.h" + +uint16_t +adc_read(uint8_t pin) +{ + uint16_t volt = 0; + int i; + + ADMUX = pin; /* ADC pin PA0-PA7 -> 0-7 */ + ADCSRB &= ~(1 << MUX5); /* Needs to write before ADMUX pp 418 */ + ADMUX |= (1 << REFS1) | (1 << REFS0); /* 1.6 */ + + /* Maximal Track and Hold time */ + + ADCSRA = (1 << ADPS2) | (0 << ADPS1) | (1 << ADPS0); /* Prescaler /32 */ + ADCSRA |= (1 << ADEN); /* Enable the ADC */ + + while(!(ADCSRB & (1 << AVDDOK))) ; /* Wait for AVDD ok */ + while(!(ADCSRB & (1 << REFOK))) ; /* Wait for ref ok */ + + /* Ignore first result */ + + ADCSRA |= (1 << ADSC); + while(ADCSRA & _BV(ADSC)) { + } + + ADCW = 0; +#define RES 4 + + for(i = 0; i < RES; i++) { + + /* Start the conversion */ + ADCSRA |= (1 << ADSC); + + /* Wait for conversion */ + while(ADCSRA & (1 << ADSC)) { + } + + volt += ADCW; + } + ADMUX = 0; /* turn off internal vref */ + volt = volt / RES; + + /* Disable the ADC to save power */ + ADCSRA &= ~_BV(ADEN); + + return volt; +} +double +adc_read_v_in(void) +{ + /* Special treatment for v_in. Schottky voltage drop add */ + return ((double)adc_read(AV_IN)) * V_IN_FACTOR_SCHOTTKY + SCHOTTKY_DROP; +} +double +adc_read_a1(void) +{ + return ((double)adc_read(A1)) * V_IN_FACTOR; +} +double +adc_read_a2(void) +{ + return ((double)adc_read(A2)) * V_IN_FACTOR; +} diff --git a/platform/avr-rss2/dev/adc.h b/platform/avr-rss2/dev/adc.h new file mode 100644 index 000000000..9e9473e31 --- /dev/null +++ b/platform/avr-rss2/dev/adc.h @@ -0,0 +1,16 @@ +/* Copyright Robert Olsson */ + +#define V_IN_FACTOR 0.006256 /* 6.4/1023 */ +#define V_IN_FACTOR_NONE 0.001564 /* 1.6/1023 */ +#define SCHOTTKY_DROP 0.29 +#define V_IN_FACTOR_SCHOTTKY 0.0292 /* 30.19-SCHOTTKY_DROP/1023 schottky corr */ + +uint16_t +adc_read(uint8_t pin); +double +adc_read_v_in(void); +double +adc_read_a1(void); +double +adc_read_a2(void); + diff --git a/platform/avr-rss2/dev/battery-sensor.c b/platform/avr-rss2/dev/battery-sensor.c new file mode 100644 index 000000000..b81db95f6 --- /dev/null +++ b/platform/avr-rss2/dev/battery-sensor.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISE OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * ----------------------------------------------------------------- + * + * Author : Dag Björklund, Robert Olsson + * Created : 2005-11-01 + * Updated : $Date: 2010/08/25 19:30:52 $ + * $Revision: 1.11 $ + */ + +#include "contiki.h" +#include "dev/battery-sensor.h" +#include +#define delay_us(us) (_delay_loop_2(1 + (us * F_CPU) / 4000000UL)) + +const struct sensors_sensor battery_sensor; + +/* Returns the MCU voltage in mV read from the BATMON MCU register + * See AtMega chip docs for BATMON details. + */ + +static int +value(int type) +{ + uint16_t mv; + int i; + /* Resolution is 75mV if V>=2.55V; and 50mV if V<=2.45V */ + mv = 3675; + + for(i = 0x1f; 1; i--) { + + BATMON = i; + delay_us(100); + if(BATMON & 0x20) { + break; + } + + if(i == 0x10) { /* Range hi or lo */ + mv = 2500; + } + if(i > 0x10) { + mv -= 75; + } else { + mv -= 50; + } + } + return (int)((float)mv); +} +static int +configure(int type, int c) +{ + return 0; +} +static int +status(int type) +{ + return 1; +} +SENSORS_SENSOR(battery_sensor, BATTERY_SENSOR, value, configure, status); + diff --git a/platform/avr-rss2/dev/button-sensor.c b/platform/avr-rss2/dev/button-sensor.c new file mode 100644 index 000000000..664278993 --- /dev/null +++ b/platform/avr-rss2/dev/button-sensor.c @@ -0,0 +1,41 @@ +/* Dummy sensor routine */ + +#include "lib/sensors.h" +#include "dev/button-sensor.h" +const struct sensors_sensor button_sensor; +static int status(int type); +struct sensors_sensor *sensors[1]; +unsigned char sensors_flags[1]; + +static int +value(int type) +{ + return 0; +} +static int +configure(int type, int c) +{ + switch(type) { + case SENSORS_ACTIVE: + if(c) { + if(!status(SENSORS_ACTIVE)) { + } + } else { + } + return 1; + } + return 0; +} +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return 1; + } + return 0; +} +SENSORS_SENSOR(button_sensor, BUTTON_SENSOR, + value, configure, status); + diff --git a/platform/avr-rss2/dev/co2_sa_kxx-sensor.c b/platform/avr-rss2/dev/co2_sa_kxx-sensor.c new file mode 100644 index 000000000..564f8c011 --- /dev/null +++ b/platform/avr-rss2/dev/co2_sa_kxx-sensor.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015, Copyright Markus Hidell, Robert Olsson + * 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. + * + * + * Authors : Markus Hidell, Robert Olsson {mahidell, roolss} @kth.se + * Created : 2015-10-27 + * Updated : $Date: 2010/01/14 20:23:02 $ + * $Revision: 1.2 $ + */ + +#include "contiki.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "dev/watchdog.h" +#include "lib/list.h" +#include "lib/memb.h" +#include "co2_sa_kxx-sensor.h" + +static int +status(int type) +{ + return 0; +} +static int +configure(int type, int c) +{ + return 0; +} +static int +value(int var) +{ + int val, status; + uint8_t buf[2], csum; + int16_t res; + (void) status; + (void) csum; + + res = 0; + i2c_start_wait(I2C_CO2SA_ADDR | I2C_WRITE); + if(res) { + goto err; + } + + i2c_write(0x22); + i2c_write(0x00); + + if(var == CO2_SA_KXX_CO2) { + i2c_write(0x08); + i2c_write(0x2A); + } + + if(var == CO2_SA_KXX_TEMP) { + i2c_write(0x12); + i2c_write(0x34); + } + + if(var == CO2_SA_KXX_RH) { + i2c_write(0x14); + i2c_write(0x36); + } + + i2c_stop(); + + if(res) { + goto err; + } + + clock_delay_msec(20); + + res = 0; + i2c_start(I2C_CO2SA_ADDR | I2C_READ); + + if(res) { + goto err; + } + + + status = i2c_readAck(); + + if((status & 0x01) == 0) + goto err; + + buf[0] = i2c_readAck(); + buf[1] = i2c_readAck(); + csum = i2c_readNak(); + i2c_stop(); + + val = ((int16_t)(buf[0] << 8)) | buf[1]; + + return val; + +err: + i2c_stop(); + return 0; +} +SENSORS_SENSOR(co2_sa_kxx_sensor, "CO2", value, configure, status); diff --git a/platform/avr-rss2/dev/co2_sa_kxx-sensor.h b/platform/avr-rss2/dev/co2_sa_kxx-sensor.h new file mode 100644 index 000000000..bdb366fea --- /dev/null +++ b/platform/avr-rss2/dev/co2_sa_kxx-sensor.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015, Copyright Markus Hidell, Robert Olsson + * 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. + * + * + * Authors : Markus Hidell, Robert Olsson {mahidell, roolss} @kth.se + * Created : 2015-10-27 + * Updated : $Date: 2010/01/14 20:23:02 $ + * $Revision: 1.2 $ + */ + +#ifndef CO2_SA_KXX_SENSOR_H_ +#define CO2_SA_KXX_SENSOR_H_ + +#define CO2_SA_KXX_CO2 0 +#define CO2_SA_KXX_TEMP 1 +#define CO2_SA_KXX_RH 3 + +#include "lib/sensors.h" + +extern const struct sensors_sensor co2_sa_kxx_sensor; + +#define I2C_CO2SA_ADDR (0x68 << 1) + +#endif /* CO2_SA_KXX-SENSOR_H_ */ diff --git a/platform/avr-rss2/dev/ds18b20.c b/platform/avr-rss2/dev/ds18b20.c new file mode 100644 index 000000000..6044ad91e --- /dev/null +++ b/platform/avr-rss2/dev/ds18b20.c @@ -0,0 +1,247 @@ +/* + + Contiki library for DS18B20 temperature sensor - + For more details see http://xxx + + Author - + Author - + + License - GPLv3 + + */ + +#include "ds18b20.h" + +/* probe_for_ds18b20 probes for the sensor. Returns 0 on failure, 1 on success */ +/* Assumptions: only one sensor on the "1-wire bus", on port WSN_DS18B20_PORT */ +/* BUG: THIS CODE DOES NOT WORK AS INTENDED! IT RETURNS "1" EVEN WHEN THERE IS NO */ +/* SENSOR CONNECTED. */ + +uint8_t +ds18b20_probe(void) +{ + uint8_t result = 0; + + /* Reset 1W-bus */ + + /* Pull PIN low for 480 microseconds (us) */ + /* Start with setting bit DS18B20_1_PIN to 0 */ + OW_SET_PIN_LOW(); + /* then set direction to OUT by setting DS18B20_1_DDR bit to 1 */ + OW_SET_OUTPUT(); + /* Delay 480 us */ + clock_delay_usec(480); + /* See if sensor responds. First release the bus and switch to INput mode */ + /* by setting DS18B20_1_DDR bit to 0 */ + OW_SET_INPUT(); + /* Activate internal pull-up by setting pin to HIGH (when in INput mode) */ + /* OW_SET_PIN_HIGH(); */ + /* Wait for the pin to go HIGH for 64 us */ + clock_delay_usec(64); + /* Now the sensor, if present, pulls the pin LOW for 60-240 us */ + /* Detect 0 on PIND bit DS18B20_1_PIN. Invert the result so a presence (aka a 0) */ + /* sets "result" to 1 (for success) */ + result = !OW_GET_PIN_STATE(); + + /* The sensor releases the pin so it goes HIGH after 240 us, add some */ + /* for the signal to stabilize, say 300 usecs to be on the safe side? */ + if(result) { + clock_delay_usec(300); + /* Now the bus should be HIGH again */ + result = OW_GET_PIN_STATE(); + } + + return result; +} +/* Write 1 or 0 on the bus */ + +void +write_bit(uint8_t bit) +{ + /* Set pin to 0 */ + OW_SET_OUTPUT(); + OW_SET_PIN_LOW(); + + /* Pin should be 0 for at least 1 us */ + clock_delay_usec(2); + + /* If we're writing a 1, let interna pull-up pull the bus high */ + /* within 15 us of setting the bus to low */ + if(bit) { + /* Internal pull-up is activated by setting direction to IN and the */ + /* setting the pin to HIGH */ + OW_SET_INPUT(); + OW_SET_PIN_HIGH(); + } + /* OK, now the bus is either LOW, or pulled HIGH by the internal pull-up */ + /* Let this state remain for 60 us, then release the bus */ + clock_delay_usec(60); + + /* Release the bus */ + OW_SET_PIN_HIGH(); + OW_SET_INPUT(); + + /* Allow > 1 us between read/write operations */ + clock_delay_usec(2); +} +/* */ +/* Read one bit of information from the bus, and return it as 1 or 0 */ +/* */ + +uint8_t +read_bit(void) +{ + uint8_t bit = 0; + + /* Set pin to 0 */ + OW_SET_OUTPUT(); + OW_SET_PIN_LOW(); + + /* Pin should be 0 for at least 1 us */ + clock_delay_usec(2); + + /* Now read the bus, start by setting in/out direction and activating internal */ + /* pull-up resistor */ + OW_SET_INPUT(); + OW_SET_PIN_HIGH(); + + /* ds18b20 either keeps the pin down or releases the bus and the */ + /* bus then goes high because of the interna pull-up resistor */ + /* Check whichever happens before 15 us has passed */ + clock_delay_usec(15 - 2 - 1); + bit = OW_GET_PIN_STATE(); + + /* The complete read cycle must last at least 60 us. We have now spent */ + /* about 14-15 us in delays, so add another delay to reach >= 60 us */ + clock_delay_usec(50); + + /* Release bus */ + OW_SET_PIN_HIGH(); + OW_SET_INPUT(); + + /* Allow > 1 us between read/write operations */ + clock_delay_usec(2); + + return bit ? 1 : 0; +} +/* */ +/* Read one byte of information. A byte is read least significant bit first */ +/* */ + +uint8_t +read_byte(void) +{ + uint8_t result = 0; + uint8_t bit; + int i; + + for(i = 0; i < 8; i++) { + bit = read_bit(); + result += (bit << i); + } + return result; +} +/* */ +/* Write one byte of information. A byte is written least significant bit first */ +/* */ + +void +write_byte(uint8_t byte) +{ + int i; + + for(i = 0; i < 8; i++) { + write_bit((byte >> i) & 1); + } +} +/* */ +/* ds18b20_get_temp returns the temperature in "temp" (in degrees celsius) */ +/* Returns 0 on failure (and then "temp" is left unchanged */ +/* Returns 1 on success, and sets temp */ +/* */ + +uint8_t +ds18b20_get_temp(float *temp) +{ + uint8_t result = 0; + + /* Reset bus by probing. Probe returns 1 on success/presence of sensor */ + if(ds18b20_probe()) { + /* write command "skip rom" since we only have one sensor on the wire! */ + write_byte(DS18B20_COMMAND_SKIP_ROM); + + /* write command to start measurement */ + write_byte(DS18B20_COMMAND_START_CONVERSION); + + /* Wait for conversion to complete */ + /* Conversion is 12-bit by default. */ + /* Since we have external power to the sensor (ie not in "parasitic power" mode) */ + /* the bus is held LOW by the sensor while the conversion is going on, and then HIGH */ + /* when conversion is finished. */ + OW_SET_INPUT(); + int count = 0; + while(!OW_GET_PIN_STATE()) { + clock_delay_msec(10); + count++; + /* Longest conversion time is 750 ms (12-bit resolution) */ + /* So if count > 80 (for a little margin!), we return -274.0 */ + /* which indicates failure to read the temperature. */ + if(count > 80) { + return 0; + } + } + + /* The result is stored in the "scratch pad", a 9 byte memory block. */ + /* The first two bytes are the conversion result. Reading the scratch pad */ + /* can be terminated by sending a reset signal (but we read all 9 bytes) */ + (void)ds18b20_probe(); + write_byte(DS18B20_COMMAND_SKIP_ROM); + write_byte(DS18B20_COMMAND_READ_SCRATCH_PAD); + uint8_t i, sp_arr[9]; + for(i = 0; i < 9; i++) { + sp_arr[i] = read_byte(); + } + + /* Check CRC, if mismatch, return 0 (failure to read temperature) */ + uint8_t crc_cal = crc8_ds18b20(sp_arr, 8); + + if(crc_cal != sp_arr[8]) { + return 0; + } + + /* OK, now decode what the temperature reading is. This code assumes 12-bit resolution, */ + /* so this must be modified if the code is modified to use any other resolution! */ + int16_t temp_res; + uint8_t temp_lsb = sp_arr[0]; + uint8_t temp_msb = sp_arr[1]; + + temp_res = (int16_t)temp_msb << 8 | temp_lsb; + *temp = (float)temp_res * 0.0625; + + result = 1; + } + return result; +} +/* */ +/* crc8 algorithm for ds18b20 */ +/* http://www.miscel.dk/MiscEl/CRCcalculations.html */ +/* */ + +uint8_t +crc8_ds18b20(uint8_t *buf, uint8_t buf_len) +{ + uint8_t result = 0; + uint8_t i, b; + + for(i = 0; i < buf_len; i++) { + result = result ^ buf[i]; + for(b = 1; b < 9; b++) { + if(result & 0x1) { + result = (result >> 1) ^ 0x8C; + } else { + result = result >> 1; + } + } + } + return result; +} diff --git a/platform/avr-rss2/dev/enc28j60_avr.c b/platform/avr-rss2/dev/enc28j60_avr.c new file mode 100644 index 000000000..2bfb49562 --- /dev/null +++ b/platform/avr-rss2/dev/enc28j60_avr.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2012-2013, Robert Olsson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include "dev/watchdog.h" +#include "contiki.h" +#include "i2c.h" +#include +#include +#include +#include "enc28j60_avr.h" + +#include +#define delay_us(us) (_delay_loop_2(1 + (us * F_CPU) / 4000000UL)) + +void +enc28j60_arch_spi_init(void) +{ + CS_SPI_DDR |= (1 << SPI_CS); + CS_SPI_PORT |= (1 << SPI_CS); + + SPI_DDR |= (1 << SPI_MOSI) | (1 << SPI_SCK); + SPI_DDR &= ~(1 << SPI_MISO); + SPI_PORT &= ~(1 << SPI_MOSI); + SPI_PORT &= ~(1 << SPI_SCK); + SPCR = (1 << SPE) | (1 << MSTR); + /* SPSR |= (1< + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef ENC28J60_AVR_H +#define ENC28J60_AVR_H + +#define SPI_DDR DDRB /* Data Direction Register: Port B */ +#define SPI_PORT PORTB /* Serial Peripheral Interface */ +#define SPI_MOSI 2 /* PB2: Master Out Slave In */ +#define SPI_MISO 3 /* PB3: Master In Slave out */ +#define SPI_SCK 1 /* PB1: Serial Clock */ + +#define CS_SPI_DDR DDRD /* Data Direction Register: Port B */ +#define CS_SPI_PORT PORTD /* Serial Peripheral Interface */ +#define SPI_CS 6 /* PD6: OW2_PIN, Chip Select */ + +/* AVR specific's for enc28j60 */ + +void enc28j60_arch_spi_init(void); +uint8_t enc28j60_arch_spi_write(uint8_t data); +uint8_t enc28j60_arch_spi_read(void); +void enc28j60_arch_spi_select(void); +void enc28j60_arch_spi_deselect(void); + +#endif /* ENC28J60_AVR_H */ diff --git a/platform/avr-rss2/dev/i2c.c b/platform/avr-rss2/dev/i2c.c new file mode 100644 index 000000000..2668aad58 --- /dev/null +++ b/platform/avr-rss2/dev/i2c.c @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2010, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \file + * i2c core functions + * \author + * Robert Olsson + */ + +#include +#include +#include +#include +#include "dev/watchdog.h" +#include "contiki.h" +#include "i2c.h" +#include +#include +#include +#include "dev/co2_sa_kxx-sensor.h" + +void +i2c_init(uint32_t speed) +{ + /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */ + + TWSR = 0; /* no prescaler */ + TWBR = ((F_CPU / speed) - 16) / 2; /* must be > 10 for stable operation */ +} +uint8_t +i2c_start(uint8_t addr) +{ + uint8_t twst; + uint32_t n; + + /* Send START condition */ + TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); + + /* Wait until transmission completed */ + for(n = 0; n < 100000 && !(TWCR & (1 << TWINT)); n++) { + } + if(n >= 100000) { + return 1; + } + + /* check value of TWI Status Register. Mask prescaler bits. */ + twst = TW_STATUS & 0xF8; + if((twst != TW_START) && (twst != TW_REP_START)) { + return 1; + } + + /* send device address */ + TWDR = addr; + TWCR = (1 << TWINT) | (1 << TWEN); + + /* wail until transmission completed and ACK/NACK has been received */ + for(n = 0; n < 100000 && !(TWCR & (1 << TWINT)); n++) { + } + if(n >= 100000) { + return 1; + } + + /* check value of TWI Status Register. Mask prescaler bits. */ + twst = TW_STATUS & 0xF8; + if((twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK)) { + return 1; + } + + return 0; +} +void +i2c_start_wait(uint8_t addr) +{ + uint8_t twst; + while ( 1 ) + { + // send START condition + TWCR = (1< + */ + +#include "contiki.h" + +/* Here we define the i2c address for dev we support */ +#define I2C_AT24MAC_ADDR 0xB0 /* EUI64 ADDR */ +#define I2C_SHT2X_ADDR (0x40 << 1) /* SHT2X ADDR */ + + +/* Here we define a enumration for devices */ +#define I2C_AT24MAC (1<<0) +#define I2C_SHT2X (1<<1) +#define I2C_CO2SA (1<<2) /* Sense-Air CO2 */ + +#define I2C_READ 1 +#define I2C_WRITE 0 + +void i2c_init(uint32_t speed); +uint8_t i2c_start(uint8_t addr); +void i2c_start_wait(uint8_t addr); +void i2c_stop(void); +void i2c_write(uint8_t u8data); +uint8_t i2c_readAck(void); +uint8_t i2c_readNak(void); +uint8_t i2c_getstatus(void); +uint16_t i2c_probe(void); +void i2c_read_mem(uint8_t addr, uint8_t reg, uint8_t buf[], uint8_t bytes); +void i2c_write_mem(uint8_t addr, uint8_t reg, uint8_t value); +void i2c_at24mac_read(char *buf, uint8_t eui64); +extern uint16_t i2c_probed; /* i2c devices we have probed */ diff --git a/platform/avr-rss2/dev/leds.c b/platform/avr-rss2/dev/leds.c new file mode 100644 index 000000000..c59f9d09f --- /dev/null +++ b/platform/avr-rss2/dev/leds.c @@ -0,0 +1,45 @@ +#include +#include "rss2.h" +#include "leds.h" + +void +leds_init(void) +{ + DDRE |= (1 << LED_RED); + DDRE |= (1 << LED_YELLOW); + /* Off */ + leds_off(LEDS_ALL); +} +void +leds_on(unsigned char ledv) +{ + if(ledv & LEDS_YELLOW) { + PORTE &= ~(1 << LED_YELLOW); + } + if(ledv & LEDS_RED) { + PORTE &= ~(1 << LED_RED); + } +} +void +leds_off(unsigned char ledv) +{ + if(ledv & LEDS_YELLOW) { + PORTE |= (1 << LED_YELLOW); + } + if(ledv & LEDS_RED) { + PORTE |= (1 << LED_RED); + } +} +void +leds_toggle(unsigned char ledv) +{ +} +void +leds_invert(unsigned char ledv) +{ +} +unsigned char +leds_get(void) +{ + return 0; +} diff --git a/platform/avr-rss2/dev/leds.h b/platform/avr-rss2/dev/leds.h new file mode 100644 index 000000000..6dee358c8 --- /dev/null +++ b/platform/avr-rss2/dev/leds.h @@ -0,0 +1,17 @@ + +#ifndef CONTIKI_LED_H_ +#define CONTIKI_LED_H_ + +#define LEDS_GREEN 1 +#define LEDS_YELLOW 2 +#define LEDS_RED 4 +#define LEDS_ALL 7 + +void leds_init(void); /* Initialize the LEDs driver. */ +unsigned char leds_get(void); /* Get the status of a LED. */ +void leds_on(unsigned char ledv); /* Turn on a set of LEDs. */ +void leds_off(unsigned char ledv); /* Turn off a set of LEDs. */ +void leds_toggle(unsigned char ledv); /* Toggle a set of LEDs. */ +void leds_invert(unsigned char ledv); /* Toggle a set of LEDs. */ + +#endif /* CONTIKI_LED_H_ */ diff --git a/platform/avr-rss2/dev/light-sensor.c b/platform/avr-rss2/dev/light-sensor.c new file mode 100644 index 000000000..cbb0a93f7 --- /dev/null +++ b/platform/avr-rss2/dev/light-sensor.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015, Copyright Robert Olsson + * 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" +#include "lib/sensors.h" +#include "dev/light-sensor.h" +#include "rss2.h" +#include "adc.h" + +const struct sensors_sensor light_sensor; + +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + return adc_read(A3); +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int c) +{ + DDRF &= ~(1 << A3); /* Light sensor */ + DDRF &= ~(1 << A3_PWR); + + PORTF |= (1 << A3_PWR); /* Light sensor */ + return 0; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(light_sensor, "Light", value, configure, status); diff --git a/platform/avr-rss2/dev/light-sensor.h b/platform/avr-rss2/dev/light-sensor.h new file mode 100644 index 000000000..da26c724e --- /dev/null +++ b/platform/avr-rss2/dev/light-sensor.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015, Copyright Robert Olsson + * 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. + * + * + * Author : Robert Olsson + * Created : 2015-10-27 + * Updated : $Date: 2010/01/14 20:23:02 $ + * $Revision: 1.2 $ + */ + +#ifndef LIGHT_SENSOR_H_ +#define LIGHT_SENSOR_H_ + +#include "lib/sensors.h" + +extern const struct sensors_sensor light_sensor; + +#endif /* LIGHT-SENSOR_H_ */ diff --git a/platform/avr-rss2/dev/pulse-sensor.c b/platform/avr-rss2/dev/pulse-sensor.c new file mode 100644 index 000000000..eb0f3a842 --- /dev/null +++ b/platform/avr-rss2/dev/pulse-sensor.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2015, Copyright Robert Olsson / Radio Sensors AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the 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. + * + * + * Author : Robert Olsson robert@radio-sensors.com + * Created : 2015-11-22 + */ + +#include "contiki.h" +#include "lib/sensors.h" +#include "dev/pulse-sensor.h" +#include "rss2.h" + +const struct sensors_sensor pulse_sensor; + +#define NP 2 + +uint32_t volatile pc[NP]; + +/* + * Note interrupt sources can be woken up from sleep mode PWR_SAVE + * Two interrupt ports, #0 green terminal block. #1 pin header via + * a comparator. + */ + +static void +port_irq_ctrl(uint8_t on) +{ + if(on) { + + DDRD &= ~(1 << PD2); + PORTD &= ~(1 << PD2); + EIMSK = 0; + EICRA |= 0x20; /* Falling edge INT2 */ + EIMSK |= (1 << PD2); /* Enable interrupt for pin */ + + /* p1 port */ + DDRD &= ~(1 << PD3); + PORTD &= ~(1 << PD3); + EIMSK |= (1 << PD3); /* Enable interrupt for pin */ + EICRA |= 0x80; /* Falling edge */ + PCICR |= (1 << PCIE0); /* And enable irq PCINT 7:0 */ + } else { + EICRA = 0; + PORTD |= (1 << PD2); + EIMSK &= ~(1 << PD2); /* Disable interrupt for pin */ + + PORTD |= (1 << PD3); + EIMSK &= ~(1 << PD3); /* Disable interrupt for pin */ + } +} +ISR(INT2_vect) +{ + if(!(PCICR & (1 << PCIE0))) { + return; + } + pc[0]++; +} + +ISR(INT3_vect) +{ + if(!(PCICR & (1 << PCIE0))) { + return; + } + pc[1]++; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + if(type == 0) { + return (int)pc[0]; + } + if(type == 1) { + return (int)pc[1]; + } + return -1; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int c) +{ + port_irq_ctrl(1); /* Enable pulse counts */ + return 0; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(pulse_sensor, "Pulse", value, configure, status); diff --git a/platform/avr-rss2/dev/pulse-sensor.h b/platform/avr-rss2/dev/pulse-sensor.h new file mode 100644 index 000000000..03a09cd1b --- /dev/null +++ b/platform/avr-rss2/dev/pulse-sensor.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2015, Copyright Robert Olsson / Radio Sensors AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the 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. + * + * + * Author : Robert Olsson robert@radio-sensors.com + * Created : 2015-11-22 + */ + +#ifndef PULSE_SENSOR_H_ +#define PULSE_SENSOR_H_ + +#include "lib/sensors.h" + +extern const struct sensors_sensor pulse_sensor; + +#endif /* PULSE-SENSOR_H_ */ diff --git a/platform/avr-rss2/dev/temp-sensor.c b/platform/avr-rss2/dev/temp-sensor.c new file mode 100644 index 000000000..5bc108c7e --- /dev/null +++ b/platform/avr-rss2/dev/temp-sensor.c @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2015, Copyright Per Lindgren + * 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. + * + * + * Author : Per Lindgren + * Hacked by: Robert Olsson robert@radio-sensors.com + * Created : 2015-11-22 + */ + +#include "contiki.h" +#include "dev/temp-sensor.h" +#include +#define delay_us(us) (_delay_loop_2(1 + (us * F_CPU) / 4000000UL)) + +const struct sensors_sensor temp_mcu_sensor; + +/* probe_for_ds18b20 probes for the sensor. Returns 0 on failure, 1 on success + * Assumptions: only one sensor on the "1-wire bus", on port WSN_DS18B20_PORT + * BUG: THIS CODE DOES NOT WORK AS INTENDED! IT RETURNS "1" EVEN WHEN THERE + * IS NO SENSOR CONNECTED. + */ + +uint8_t +ds18b20_probe(void) +{ + uint8_t result = 0; + + /* Reset 1W-bus */ + + /* Pull PIN low for 480 microseconds (us) + * Start with setting bit DS18B20_1_PIN to 0 */ + OW_SET_PIN_LOW(); + /* then set direction to OUT by setting DS18B20_1_DDR bit to 1 */ + OW_SET_OUTPUT(); + /* Delay 480 us */ + clock_delay_usec(480); + /* See if sensor responds. First release the bus and switch to INput mode + * by setting DS18B20_1_DDR bit to 0 */ + OW_SET_INPUT(); + /* Activate internal pull-up by setting pin to HIGH (when in INput mode) + * OW_SET_PIN_HIGH(); + * Wait for the pin to go HIGH for 64 us */ + clock_delay_usec(64); + /* Now the sensor, if present, pulls the pin LOW for 60-240 us + * Detect 0 on PIND bit DS18B20_1_PIN. Invert the result so a presence + * (aka * a 0) sets "result" to 1 (for success) */ + result = !OW_GET_PIN_STATE(); + + /* The sensor releases the pin so it goes HIGH after 240 us, add some + for the signal to stabilize, say 300 usecs to be on the safe side? */ + if(result) { + clock_delay_usec(300); + /* Now the bus should be HIGH again */ + result = OW_GET_PIN_STATE(); + } + return result; +} +/* Write 1 or 0 on the bus */ + +void +write_bit(uint8_t bit) +{ + /* Set pin to 0 */ + OW_SET_OUTPUT(); + OW_SET_PIN_LOW(); + + /* Pin should be 0 for at least 1 us */ + clock_delay_usec(2); + + /* If we're writing a 1, let interna pull-up pull the bus high + * within 15 us of setting the bus to low */ + if(bit) { + /* Internal pull-up is activated by setting direction to IN and the + * setting the pin to HIGH */ + OW_SET_INPUT(); + OW_SET_PIN_HIGH(); + } + /* OK, now the bus is either LOW, or pulled HIGH by the internal pull-up + * Let this state remain for 60 us, then release the bus */ + clock_delay_usec(60); + + /* Release the bus */ + OW_SET_PIN_HIGH(); + OW_SET_INPUT(); + + /* Allow > 1 us between read/write operations */ + clock_delay_usec(2); +} +/* Read one bit of information from the bus, and return it as 1 or 0 */ + +uint8_t +read_bit(void) +{ + uint8_t bit = 0; + + /* Set pin to 0 */ + OW_SET_OUTPUT(); + OW_SET_PIN_LOW(); + + /* Pin should be 0 for at least 1 us */ + clock_delay_usec(2); + + /* Now read the bus, start by setting in/out direction and activating + * internal pull-up resistor */ + OW_SET_INPUT(); + OW_SET_PIN_HIGH(); + + /* ds18b20 either keeps the pin down or releases the bus and the + * bus then goes high because of the interna pull-up resistor + * Check whichever happens before 15 us has passed */ + clock_delay_usec(15 - 2 - 1); + bit = OW_GET_PIN_STATE(); + + /* The complete read cycle must last at least 60 us. We have now spent + * about 14-15 us in delays, so add another delay to reach >= 60 us */ + clock_delay_usec(50); + + /* Release bus */ + OW_SET_PIN_HIGH(); + OW_SET_INPUT(); + + /* Allow > 1 us between read/write operations */ + clock_delay_usec(2); + + return bit ? 1 : 0; +} +/* Read one byte of information. A byte is read least significant bit first */ + +uint8_t +read_byte(void) +{ + uint8_t result = 0; + uint8_t bit; + int i; + + for(i = 0; i < 8; i++) { + bit = read_bit(); + result += (bit << i); + } + return result; +} +/* Write one byte of information. A byte is written least significant bit first */ + +void +write_byte(uint8_t byte) +{ + int i; + + for(i = 0; i < 8; i++) { + write_bit((byte >> i) & 1); + } +} +/* ds18b20_get_temp returns the temperature in "temp" (in degrees celsius) + * Returns 0 on failure (and then "temp" is left unchanged + * Returns 1 on success, and sets temp */ + +uint8_t +ds18b20_get_temp(double *temp) +{ + uint8_t result = 0; + + /* Reset bus by probing. Probe returns 1 on success/presence of sensor */ + if(ds18b20_probe()) { + /* write command "skip rom" since we only have one sensor on the wire! */ + write_byte(DS18B20_COMMAND_SKIP_ROM); + + /* write command to start measurement */ + write_byte(DS18B20_COMMAND_START_CONVERSION); + + /* Wait for conversion to complete. Conversion is 12-bit by default. + * Since we have external power to the sensor (ie not in "parasitic power" + * mode) the bus is held LOW by the sensor while the conversion is going + * on, and then HIGH when conversion is finished. */ + OW_SET_INPUT(); + int count = 0; + while(!OW_GET_PIN_STATE()) { + clock_delay_msec(10); + count++; + /* Longest conversion time is 750 ms (12-bit resolution) + * So if count > 80 (for a little margin!), we return -274.0 + * which indicates failure to read the temperature. */ + if(count > 80) { + return 0; + } + } + + /* The result is stored in the "scratch pad", a 9 byte memory block. + * The first two bytes are the conversion result. Reading the scratch pad + * can be terminated by sending a reset signal (but we read all 9 bytes) */ + (void)ds18b20_probe(); + write_byte(DS18B20_COMMAND_SKIP_ROM); + write_byte(DS18B20_COMMAND_READ_SCRATCH_PAD); + uint8_t i, sp_arr[9]; + for(i = 0; i < 9; i++) { + sp_arr[i] = read_byte(); + } + + /* Check CRC, if mismatch, return 0 (failure to read temperature) */ + uint8_t crc_cal = crc8_ds18b20(sp_arr, 8); + + if(crc_cal != sp_arr[8]) { + return 0; + } + + /* OK, now decode what the temperature reading is. This code assumes + * 12-bit resolution, so this must be modified if the code is modified + * to use any other resolution! */ + int16_t temp_res; + uint8_t temp_lsb = sp_arr[0]; + uint8_t temp_msb = sp_arr[1]; + + temp_res = (int16_t)temp_msb << 8 | temp_lsb; + *temp = (double)temp_res * 0.0625; + + result = 1; + } + return result; +} +/* crc8 algorithm for ds18b20 */ +/* http://www.miscel.dk/MiscEl/CRCcalculations.html */ + +uint8_t +crc8_ds18b20(uint8_t *buf, uint8_t buf_len) +{ + uint8_t result = 0; + uint8_t i, b; + + for(i = 0; i < buf_len; i++) { + result = result ^ buf[i]; + for(b = 1; b < 9; b++) { + if(result & 0x1) { + result = (result >> 1) ^ 0x8C; + } else { + result = result >> 1; + } + } + } + return result; +} +static int +value(int type) +{ + double t; + int ret; + ret = ds18b20_get_temp(&t); + + /* Return temp multiplied by 100 for two decimals */ + if(ret) + return (int) (t * 100); + + /* Error return largest negative value */ + return 0x8000; +} +static int +configure(int type, int c) +{ + ds18b20_probe(); + return 0; +} +static int +status(int type) +{ + return 1; +} +SENSORS_SENSOR(temp_sensor, TEMP_SENSOR, value, configure, status); diff --git a/platform/avr-rss2/dev/temp-sensor.h b/platform/avr-rss2/dev/temp-sensor.h new file mode 100644 index 000000000..b5ab53659 --- /dev/null +++ b/platform/avr-rss2/dev/temp-sensor.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015, Copyright Per Lindgren + * 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. + * + * + * Author : Per Lindgren + * Hacked by: Robert Olsson robert@radio-sensors.com + * Created : 2015-11-22 + */ + +#ifndef TEMP_SENSOR_H_ +#define TEMP_SENSOR_H_ + +#include "lib/sensors.h" +#include +#include "contiki.h" +#include "rss2.h" + +#define DS18B20_1_PIN OW_BUS_0 +#define DS18B20_1_IN PIND +#define DS18B20_1_OUT PORTD +#define DS18B20_1_DDR DDRD + +#define OW_SET_PIN_LOW() (DS18B20_1_OUT &= ~(1 << DS18B20_1_PIN)) +#define OW_SET_PIN_HIGH() (DS18B20_1_OUT |= (1 << DS18B20_1_PIN)) +#define OW_SET_OUTPUT() (DS18B20_1_DDR |= (1 << DS18B20_1_PIN)) +#define OW_SET_INPUT() (DS18B20_1_DDR &= ~(1 << DS18B20_1_PIN)) +#define OW_GET_PIN_STATE() ((DS18B20_1_IN & (1 << DS18B20_1_PIN)) ? 1 : 0) + +#define DS18B20_COMMAND_READ_SCRATCH_PAD 0xBE +#define DS18B20_COMMAND_START_CONVERSION 0x44 +#define DS18B20_COMMAND_SKIP_ROM 0xCC + +/* probe_for_ds18b20 probes for the sensor. Returns 0 on failure, 1 on success + * Assumption: only one sensor on the "1-wire bus", on port DS18B20_1_PIN */ + +extern uint8_t ds18b20_probe(void); +extern uint8_t ds18b20_get_temp(double *temp); +extern uint8_t crc8_ds18b20(uint8_t *buf, uint8_t buf_len); + +extern const struct sensors_sensor temp_sensor; + +#define TEMP_SENSOR "temp" + +#endif /* TEMP_SENSOR_H_ */ diff --git a/platform/avr-rss2/dev/temp_mcu-sensor.c b/platform/avr-rss2/dev/temp_mcu-sensor.c new file mode 100644 index 000000000..cfa21707d --- /dev/null +++ b/platform/avr-rss2/dev/temp_mcu-sensor.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISE OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * ----------------------------------------------------------------- + * + * Author : Robert Olsson + * Created : 2015-10-27 + * Updated : $Date: 2010/08/25 19:30:52 $ + * $Revision: 1.11 $ + */ + +#include "contiki.h" +#include "dev/temp_mcu-sensor.h" +#include +#define delay_us(us) (_delay_loop_2(1 + (us * F_CPU) / 4000000UL)) + +const struct sensors_sensor temp_mcu_sensor; + +/* Returns the MCU temp in C*10 read from the BATMON MCU register + * See AtMega chip docs for BATMON details. + */ + +static int +value(int type) +{ + uint16_t v; + + ADCSRB |= (1 << MUX5); /* this bit buffered till ADMUX written to! */ + ADMUX = 0xc9; + + /* ADC on /32 ADC start */ + ADCSRA = (1 << ADPS2) | (0 << ADPS1) | (1 << ADPS0); + ADCSRA |= (1 << ADEN); /* Enable the ADC */ + + while(!(ADCSRB & (1 << AVDDOK))) ; /* Wait for AVDD ok */ + while(!(ADCSRB & (1 << REFOK))) ; /* Wait for ref ok */ + + ADCSRA |= (1 << ADSC); /* Throwaway conversion */ + while + (ADCSRA & (1 << ADSC)) ; + + ADCSRA |= (1 << ADSC); /* Start conversion */ + while + (ADCSRA & (1 << ADSC)) ; + + v = ADC; + + /* Disable the ADC to save power */ + ADCSRA &= ~_BV(ADEN); + /* ADMUX = 0; //turn off internal vref */ + return (int)((double)(v * 1.13 - 272.8) * 10); +} +static int +configure(int type, int c) +{ + return 0; +} +static int +status(int type) +{ + return 1; +} +SENSORS_SENSOR(temp_mcu_sensor, TEMP_MCU_SENSOR, value, configure, status); + diff --git a/platform/avr-rss2/dev/temp_mcu-sensor.h b/platform/avr-rss2/dev/temp_mcu-sensor.h new file mode 100644 index 000000000..c311fdb16 --- /dev/null +++ b/platform/avr-rss2/dev/temp_mcu-sensor.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * + * ----------------------------------------------------------------- + * + * Author : Robert Olsson + * Created : 2015-10-27 + * Updated : $Date: 2007/11/13 20:36:40 $ + * $Revision: 1.1 $ + */ + +#ifndef TEMP_MCU_SENSOR_H_ +#define TEMP_MCU_SENSOR_H_ + +#include "lib/sensors.h" + +extern const struct sensors_sensor temp_mcu_sensor; + +#define TEMP_MCU_SENSOR "temp_mcu" + +#endif /* TEMP_MCU_SENSOR_H_ */ diff --git a/platform/avr-rss2/ip64-conf.h b/platform/avr-rss2/ip64-conf.h new file mode 100644 index 000000000..26c51a55f --- /dev/null +++ b/platform/avr-rss2/ip64-conf.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2012, Thingsquare, http://www.thingsquare.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. + * + */ +#ifndef IP64_CONF_H +#define IP64_CONF_H + +#include "net/ip64/ip64-eth-interface.h" +#include "dev/enc28j60/enc28j60-ip64-driver.h" +#define IP64_CONF_UIP_FALLBACK_INTERFACE ip64_eth_interface +#define IP64_CONF_INPUT ip64_eth_interface_input +#define IP64_CONF_DHCP 1 +#define IP64_CONF_ETH_DRIVER enc28j60_ip64_driver + +#endif /* IP64_CONF_H */ diff --git a/platform/avr-rss2/params.c b/platform/avr-rss2/params.c new file mode 100644 index 000000000..f2ae2abfc --- /dev/null +++ b/platform/avr-rss2/params.c @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2011, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +#define PRINTF(FORMAT, args ...) printf_P(PSTR(FORMAT),##args) + +#define DEBUG 1 +#if DEBUG +#define PRINTD(FORMAT, args ...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTD(...) +#endif + +#include "contiki.h" +#include +#include +#include +#include + +#if AVR_WEBSERVER +/* #include "httpd-fs.h" */ +/* #include "httpd-cgi.h" */ +#endif + +#include "contiki-net.h" +#include "params.h" + +#if CONTIKI_CONF_RANDOM_MAC +extern uint8_t rng_get_uint8(void); +static void +generate_new_eui64(uint8_t eui64[8]) +{ + eui64[0] = 0x02; + eui64[1] = rng_get_uint8(); + eui64[2] = rng_get_uint8(); + eui64[3] = 0xFF; + eui64[4] = 0xFE; + eui64[5] = rng_get_uint8(); + eui64[6] = rng_get_uint8(); + eui64[7] = rng_get_uint8(); +} +#endif + +#if AVR_WEBSERVER +/* Webserver builds can set these in httpd-fsdata.c via makefsdata.h */ +extern uint8_t default_mac_address[8]; +extern uint8_t default_server_name[16]; +extern uint8_t default_domain_name[30]; +#else +const uint8_t default_mac_address[8] PROGMEM = PARAMS_EUI64ADDR; +const uint8_t default_server_name[] PROGMEM = PARAMS_SERVERNAME; +const uint8_t default_domain_name[] PROGMEM = PARAMS_DOMAINNAME; +#endif + +#if PARAMETER_STORAGE == 0 +/* 0 Hard coded, minmal program and eeprom usage. */ +uint8_t +params_get_eui64(uint8_t *eui64) +{ +#if CONTIKI_CONF_RANDOM_MAC + PRINTD("Generating random EUI64 MAC\n"); + generate_new_eui64(eui64); + return 1; +#else + uint8_t i; + for(i = 0; i < sizeof(default_mac_address); i++) { + eui64[i] = pgm_read_byte_near(default_mac_address + i); + } + return 0; +#endif +} +#elif PARAMETER_STORAGE == 1 +/* 1 Stored in fixed eeprom locations, rewritten from flash if corrupt. + * They can be manually changed and kept over program reflash. + * The channel and bit complement are used to check EEMEM integrity, + * If corrupt all values will be rewritten with the default flash values. + * To make this work, get the channel before anything else. + */ +#if !AVR_WEBSERVER +uint8_t eemem_mac_address[] EEMEM = PARAMS_EUI64ADDR; +uint8_t eemem_server_name[] EEMEM = PARAMS_SERVERNAME; +uint8_t eemem_domain_name[] EEMEM = PARAMS_DOMAINNAME; +#endif /*AVR_WEBSERVER */ + +uint16_t eemem_nodeid EEMEM = PARAMS_NODEID; +uint8_t eemem_channel[2] EEMEM = { PARAMS_CHANNEL, ~PARAMS_CHANNEL }; +uint16_t eemem_panid EEMEM = PARAMS_PANID; +uint16_t eemem_panaddr EEMEM = PARAMS_PANADDR; +uint8_t eemem_txpower EEMEM = PARAMS_TXPOWER; + +#if CONTIKI_CONF_RANDOM_MAC +static uint8_t randomeui64; +#endif + +uint8_t +params_get_channel(void) +{ + uint8_t x[2]; + *(uint16_t *)x = eeprom_read_word((uint16_t *)&eemem_channel); +/* Don't return an invalid channel number */ + if((x[0] < 11) || (x[0] > 26)) { + x[1] = x[0]; + } +/* Do exclusive or test on the two values read */ + if((uint8_t)x[0] != (uint8_t) ~x[1]) { /* ~x[1] can promote comparison to 16 bit */ +/* Verification fails, rewrite everything */ + uint8_t i, buffer[32]; + PRINTD("EEPROM is corrupt, rewriting with defaults.\n"); +#if CONTIKI_CONF_RANDOM_MAC + PRINTD("Generating random EUI64 MAC\n"); + generate_new_eui64(&buffer); + randomeui64 = 1; +#else + for(i = 0; i < sizeof(default_mac_address); i++) { + buffer[i] = pgm_read_byte_near(default_mac_address + i); + } +#endif +/* eeprom_write_block should not be interrupted */ + cli(); + eeprom_write_block(&buffer, &eemem_mac_address, sizeof(eemem_mac_address)); + for(i = 0; i < sizeof(default_server_name); i++) { + buffer[i] = pgm_read_byte_near(default_server_name + i); + } + eeprom_write_block(&buffer, &eemem_server_name, sizeof(eemem_server_name)); + for(i = 0; i < sizeof(default_domain_name); i++) { + buffer[i] = pgm_read_byte_near(default_domain_name + i); + } + eeprom_write_block(&buffer, &eemem_domain_name, sizeof(eemem_domain_name)); + eeprom_write_word(&eemem_panid, PARAMS_PANID); + eeprom_write_word(&eemem_panaddr, PARAMS_PANADDR); + eeprom_write_byte(&eemem_txpower, PARAMS_TXPOWER); + eeprom_write_word(&eemem_nodeid, PARAMS_NODEID); + x[0] = PARAMS_CHANNEL; + x[1] = ~x[0]; + eeprom_write_word((uint16_t *)&eemem_channel, *(uint16_t *)x); + sei(); + } +/* Always returns a valid channel */ + return x[0]; +} +uint8_t +params_get_eui64(uint8_t *eui64) +{ + cli(); + eeprom_read_block((void *)eui64, &eemem_mac_address, sizeof(linkaddr_t)); + sei(); +#if CONTIKI_CONF_RANDOM_MAC + return randomeui64; +#else + return 0; +#endif +} +uint16_t +params_get_panid(void) +{ + return eeprom_read_word(&eemem_panid); +} +uint16_t +params_get_panaddr(void) +{ + return eeprom_read_word(&eemem_panaddr); +} +uint8_t +params_get_txpower(void) +{ + return eeprom_read_byte(&eemem_txpower); +} +#else /* CONTIKI_CONF_SETTINGS_MANAGER */ + +uint8_t +params_get_channel() +{ + uint8_t x; + size_t size = 1; + if(settings_get(SETTINGS_KEY_CHANNEL, 0, (unsigned char *)&x, &size) == SETTINGS_STATUS_OK) { + PRINTD("<-Get RF channel %u\n", x); + } else { + x = PARAMS_CHANNEL; + if(settings_add_uint8(SETTINGS_KEY_CHANNEL, x) == SETTINGS_STATUS_OK) { + PRINTD("->Set EEPROM RF channel to %d\n", x); + } + } + return x; +} +uint8_t +params_get_eui64(uint8_t *eui64) +{ + size_t size = sizeof(linkaddr_t); + if(settings_get(SETTINGS_KEY_EUI64, 0, (unsigned char *)eui64, &size) == SETTINGS_STATUS_OK) { + PRINTD("<-Get EUI64 MAC\n"); + return 0; + } +#if CONTIKI_CONF_RANDOM_MAC + PRINTD("Generating random EUI64 MAC\n"); + generate_new_eui64(eui64); +#else + { uint8_t i; + for(i = 0; i < 8; i++) { + eui64[i] = pgm_read_byte_near(default_mac_address + i); + } + } /* test this */ +#endif + if(settings_add(SETTINGS_KEY_EUI64, (unsigned char *)eui64, 8) == SETTINGS_STATUS_OK) { + PRINTD("->Set EEPROM MAC address\n"); + } +#if CONTIKI_CONF_RANDOM_MAC + return 1; +#else + return 0; +#endif +} +uint16_t +params_get_panid(void) +{ + uint16_t x; + size_t size = 2; + if(settings_get(SETTINGS_KEY_PAN_ID, 0, (unsigned char *)&x, &size) == SETTINGS_STATUS_OK) { + PRINTD("<-Get PAN ID of %04x\n", x); + } else { + x = PARAMS_PANID; + if(settings_add_uint16(SETTINGS_KEY_PAN_ID, x) == SETTINGS_STATUS_OK) { + PRINTD("->Set EEPROM PAN ID to %04x\n", x); + } + } + return x; +} +uint16_t +params_get_panaddr(void) +{ + uint16_t x; + size_t size = 2; + if(settings_get(SETTINGS_KEY_PAN_ADDR, 0, (unsigned char *)&x, &size) == SETTINGS_STATUS_OK) { + PRINTD("<-Get PAN address of %04x\n", x); + } else { + x = PARAMS_PANADDR; + if(settings_add_uint16(SETTINGS_KEY_PAN_ADDR, x) == SETTINGS_STATUS_OK) { + PRINTD("->Set EEPROM PAN address to %04x\n", x); + } + } + return x; +} +uint8_t +params_get_txpower(void) +{ + uint8_t x; + size_t size = 1; + if(settings_get(SETTINGS_KEY_TXPOWER, 0, (unsigned char *)&x, &size) == SETTINGS_STATUS_OK) { + PRINTD("<-Get tx power of %d (0=max)\n", x); + } else { + x = PARAMS_TXPOWER; + if(settings_add_uint8(SETTINGS_KEY_TXPOWER, x) == SETTINGS_STATUS_OK) { + PRINTD("->Set EEPROM tx power of %d (0=max)\n", x); + } + } + return x; +} +#endif /* CONTIKI_CONF_SETTINGS_MANAGER */ diff --git a/platform/avr-rss2/params.h b/platform/avr-rss2/params.h new file mode 100644 index 000000000..95150333b --- /dev/null +++ b/platform/avr-rss2/params.h @@ -0,0 +1,108 @@ +#ifndef __PARAMS_H__ +#define __PARAMS_H__ +/* PARAMETER_STORAGE = + * 0 Hard coded, minmal program and eeprom usage. + * 1 Stored in fixed eeprom locations, rewritten from flash if corrupt. + * This allows parameter changes using a hardware programmer or custom application code. + * Corruption test is based on channel verify so get the channel before anything else! + * 2 Obtained from eeprom using the general settings manager and read from program flash if not present. + * Useful for for testing builds without wearing out flash memory. + * 3 Obtained from eeprom using the settings manager and rewritten from flash if not present. + * This ensures all parameters are present in upper eeprom flash. + * + * Note the parameters in this file can be changed without forcing a complete rebuild. + */ +#define CONTIKI_CONF_RANDOM_MAC 0 /* adds 78 bytes */ +#define CONTIKI_CONF_SETTINGS_MANAGER 0 /* adds 1696 bytes */ + +#if CONTIKI_CONF_SETTINGS_MANAGER +/* #define PARAMETER_STORAGE 2 */ +#define PARAMETER_STORAGE 2 +#else +#define PARAMETER_STORAGE 1 +#endif + +/* Include settings.h, then dummy out the write routines */ +#include "settings.h" +#if PARAMETER_STORAGE == 2 +#define settings_add(...) 0 +#define settings_add_uint8(...) 0 +#define settings_add_uint16(...) 0 +#endif + +#if AVR_WEBSERVER +/* Webserver builds can set some defaults in httpd-fsdata.c via makefsdata.h */ +extern uint8_t eemem_mac_address[8]; +extern uint8_t eemem_server_name[16]; +extern uint8_t eemem_domain_name[30]; +#endif + +#ifdef SERVER_NAME +#define PARAMS_SERVERNAME SERVER_NAME +#else +#define PARAMS_SERVERNAME "ATMEGA256rfr2" +#endif +#ifdef DOMAIN_NAME +#define PARAMS_DOMAINNAME DOMAIN_NAME +#else +#define PARAMS_DOMAINNAME "localhost" +#endif +#ifdef NODE_ID +#define PARAMS_NODEID NODE_ID +#else +#define PARAMS_NODEID 0 +#endif +#ifdef CHANNEL_802_15_4 +#define PARAMS_CHANNEL CHANNEL_802_15_4 +#else +#define PARAMS_CHANNEL 26 +#endif +#ifdef IEEE802154_PANID +#define PARAMS_PANID IEEE802154_PANID +#else +#define PARAMS_PANID 0xABCD +#endif +#ifdef IEEE802154_PANADDR +#define PARAMS_PANADDR IEEE802154_PANADDR +#else +#define PARAMS_PANADDR 0 +#endif +#ifdef RF230_MAX_TX_POWER +#define PARAMS_TXPOWER RF230_MAX_TX_POWER +#else +#define PARAMS_TXPOWER 0 +#endif +#ifdef EUI64_ADDRESS +#define PARAMS_EUI64ADDR EUI64_ADDRESS +#else +/* This form of of EUI64 mac allows full 6LoWPAN header compression from mac address */ +#if UIP_CONF_LL_802154 +/* #define PARAMS_EUI64ADDR {0x02, 0xNN, 0xNN, 0xNN, 0xNN, 0xNN, 0xNN, 0xNN} */ +#define PARAMS_EUI64ADDR { 0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x01 } +#else +/* #define PARAMS_EUI64ADDR {0x02, 0xNN, 0xNN, 0xff, 0xfe, 0xNN, 0xNN, 0xNN} */ +#define PARAMS_EUI64ADDR { 0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x01 } +#endif +/* This form of of EUI64 mac allows 16 bit 6LoWPAN header compression on multihops */ +/* #define PARAMS_EUI64ADDR {0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0xNN, 0xNN} */ +#endif + +uint8_t params_get_eui64(uint8_t *eui64); +#if PARAMETER_STORAGE == 0 +/* Hard coded program flash parameters */ +#define params_get_servername(...) +#define params_get_nodeid(...) PARAMS_NODEID +#define params_get_channel(...) PARAMS_CHANNEL +#define params_get_panid(...) PARAMS_PANID +#define params_get_panaddr(...) PARAMS_PANADDR +#define params_get_txpower(...) PARAMS_TXPOWER +#else +/* Parameters stored in eeprom */ +uint16_t params_get_nodeid(void); +uint8_t params_get_channel(void); +uint16_t params_get_panid(void); +uint16_t params_get_panaddr(void); +uint8_t params_get_txpower(void); +#endif + +#endif /* __PARAMS_H__ */ diff --git a/platform/avr-rss2/rss2.h b/platform/avr-rss2/rss2.h new file mode 100644 index 000000000..46ade3822 --- /dev/null +++ b/platform/avr-rss2/rss2.h @@ -0,0 +1,36 @@ + +/* + Pin assigments for Radio Sensors board revision 2.3 + using MCU AtMega128rfa1 + */ + +#define ISP_1 PB1 /* SCK */ +#define ISP_2 PB2 /* MOSI */ +#define ISP_3 PB3 /* MISO */ + +#define LED_YELLOW PE3 /* 1k pullup to Vcc */ +#define LED_RED PE4 /* 1k pullup to Vcc */ +#define USB_PWR PB5 /* High if FTDI TTL-USB cable sources */ +#define P0 PD2 /* Pulse count input. Pullup via jumper */ +#define P1 PD3 /* Pulse count input via optional Comparator */ +#define PWR_1 PE7 /* Programmable power pin Vcc via P-FET */ + +#define AV_IN PF0 /* V_IN ADC input. 100k/1M volt. divider */ +#define A1 PF1 /* A1 ADC input. 100k/300k volt. divider */ +#define A2 PF2 /* A2 ADC input 100k/300k volt. divider */ +#define A3 PF3 /* Light sensor A3 ADC input 100k/100k volt. divider */ +#define A3_PWR PF4 /* Light sensor power A3_PWR */ + +#define RX0 PE0 /* RX UART0 -- FTDI TTL-USB cable */ +#define TX0 PE1 /* TX UART0 -- FTDI TTL-USB cable */ + +#define OW_BUS_0 PD7 /* One-Wire bus w temp/ID Pulled Up. Separate Vcc */ +#define OW_BUS_1 PD6 /* One-Wire bus extra Pulled Up. Separate Vcc */ + +/* AVR ISP standard connected */ +/* 16 MHz xtal */ +/* RTC 32.768 Hz xtal */ + +/*Optional HIH610 connected on SPI */ +#define HUM_PWR PE2 /* Power pin for HIH6130 also to ena. HIH 6130 Alarm mode */ + diff --git a/platform/avr-rss2/slip_uart0.c b/platform/avr-rss2/slip_uart0.c new file mode 100644 index 000000000..8f064f980 --- /dev/null +++ b/platform/avr-rss2/slip_uart0.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2010, University of Colombo School of Computing + * 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 + * Machine dependent AVR SLIP routines for UART0. + * \author + * Kasun Hewage + */ + +#include +#include "contiki.h" +#include "dev/rs232.h" +#include "slip.h" + +/*---------------------------------------------------------------------------*/ +static int +slip_putchar(char c, FILE *stream) +{ +#define SLIP_END 0300 + static char debug_frame = 0; + + if(!debug_frame) { /* Start of debug output */ + slip_arch_writeb(SLIP_END); + slip_arch_writeb('\r'); /* Type debug line == '\r' */ + debug_frame = 1; + } + + slip_arch_writeb((unsigned char)c); + + /* + * Line buffered output, a newline marks the end of debug output and + * implicitly flushes debug output. + */ + if(c == '\n') { + slip_arch_writeb(SLIP_END); + debug_frame = 0; + } + + return c; +} +/*---------------------------------------------------------------------------*/ +static FILE slip_stdout = FDEV_SETUP_STREAM(slip_putchar, NULL, + _FDEV_SETUP_WRITE); +/*---------------------------------------------------------------------------*/ +void +slip_arch_init(unsigned long ubr) +{ + rs232_set_input(SLIP_PORT, slip_input_byte); + stdout = &slip_stdout; +} +/*---------------------------------------------------------------------------*/ +/* + XXX: + Currently, the following function is in cpu/avr/dev/rs232.c file. this + should be moved to here from there hence this is a platform specific slip + related function. + void + slip_arch_writeb(unsigned char c) + { + rs232_send(RS232_PORT_0, c); + } + */ diff --git a/platform/avr-zigbit/contiki-conf.h b/platform/avr-zigbit/contiki-conf.h index f84df8863..c01c6555c 100644 --- a/platform/avr-zigbit/contiki-conf.h +++ b/platform/avr-zigbit/contiki-conf.h @@ -88,7 +88,6 @@ void clock_adjust_ticks(clock_time_t howmany); #endif #define LINKADDR_CONF_SIZE 8 -#define PACKETBUF_CONF_HDR_SIZE 0 //define NETSTACK_CONF_WITH_IPV6 1 //Let the makefile do this, allows hello-world to compile #if NETSTACK_CONF_WITH_IPV6 @@ -100,7 +99,6 @@ void clock_adjust_ticks(clock_time_t howmany); /* The new NETSTACK interface requires RF230BB */ #if RF230BB #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 -#undef PACKETBUF_CONF_HDR_SIZE //RF230BB takes the packetbuf default for header size #define UIP_CONF_LLH_LEN 0 /* No radio cycling */ @@ -126,7 +124,6 @@ void clock_adjust_ticks(clock_time_t howmany); #else /* Original combined RF230/mac code will not compile with current contiki stack */ -//#define PACKETBUF_CONF_HDR_SIZE 0 //RF230 handles headers internally //FTH081105 #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #define SICSLOWPAN_CONF_MAXAGE 5 diff --git a/platform/c128/Makefile.c128 b/platform/c128/Makefile.c128 index b186fac60..0c674ee38 100644 --- a/platform/c128/Makefile.c128 +++ b/platform/c128/Makefile.c128 @@ -31,7 +31,7 @@ # Author: Oliver Schmidt # -CONTIKI_TARGET_SOURCEFILES += lseek.c pfs.S pfs_write.S +CONTIKI_TARGET_SOURCEFILES += exec.c lseek.c pfs.S pfs_remove.S pfs_seek.S pfs_write.S CONTIKI_CPU = $(CONTIKI)/cpu/6502 include $(CONTIKI_CPU)/Makefile.6502 @@ -46,16 +46,16 @@ endif disk: all $(C1541) -format contiki,00 d71 contiki.d71 - $(C1541) -attach contiki.d71 -write $(CONTIKI_PROJECT).$(TARGET) contiki,p - $(C1541) -attach contiki.d71 -write $(CONTIKI)/tools/$(TARGET)/sample.cfg contiki.cfg,s - $(C1541) -attach contiki.d71 -write cs8900a.eth cs8900a.eth,s - $(C1541) -attach contiki.d71 -write lan91c96.eth lan91c96.eth,s + $(C1541) -attach contiki.d71 -write $(CONTIKI_PROJECT).$(TARGET) contiki,p + $(C1541) -attach contiki.d71 -write $(CONTIKI)/tools/$(TARGET)/sample.cfg contiki.cfg,s + $(C1541) -attach contiki.d71 -write cs8900a.eth cs8900a.eth,s + $(C1541) -attach contiki.d71 -write lan91c96.eth lan91c96.eth,s ifeq ($(findstring WITH_MOUSE,$(DEFINES)),WITH_MOUSE) - $(C1541) -attach contiki.d71 -write $(CC65_HOME)/mou/c128-1351.mou contiki.mou,s + $(C1541) -attach contiki.d71 -write $(CC65_TARGET_DIR)/drv/mou/c128-1351.mou contiki.mou,s endif ifeq ($(HTTPD-CFS),1) - $(C1541) -attach contiki.d71 -write httpd-cfs/index.htm index.htm,s - $(C1541) -attach contiki.d71 -write httpd-cfs/backgrnd.gif backgrnd.gif,s - $(C1541) -attach contiki.d71 -write httpd-cfs/contiki.gif contiki.gif,s - $(C1541) -attach contiki.d71 -write httpd-cfs/notfound.htm notfound.htm,s + $(C1541) -attach contiki.d71 -write httpd-cfs/index.htm index.htm,s + $(C1541) -attach contiki.d71 -write httpd-cfs/backgrnd.gif backgrnd.gif,s + $(C1541) -attach contiki.d71 -write httpd-cfs/contiki.gif contiki.gif,s + $(C1541) -attach contiki.d71 -write httpd-cfs/notfound.htm notfound.htm,s endif diff --git a/platform/c128/lib/exec.c b/platform/c128/lib/exec.c new file mode 100644 index 000000000..5a633d45d --- /dev/null +++ b/platform/c128/lib/exec.c @@ -0,0 +1,139 @@ +/* +** Program-chaining function for Commodore platforms. +** +** This copy of the cc65 system library function makes smaller code by using +** Contiki's Personal File System (instead of POSIX) functions. +** +** 2016-03-16, Greg King +** +** This function exploits the program-chaining feature in CBM BASIC's ROM. +** +** CC65's CBM programs have a BASIC program stub. We start those programs by +** RUNning that stub; it SYSes to the Machine Language code. Normally, after +** the ML code exits, the BASIC ROM continues running the stub. But, it has +** no more statements; so, the program stops. +** +** This function puts the desired program's name and device number into a LOAD +** statement. Then, it points BASIC to that statement, so that the ROM will run +** that statement after this program quits. The ROM will load the next program, +** and will execute it (because the LOAD will be seen in a running program). +*/ + +#include +#include +#include +#include +#include + +#include "cfs.h" + + +/* The struct below is a line of BASIC code. It sits in the LOWCODE segment +** to make sure that it won't be hidden by a ROM when BASIC is re-enabled. +** The line is: +** 0 CLR:LOAD""+"" ,01 +** After this function has written into the line, it might look like this: +** 0 CLR:LOAD""+"program name" ,08 +** +** When BASIC's LOAD command asks the Kernal to load a file, it gives the +** Kernal a pointer to a file-name string. CC65's CBM programs use that +** pointer to give a copy of the program's name to main()'s argv[0] parameter. +** But, when BASIC uses a string literal that is in a program, it points +** directly to that literal -- in the models that don't use banked RAM +** (Pet/CBM, VIC-20, and 64). The literal is overwritten by the next program +** that is loaded. So, argv[0] would point to machine code. String operations +** create a new result string -- even when that operation changes nothing. The +** result is put in the string space at the top of BASIC's memory. So, the ""+ +** in this BASIC line guarantees that argv[0] will get a name from a safe place. +*/ +#pragma data-name(push, "LOWCODE") +static struct line { + const char end_of_line; /* fake previous line */ + const struct line* const next; + const unsigned line_num; + const char CLR_token, colon, LOAD_token, quotes[2], add_token, quote; + char name[21]; + const char comma; + char unit[3]; +} basic = { + '\0', &basic + 1, /* high byte of link must be non-zero */ + 0, 0x9C, ':', 0x93, "\"\"", 0xAA, '\"', + "\" ", /* format: "123:1234567890123456\"" */ + ',', "01" +}; +#pragma data-name(pop) + +/* These values are platform-specific. */ +extern const void* vartab; /* points to BASIC program variables */ +#pragma zpsym("vartab") +extern const void* memsize; /* points to top of BASIC RAM */ +#pragma zpsym("memsize") +extern const struct line* txtptr; /* points to BASIC code */ +#pragma zpsym("txtptr") +extern char basbuf[]; /* BASIC's input buffer */ +extern void basbuf_len[]; +#pragma zpsym("basbuf_len") + + +int __fastcall__ +exec(const char *progname, const char *cmdline) +{ + static int fd; + static unsigned char dv, n; + + /* Exclude devices that can't load files. */ + /* (Use hand optimization, to make smaller code.) */ + dv = getcurrentdevice(); + if(dv < 8 && __AX__ != 1 || __AX__ > 30) { + return _mappederrno(9); /* illegal device number */ + } + utoa(dv, basic.unit, 10); + + /* Tape files can be openned only once; skip this test for the Datasette. */ + if(dv != 1) { + /* Don't try to run a program that can't be found. */ + fd = cfs_open(progname, CFS_READ); + if(fd < 0) { + return -1; + } + cfs_close(fd); + } + + n = 0; + do { + if((basic.name[n] = progname[n]) == '\0') { + break; + } + } while(++n < 20); /* truncate long names */ + basic.name[n] = '\"'; + +/* This next part isn't needed by machines that put +** BASIC source and variables in different RAM banks. +*/ +#if !defined(__C128__) + /* cc65 program loads might extend beyond the end of the RAM that is allowed + ** for BASIC. Then, the LOAD statement would complain that it is "out of + ** memory". Some pointers that say where to put BASIC program variables + ** must be changed, so that we do not get that error. One pointer is + ** changed here; a BASIC CLR statement changes the others. Some space is + ** needed for the file-name string. Subtracting an entire RAM page allows + ** better optimization of this expression. + */ + vartab = (char*)memsize - 0x0100; +#endif + + /* Build the next program's argument list. */ + basbuf[0] = 0x8F; /* REM token */ + basbuf[1] = '\0'; + if(cmdline != NULL) { + strncat(basbuf, cmdline, (size_t)basbuf_len - 2); + } + + /* Tell the ROM where to find that BASIC program. */ + txtptr = &basic; + + /* (The return code, in ST [status], will be destroyed by LOAD. + ** So, don't bother to set it here.) + */ + exit(__AX__); +} diff --git a/platform/c128/lib/pfs.S b/platform/c128/lib/pfs.S index acec45959..7947b67d8 100644 --- a/platform/c128/lib/pfs.S +++ b/platform/c128/lib/pfs.S @@ -29,99 +29,212 @@ ; This file is part of the Contiki operating system. ; ; Author: Kajtar Zsolt +; Author: Greg King ; ;--------------------------------------------------------------------- - .define F_IDE64 0 ; support IDE64, not on C128 +.define F_IDE64 0 ; C128 doesn't have IDE64 - .constructor init_pfs - .destructor done_pfs - .importzp ptr1, ptr2, ptr3, sp - .import curunit, __filetype, popax, addysp, subysp - .export pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend - .if F_IDE64 - .export ide64_rwprepare, ide64_rwfinish - .endif - .export _pfs_open, _pfs_read, _pfs_close + .constructor init_pfs + .destructor done_pfs + .importzp sp, ptr1, ptr2, ptr3 + .import curunit, __filetype, popax, addysp, subysp + .export pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend +.if F_IDE64 + .export ide64_rwprepare, ide64_rwfinish +.endif + .export cmdc, flags + .export pfs_makename, pfs_scratch + + .export _pfs_open, _pfs_read, _pfs_close ;--------------------------------------------------------------------- -F_EOF = $80 -F_NBLK = $40 -F_OPEN = $20 -F_MAXLEN = 80 ;max filename length -ST = $90 ;status -FN = $BB ;filename -FNL = $B7 ;filenamelength -LF = $B8 ;logical file number -SA = $B9 ;secondary address -OPEN = $FFC0 -CLOSE = $FFC3 -CHKIN = $FFC6 -CHKOUT = $FFC9 -CLRCHN = $FFCC -CHRIN = $FFCF -CHROUT = $FFD2 -SETLFS = $FFBA -SETNAM = $FFBD -CLALL = $FFE7 -WRITE = $DEF1 -READ = $DEF4 +MAXLEN = 80 ;maximum filename length + +; Flag bits +F_EOF = %10000000 ;end of file +F_NBLK = %01000000 ;block read/write not available +F_OPEN = %00100000 + +; Kernal variables +ST := $90 ;status +FN := $BB ;filename +FNL := $B7 ;filename length +LF := $B8 ;logical file number + +OPNVec := $031A ;address vector to OPEN function's code + +; IDEDOS function +READ := $DEF4 + +; Kernal functions +SETLFS := $FFBA +SETNAM := $FFBD +OPEN := $FFC0 +CLOSE := $FFC3 +CHKIN := $FFC6 +CHKOUT := $FFC9 +CLRCHN := $FFCC +CHRIN := $FFCF +CHROUT := $FFD2 ;--------------------------------------------------------------------- .data -illchr: .byte $3A, $2A, $3F, $3D ;illegal chars -pw: .byte $2C, $50, $2C, $57 ;,p,w +; illchr and sw must stay together because the comma, also, is illegal in names. +illchr: .byte "*?:=" ;illegal chars +sw: .byte ",s,w" cmdc: .byte 0 -flags: .res 10 +flags: .res 10 ;(Kernal allows only ten open files) ;--------------------------------------------------------------------- - .segment "INIT" + .segment "ONCE" init_pfs: - ldy #F_MAXLEN+8 - jsr subysp ;allocate - lda #0 - sta FNL ;no name - ldy #15-1 - jsr open2 ;open command channel + ldy #MAXLEN + 8 + jsr subysp ;allocate because open2 will free it + lda #0 ;no name, file number 1 + sta FNL + ldy #15 - 1 ;secondary address 15 + jsr open2 ;open command channel sta cmdc rts ;--------------------------------------------------------------------- .code -error3: jmp error - _pfs_open: - sta ptr2 - ; Pop and store name + sta ptr2 ;save open-mode flags + + ; Get and store name jsr popax + jsr pfs_makename + lda FNL + beq error ;must have a filename + + lda #2 - 1 ;file number + tay ;secondary address +open2: sta ptr2 + sty ptr2 + 1 + +next: inc ptr2 ;next file number + ldx ptr2 ;file number + cpx #.sizeof(flags) + 1 + bcs error ;no more files + lda flags - 1,x + bne next ;already used + lda ptr2 + 1 + bne nextsa + inx + stx ptr2 + 1 +nextsa: inc ptr2 + 1 ;next channel +retr: lda ptr2 ;file number + ldx curunit + ldy ptr2 + 1 ;secondary address (channel number) + jsr SETLFS + jsr OPEN ;open a pair of files (in computer and drive) + bcs oerr ;branch if could not open computer file + ldx cmdc + beq opok ;branch if error channel just was openned + jsr CHKIN + bcs error + jsr CHRIN + pha ;first digit of error code + jsr CHRIN + sta ptr1 ;second digit +@L4: jsr CHRIN ;flush status message + lda ST + beq @L4 + jsr CLRCHN + pla + cmp #'2' + bcc opok ;no serious error + pha + lda ptr2 + jsr CLOSE ;close computer file + pla + ldx ptr1 + cmp #'7' ;no channel? + bne nnoc + cpx #'0' + bne error ;not "no channel" + lda ptr2 + 1 + cmp #14 + bcc nextsa ;try next channel + bcs error ;give up + +opok: ldx ptr2 + lda #F_OPEN + sta flags - 1,x + txa ;OK, return file number +ret0: ldx #>$0000 +ret: ldy #MAXLEN + 8 ;free filename space + jmp addysp + +oerr: dec ptr2 + 1 + cmp #2 ;already open, + beq next ;retry with next + +error: lda #<-1 + tax ;failed + bne ret + +nnoc: inc ptr3 + bne error ;no retry + cmp #'6' + bne error ;not "file exists" + cpx #'3' + bne error + jsr pfs_scratch + bcc retr + bcs error ;branch always + +pfs_scratch: + ldx cmdc + jsr CHKOUT + bcs @L5 + ldy #1 + lda #'s' ;scratch +@L4: jsr CHROUT + lda (FN),y + iny + cmp #',' + bne @L4 + lda #$0D ;carriage return + jsr CHROUT + jsr CLRCHN + clc ;carry = 0: OK +@L5: rts ;carry = 1: error + +pfs_makename: sta FN - stx FN+1 ;filename (kernal) - ldy #F_MAXLEN+8 - jsr subysp ;allocate name - ldy #255 + stx FN+1 ;Kernal filename pointer + ldy #MAXLEN + 8 + jsr subysp ;allocate name space + + ; Validate the name; and, find its length + ldy #<-1 sty ptr3 sty ptr1 @L10: iny - cpy #F_MAXLEN - bcs error3 ;too long... - ldx #4 ;4+1 (comma) + cpy #MAXLEN + bcs badchr ;too long + lda (FN),y + ldx #.sizeof(illchr); 4 + 1 (includes comma) @L12: cmp illchr,x - beq error3 ;illegal char? + beq badchr ;illegal char dex bpl @L12 - cmp #$2F + cmp #'/' bne @L11 - sty ptr1 ;last slash -@L11: lda (FN),y + sty ptr1 ;last slash +@L11: tax ;test for '\0' bne @L10 - sty FNL + cpy #0 + beq badchr ;no name - tay - tax - lda #$30 ;this partition + tay ;zero index reg. + lda #'0' ;drive 0 or current partition sta (sp),y iny inc ptr1 beq nopath - lda #$2F + lda #'/' @L13: sta (sp),y iny lda (FN,x) @@ -130,158 +243,67 @@ _pfs_open: inc FN+1 @L14: cpy ptr1 bcc @L13 - lda #$2F + ;lda #'/' ; (.A already has a slash) sta (sp),y iny -nopath: lda #$3A +nopath: lda #':' @L16: sta (sp),y iny lda (FN,x) inc FN bne @L15 inc FN+1 -@L15: ora #0 +@L15: ora #$00 ;test for '\0' bne @L16 lsr ptr2 - bcs ro ;read only + bcs ro ;read-only (read-write not supported) lda __filetype - sta pw+1 ;set filetype - ldx #252 -@L20: lda pw-252,x - sta (sp),y ;write + sta sw + 1 ;set filetype + lsr ptr2 + lda #'w' ;write-only + lsr ptr2 + bcc write + lda #'a' ;append +write: sta sw + 3 ;set mode + ldx #$0100 - .sizeof(sw) +@L20: lda sw - ($0100 - .sizeof(sw)),x + sta (sp),y iny inx bne @L20 -ro: tya ;name length (kernal) +ro: tya ;pathname length ldx sp ldy sp+1 - jsr SETNAM +namset: jmp SETNAM - lda #0 ;file number - tay ;secondary address -open2: sta ptr2 - sty ptr2+1 - -next: inc ptr2 ;next file number - ldx ptr2 ;file number - cpx #11 - bcs error ;no more files - lda flags-1,x - bne next ;already used - lda ptr2+1 - bne nextsa - inx - stx ptr2+1 -nextsa: inc ptr2+1 ;next channel -retr: lda ptr2 ;file number - ldx curunit - ldy ptr2+1 ;secondary address - jsr SETLFS - jsr OPEN ;open - bcs oerr - ldx cmdc - beq opok ;error channel open - jsr CHKIN - bcs error - jsr CHRIN - pha - jsr CHRIN - sta ptr1 -@L4: jsr CHRIN - lda ST - beq @L4 - jsr CLRCHN - pla - tax - lsr - cmp #$18 ;no serious error - beq opok - txa - pha - lda ptr2 - jsr CLOSE ;close - pla - ldx ptr1 - cmp #$37 ;no channel? - bne nnoc - cpx #$30 - bne error ;not no channel - lda ptr2+1 - cmp #14 - bcc nextsa ;try next channel - bcs error ;give up - -opok: ldx ptr2 - lda #F_OPEN - sta flags-1,x - txa ;ok, return file number - ldx #0 -ret: ldy #F_MAXLEN+8 ; free filename - jmp addysp - -oerr: dec ptr2+1 - cmp #2 ;already open, - beq next ;retry with next - -error: lda #$FF - tax ;failed - bne ret - -nnoc: inc ptr3 - bne error ;no retry - cmp #$36 - bne error ;no exists - cpx #$33 - bne error - ldx cmdc - jsr CHKOUT - bcs error - lda FNL - sec - sbc #5 - tax - lda #$53 ;scratch - jsr CHROUT - ldy #1 -@L4: lda (FN),y - iny - jsr CHROUT - dex - bne @L4 - lda #$3D - jsr CHROUT - iny - lda (FN),y - jsr CHROUT - lda #$0d - jsr CHROUT - jsr CLRCHN - jmp retr +badchr: lda #0 + beq namset .proc _pfs_read jsr pfs_rwcommon ; pop params, check handle beq error2 ; not open bmi eof - .if F_IDE64 - asl + +.if F_IDE64 + asl a bmi nblk ; no block operation jsr CHKIN bcs error2 - + ; check support jsr ide64_rwprepare bcs norm - - ; read + + ; do a block read jsr READ bcs nosup jmp ide64_rwfinish nosup: lda #F_NBLK jsr pfs_rwsetflags - .endif +.endif ; Valid lfn. Make it the input file nblk: jsr CHKIN @@ -292,15 +314,15 @@ norm: ldy #0 @L3: inc ptr1 bne @L0 inc ptr1+1 - beq done ; branch always + beq done ; Read the next byte @L0: jsr CHRIN tax ; save the input byte - lda ST ; read the IEEE status - cmp #1 ; save it - and #%10111111 ; check anything but the EOI bit + lda ST ; read the file status + cmp #$01 ; save it + and #%10111111 ; check anything but the EOF bit bne error5 ; assume device not present ; Store the byte just read @@ -310,45 +332,60 @@ norm: ldy #0 bne @L1 inc ptr2+1 ; *buf++ = A; - ; Get the status again and check the EOI bit -@L1: bcc @L3 ; loop if no end of file + ; Get the status again; and, check the EOF bit +@L1: bcc @L3 ; loop if not end of file - ; Set the EOI flag and bail out + ; Set the EOF flag; and, bail out lda #F_EOF jsr pfs_rwsetflags - ; Read done, close the input channel -done: jsr CLRCHN ; clrchn + ; Read done; cancel the input channel +done: jsr CLRCHN ; Return the number of chars read -eof: jmp pfs_rwcommonend +eof: +; jmp pfs_rwcommonend ; (fall through) +.endproc + +.proc pfs_rwcommonend + lda ptr2 + sec + sbc ptr3 + pha + lda ptr2+1 + sbc ptr3+1 + tax + pla + rts .endproc - ; Error entry, file is not open done_pfs: - ldx #10 -@L2: ldy flags-1,x ; file open? + ldx #.sizeof(flags) +@L2: ldy flags - 1,x ; file open? beq @L1 txa - jsr _pfs_close + jsr close1 @L1: dex - bne @L2 + bne @L2 rts -error5: jsr CLRCHN ; clrchn +error5: jsr CLRCHN -error2: ldx #255 + ; Error entry, file is not open +error2: ldx #>-1 txa rts _pfs_close: - pha - jsr CLOSE ;close + cmp #.sizeof(flags) + 1 + bcs close0 ; don't close if not valid file number +close1: pha + jsr CLOSE pla tax - lda #0 - sta flags-1,x - rts + lda #$00 + sta flags - 1,x +close0: rts ; .X = file number .proc pfs_rwcommon eor #$FF @@ -366,70 +403,56 @@ _pfs_close: jsr popax ; get the handle sta LF - lda #0 - beq pfs_rwsetflags + lda #$00 +; beq pfs_rwsetflags ; (fall through) .endproc - .if F_IDE64 -.proc ide64_rwprepare - sec - lda ptr1+1 - eor #255 - beq small ; too small, not worth it - tay - lda ptr1 ; setup registers - eor #255 - tax - lda $031B - eor #$DE - bne noide ; open vector set? - lda $DE60 - eor #$49 - bne noide ; check identification - lda $DE61 - eor #$44 - bne noide - lda $DE62 - eor #$45 - bne noide - clc - lda #ptr2 -small: rts - -noide: lda #F_NBLK - bne pfs_rwsetflags -.endproc - .endif - .proc pfs_rwsetflags ldx LF - ora flags-1,x - sta flags-1,x + ora flags - 1,x + sta flags - 1,x rts .endproc - .if F_IDE64 +.if F_IDE64 +.proc ide64_rwprepare + sec ; assume it won't use IDEDOS + lda ptr1+1 + eor #$FF ; convert -count-1 back to count + beq small ; too small, not worth it + tay + lda ptr1 ; set up registers + eor #$FF + tax + lda OPNVec+1 + eor #>$DE00 + bne noide ; is OPEN vector set to IDEDOS? + lda $DE60 + eor #'i' + bne noide ; check identification + lda $DE61 + eor #'d' + bne noide + lda $DE62 + eor #'e' + bne noide + clc ; it will use IDEDOS + lda #ptr2 +small: rts + +noide: lda #F_NBLK + bne pfs_rwsetflags +.endproc + .proc ide64_rwfinish - txa + txa ; push .YX pha tya pha jsr CLRCHN - pla - tax - pla - rts -.endproc - .endif - -.proc pfs_rwcommonend - lda ptr2 - sec - sbc ptr3 - pha - lda ptr2+1 - sbc ptr3+1 + pla ; pull .XA tax pla rts .endproc +.endif diff --git a/platform/c128/lib/pfs_remove.S b/platform/c128/lib/pfs_remove.S new file mode 100644 index 000000000..7477e4314 --- /dev/null +++ b/platform/c128/lib/pfs_remove.S @@ -0,0 +1,59 @@ +; +; Copyright (c) 2016, Greg King +; 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 author nor the names of contributors +; may be used to endorse or promote products derived from this software +; without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +; +; Author: Greg King +; +;--------------------------------------------------------------------- + .importzp ptr2 + .import addysp + .import pfs_makename, pfs_scratch + + .export _pfs_remove +;--------------------------------------------------------------------- +MAXLEN = 80 ; max. filename length + +FNL := $B7 ; filename length +;--------------------------------------------------------------------- +.proc _pfs_remove + asl ptr2 ; force pfs_makename to format for pfs_scratch + jsr pfs_makename + ldx FNL + beq error ; no name + + jsr pfs_scratch + ldx #>$0000 + bcs error +ret: txa + ldy #MAXLEN + 8 ; free filename space + jmp addysp + +error: dex ;(ldx #>-1) + bne ret +.endproc diff --git a/platform/c128/lib/pfs_seek.S b/platform/c128/lib/pfs_seek.S new file mode 100644 index 000000000..4ef0014d1 --- /dev/null +++ b/platform/c128/lib/pfs_seek.S @@ -0,0 +1,46 @@ +; +; Copyright (c) 2016, Greg King +; 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 author nor the names of contributors +; may be used to endorse or promote products derived from this software +; without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +; +; Author: Greg King +; +;--------------------------------------------------------------------- + .importzp sp, sreg, ptr1, ptr2, ptr3 + .import popax, incsp6 + .import cmdc, flags + + .export _pfs_seek +;--------------------------------------------------------------------- +.proc _pfs_seek + lda #<-1 ; seek not implemented + tax + stx sreg ; return long data type + stx sreg+1 + jmp incsp6 ; drop int and long arguments from stack +.endproc diff --git a/platform/c128/lib/pfs_write.S b/platform/c128/lib/pfs_write.S index 0fc8e3160..e17ff91b7 100644 --- a/platform/c128/lib/pfs_write.S +++ b/platform/c128/lib/pfs_write.S @@ -31,27 +31,33 @@ ; Author: Kajtar Zsolt ; ;--------------------------------------------------------------------- - .define F_IDE64 0 ; support IDE64, 100 byte only +.define F_IDE64 0 ; c128 doesn't have IDE64 - .importzp ptr1, ptr2 - .import pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend - .if F_IDE64 - .import ide64_rwprepare, ide64_rwfinish - .endif - .export _pfs_write + .importzp ptr1, ptr2 + .import pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend +.if F_IDE64 + .import ide64_rwprepare, ide64_rwfinish +.endif + + .export _pfs_write ;--------------------------------------------------------------------- -F_NBLK = $40 -ST = $90 ;status -CHKOUT = $FFC9 -CLRCHN = $FFCC -CHROUT = $FFD2 -WRITE = $DEF1 +F_NBLK = %01000000 ;block read/write not available + +ST := $90 ;status + +; IDEDOS function +WRITE := $DEF1 + +; Kernal functions +CHKOUT := $FFC9 +CLRCHN := $FFCC +CHROUT := $FFD2 ;--------------------------------------------------------------------- .code -error5: jsr CLRCHN ; clrchn +error5: jsr CLRCHN -error2: ldx #255 +error2: ldx #>-1 txa rts @@ -59,8 +65,8 @@ error2: ldx #255 jsr pfs_rwcommon ; pop params, check handle beq error2 ; not open - .if F_IDE64 - asl +.if F_IDE64 + asl a bmi nblk ; no block operation jsr CHKOUT @@ -70,7 +76,7 @@ error2: ldx #255 jsr ide64_rwprepare bcs norm - ; write + ; do a block write jsr WRITE bcs nosup jmp ide64_rwfinish @@ -98,10 +104,9 @@ norm: ldy #0 lda ST beq @L3 bne error5 ; bail out on errors -@L2: - ; Wrote all chars, close the output channel - jsr CLRCHN + ; Wrote all chars.; cancel the output channel +@L2: jsr CLRCHN ; Return the number of chars written jmp pfs_rwcommonend diff --git a/platform/c64/Makefile.c64 b/platform/c64/Makefile.c64 index bf0197565..f78dcf717 100644 --- a/platform/c64/Makefile.c64 +++ b/platform/c64/Makefile.c64 @@ -31,7 +31,7 @@ # Author: Oliver Schmidt # -CONTIKI_TARGET_SOURCEFILES += lseek.c pfs.S pfs_write.S +CONTIKI_TARGET_SOURCEFILES += exec.c lseek.c pfs.S pfs_remove.S pfs_seek.S pfs_write.S CONTIKI_CPU = $(CONTIKI)/cpu/6502 include $(CONTIKI_CPU)/Makefile.6502 @@ -50,16 +50,16 @@ endif disk: all $(C1541) -format contiki,00 d64 contiki.d64 - $(C1541) -attach contiki.d64 -write $(CONTIKI_PROJECT).$(TARGET) contiki,p - $(C1541) -attach contiki.d64 -write $(CONTIKI)/tools/$(TARGET)/sample.cfg contiki.cfg,s - $(C1541) -attach contiki.d64 -write cs8900a.eth cs8900a.eth,s - $(C1541) -attach contiki.d64 -write lan91c96.eth lan91c96.eth,s + $(C1541) -attach contiki.d64 -write $(CONTIKI_PROJECT).$(TARGET) contiki,p + $(C1541) -attach contiki.d64 -write $(CONTIKI)/tools/$(TARGET)/sample.cfg contiki.cfg,s + $(C1541) -attach contiki.d64 -write cs8900a.eth cs8900a.eth,s + $(C1541) -attach contiki.d64 -write lan91c96.eth lan91c96.eth,s ifeq ($(findstring WITH_MOUSE,$(DEFINES)),WITH_MOUSE) - $(C1541) -attach contiki.d64 -write $(CC65_HOME)/mou/c64-1351.mou contiki.mou,s + $(C1541) -attach contiki.d64 -write $(CC65_TARGET_DIR)/drv/mou/c64-1351.mou contiki.mou,s endif ifeq ($(HTTPD-CFS),1) - $(C1541) -attach contiki.d64 -write httpd-cfs/index.htm index.htm,s - $(C1541) -attach contiki.d64 -write httpd-cfs/backgrnd.gif backgrnd.gif,s - $(C1541) -attach contiki.d64 -write httpd-cfs/contiki.gif contiki.gif,s - $(C1541) -attach contiki.d64 -write httpd-cfs/notfound.htm notfound.htm,s + $(C1541) -attach contiki.d64 -write httpd-cfs/index.htm index.htm,s + $(C1541) -attach contiki.d64 -write httpd-cfs/backgrnd.gif backgrnd.gif,s + $(C1541) -attach contiki.d64 -write httpd-cfs/contiki.gif contiki.gif,s + $(C1541) -attach contiki.d64 -write httpd-cfs/notfound.htm notfound.htm,s endif diff --git a/platform/c64/lib/exec.c b/platform/c64/lib/exec.c new file mode 100644 index 000000000..5a633d45d --- /dev/null +++ b/platform/c64/lib/exec.c @@ -0,0 +1,139 @@ +/* +** Program-chaining function for Commodore platforms. +** +** This copy of the cc65 system library function makes smaller code by using +** Contiki's Personal File System (instead of POSIX) functions. +** +** 2016-03-16, Greg King +** +** This function exploits the program-chaining feature in CBM BASIC's ROM. +** +** CC65's CBM programs have a BASIC program stub. We start those programs by +** RUNning that stub; it SYSes to the Machine Language code. Normally, after +** the ML code exits, the BASIC ROM continues running the stub. But, it has +** no more statements; so, the program stops. +** +** This function puts the desired program's name and device number into a LOAD +** statement. Then, it points BASIC to that statement, so that the ROM will run +** that statement after this program quits. The ROM will load the next program, +** and will execute it (because the LOAD will be seen in a running program). +*/ + +#include +#include +#include +#include +#include + +#include "cfs.h" + + +/* The struct below is a line of BASIC code. It sits in the LOWCODE segment +** to make sure that it won't be hidden by a ROM when BASIC is re-enabled. +** The line is: +** 0 CLR:LOAD""+"" ,01 +** After this function has written into the line, it might look like this: +** 0 CLR:LOAD""+"program name" ,08 +** +** When BASIC's LOAD command asks the Kernal to load a file, it gives the +** Kernal a pointer to a file-name string. CC65's CBM programs use that +** pointer to give a copy of the program's name to main()'s argv[0] parameter. +** But, when BASIC uses a string literal that is in a program, it points +** directly to that literal -- in the models that don't use banked RAM +** (Pet/CBM, VIC-20, and 64). The literal is overwritten by the next program +** that is loaded. So, argv[0] would point to machine code. String operations +** create a new result string -- even when that operation changes nothing. The +** result is put in the string space at the top of BASIC's memory. So, the ""+ +** in this BASIC line guarantees that argv[0] will get a name from a safe place. +*/ +#pragma data-name(push, "LOWCODE") +static struct line { + const char end_of_line; /* fake previous line */ + const struct line* const next; + const unsigned line_num; + const char CLR_token, colon, LOAD_token, quotes[2], add_token, quote; + char name[21]; + const char comma; + char unit[3]; +} basic = { + '\0', &basic + 1, /* high byte of link must be non-zero */ + 0, 0x9C, ':', 0x93, "\"\"", 0xAA, '\"', + "\" ", /* format: "123:1234567890123456\"" */ + ',', "01" +}; +#pragma data-name(pop) + +/* These values are platform-specific. */ +extern const void* vartab; /* points to BASIC program variables */ +#pragma zpsym("vartab") +extern const void* memsize; /* points to top of BASIC RAM */ +#pragma zpsym("memsize") +extern const struct line* txtptr; /* points to BASIC code */ +#pragma zpsym("txtptr") +extern char basbuf[]; /* BASIC's input buffer */ +extern void basbuf_len[]; +#pragma zpsym("basbuf_len") + + +int __fastcall__ +exec(const char *progname, const char *cmdline) +{ + static int fd; + static unsigned char dv, n; + + /* Exclude devices that can't load files. */ + /* (Use hand optimization, to make smaller code.) */ + dv = getcurrentdevice(); + if(dv < 8 && __AX__ != 1 || __AX__ > 30) { + return _mappederrno(9); /* illegal device number */ + } + utoa(dv, basic.unit, 10); + + /* Tape files can be openned only once; skip this test for the Datasette. */ + if(dv != 1) { + /* Don't try to run a program that can't be found. */ + fd = cfs_open(progname, CFS_READ); + if(fd < 0) { + return -1; + } + cfs_close(fd); + } + + n = 0; + do { + if((basic.name[n] = progname[n]) == '\0') { + break; + } + } while(++n < 20); /* truncate long names */ + basic.name[n] = '\"'; + +/* This next part isn't needed by machines that put +** BASIC source and variables in different RAM banks. +*/ +#if !defined(__C128__) + /* cc65 program loads might extend beyond the end of the RAM that is allowed + ** for BASIC. Then, the LOAD statement would complain that it is "out of + ** memory". Some pointers that say where to put BASIC program variables + ** must be changed, so that we do not get that error. One pointer is + ** changed here; a BASIC CLR statement changes the others. Some space is + ** needed for the file-name string. Subtracting an entire RAM page allows + ** better optimization of this expression. + */ + vartab = (char*)memsize - 0x0100; +#endif + + /* Build the next program's argument list. */ + basbuf[0] = 0x8F; /* REM token */ + basbuf[1] = '\0'; + if(cmdline != NULL) { + strncat(basbuf, cmdline, (size_t)basbuf_len - 2); + } + + /* Tell the ROM where to find that BASIC program. */ + txtptr = &basic; + + /* (The return code, in ST [status], will be destroyed by LOAD. + ** So, don't bother to set it here.) + */ + exit(__AX__); +} diff --git a/platform/c64/lib/pfs.S b/platform/c64/lib/pfs.S index 35e64f652..49ef496ec 100644 --- a/platform/c64/lib/pfs.S +++ b/platform/c64/lib/pfs.S @@ -29,99 +29,212 @@ ; This file is part of the Contiki operating system. ; ; Author: Kajtar Zsolt +; Author: Greg King ; ;--------------------------------------------------------------------- - .define F_IDE64 1 ; support IDE64, 100 byte only +.define F_IDE64 1 ; support IDE64, >= $0100 bytes only - .constructor init_pfs - .destructor done_pfs - .importzp ptr1, ptr2, ptr3, sp - .import curunit, __filetype, popax, addysp, subysp - .export pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend - .if F_IDE64 - .export ide64_rwprepare, ide64_rwfinish - .endif - .export _pfs_open, _pfs_read, _pfs_close + .constructor init_pfs + .destructor done_pfs + .importzp sp, ptr1, ptr2, ptr3 + .import curunit, __filetype, popax, addysp, subysp + .export pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend +.if F_IDE64 + .export ide64_rwprepare, ide64_rwfinish +.endif + .export cmdc, flags + .export pfs_makename, pfs_scratch + + .export _pfs_open, _pfs_read, _pfs_close ;--------------------------------------------------------------------- -F_EOF = $80 -F_NBLK = $40 -F_OPEN = $20 -F_MAXLEN = 80 ;max filename length -ST = $90 ;status -FN = $BB ;filename -FNL = $B7 ;filenamelength -LF = $B8 ;logical file number -SA = $B9 ;secondary address -OPEN = $FFC0 -CLOSE = $FFC3 -CHKIN = $FFC6 -CHKOUT = $FFC9 -CLRCHN = $FFCC -CHRIN = $FFCF -CHROUT = $FFD2 -SETLFS = $FFBA -SETNAM = $FFBD -CLALL = $FFE7 -WRITE = $DEF1 -READ = $DEF4 +MAXLEN = 80 ;maximum filename length + +; Flag bits +F_EOF = %10000000 ;end of file +F_NBLK = %01000000 ;block read/write not available +F_OPEN = %00100000 + +; Kernal variables +ST := $90 ;status +FN := $BB ;filename +FNL := $B7 ;filename length +LF := $B8 ;logical file number + +OPNVec := $031A ;address vector to OPEN function's code + +; IDEDOS function +READ := $DEF4 + +; Kernal functions +SETLFS := $FFBA +SETNAM := $FFBD +OPEN := $FFC0 +CLOSE := $FFC3 +CHKIN := $FFC6 +CHKOUT := $FFC9 +CLRCHN := $FFCC +CHRIN := $FFCF +CHROUT := $FFD2 ;--------------------------------------------------------------------- .data -illchr: .byte $3A, $2A, $3F, $3D ;illegal chars -pw: .byte $2C, $50, $2C, $57 ;,p,w +; illchr and sw must stay together because the comma, also, is illegal in names. +illchr: .byte "*?:=" ;illegal chars +sw: .byte ",s,w" cmdc: .byte 0 -flags: .res 10 +flags: .res 10 ;(Kernal allows only ten open files) ;--------------------------------------------------------------------- - .segment "INIT" + .segment "ONCE" init_pfs: - ldy #F_MAXLEN+8 - jsr subysp ;allocate - lda #0 - sta FNL ;no name - ldy #15-1 - jsr open2 ;open command channel + ldy #MAXLEN + 8 + jsr subysp ;allocate because open2 will free it + lda #0 ;no name, file number 1 + sta FNL + ldy #15 - 1 ;secondary address 15 + jsr open2 ;open command channel sta cmdc rts ;--------------------------------------------------------------------- .code -error3: jmp error - _pfs_open: - sta ptr2 - ; Pop and store name + sta ptr2 ;save open-mode flags + + ; Get and store name jsr popax + jsr pfs_makename + lda FNL + beq error ;must have a filename + + lda #2 - 1 ;file number + tay ;secondary address +open2: sta ptr2 + sty ptr2 + 1 + +next: inc ptr2 ;next file number + ldx ptr2 ;file number + cpx #.sizeof(flags) + 1 + bcs error ;no more files + lda flags - 1,x + bne next ;already used + lda ptr2 + 1 + bne nextsa + inx + stx ptr2 + 1 +nextsa: inc ptr2 + 1 ;next channel +retr: lda ptr2 ;file number + ldx curunit + ldy ptr2 + 1 ;secondary address (channel number) + jsr SETLFS + jsr OPEN ;open a pair of files (in computer and drive) + bcs oerr ;branch if could not open computer file + ldx cmdc + beq opok ;branch if error channel just was openned + jsr CHKIN + bcs error + jsr CHRIN + pha ;first digit of error code + jsr CHRIN + sta ptr1 ;second digit +@L4: jsr CHRIN ;flush status message + lda ST + beq @L4 + jsr CLRCHN + pla + cmp #'2' + bcc opok ;no serious error + pha + lda ptr2 + jsr CLOSE ;close computer file + pla + ldx ptr1 + cmp #'7' ;no channel? + bne nnoc + cpx #'0' + bne error ;not "no channel" + lda ptr2 + 1 + cmp #14 + bcc nextsa ;try next channel + bcs error ;give up + +opok: ldx ptr2 + lda #F_OPEN + sta flags - 1,x + txa ;OK, return file number +ret0: ldx #>$0000 +ret: ldy #MAXLEN + 8 ;free filename space + jmp addysp + +oerr: dec ptr2 + 1 + cmp #2 ;already open, + beq next ;retry with next + +error: lda #<-1 + tax ;failed + bne ret + +nnoc: inc ptr3 + bne error ;no retry + cmp #'6' + bne error ;not "file exists" + cpx #'3' + bne error + jsr pfs_scratch + bcc retr + bcs error ;branch always + +pfs_scratch: + ldx cmdc + jsr CHKOUT + bcs @L5 + ldy #1 + lda #'s' ;scratch +@L4: jsr CHROUT + lda (FN),y + iny + cmp #',' + bne @L4 + lda #$0D ;carriage return + jsr CHROUT + jsr CLRCHN + clc ;carry = 0: OK +@L5: rts ;carry = 1: error + +pfs_makename: sta FN - stx FN+1 ;filename (kernal) - ldy #F_MAXLEN+8 - jsr subysp ;allocate name - ldy #255 + stx FN+1 ;Kernal filename pointer + ldy #MAXLEN + 8 + jsr subysp ;allocate name space + + ; Validate the name; and, find its length + ldy #<-1 sty ptr3 sty ptr1 @L10: iny - cpy #F_MAXLEN - bcs error3 ;too long... - ldx #4 ;4+1 (comma) + cpy #MAXLEN + bcs badchr ;too long + lda (FN),y + ldx #.sizeof(illchr); 4 + 1 (includes comma) @L12: cmp illchr,x - beq error3 ;illegal char? + beq badchr ;illegal char dex bpl @L12 - cmp #$2F + cmp #'/' bne @L11 - sty ptr1 ;last slash -@L11: lda (FN),y + sty ptr1 ;last slash +@L11: tax ;test for '\0' bne @L10 - sty FNL + cpy #0 + beq badchr ;no name - tay - tax - lda #$30 ;this partition + tay ;zero index reg. + lda #'0' ;drive 0 or current partition sta (sp),y iny inc ptr1 beq nopath - lda #$2F + lda #'/' @L13: sta (sp),y iny lda (FN,x) @@ -130,158 +243,67 @@ _pfs_open: inc FN+1 @L14: cpy ptr1 bcc @L13 - lda #$2F + ;lda #'/' ; (.A already has a slash) sta (sp),y iny -nopath: lda #$3A +nopath: lda #':' @L16: sta (sp),y iny lda (FN,x) inc FN bne @L15 inc FN+1 -@L15: ora #0 +@L15: ora #$00 ;test for '\0' bne @L16 lsr ptr2 - bcs ro ;read only + bcs ro ;read-only (read-write not supported) lda __filetype - sta pw+1 ;set filetype - ldx #252 -@L20: lda pw-252,x - sta (sp),y ;write + sta sw + 1 ;set filetype + lsr ptr2 + lda #'w' ;write-only + lsr ptr2 + bcc write + lda #'a' ;append +write: sta sw + 3 ;set mode + ldx #$0100 - .sizeof(sw) +@L20: lda sw - ($0100 - .sizeof(sw)),x + sta (sp),y iny inx bne @L20 -ro: tya ;name length (kernal) +ro: tya ;pathname length ldx sp ldy sp+1 - jsr SETNAM +namset: jmp SETNAM - lda #0 ;file number - tay ;secondary address -open2: sta ptr2 - sty ptr2+1 - -next: inc ptr2 ;next file number - ldx ptr2 ;file number - cpx #11 - bcs error ;no more files - lda flags-1,x - bne next ;already used - lda ptr2+1 - bne nextsa - inx - stx ptr2+1 -nextsa: inc ptr2+1 ;next channel -retr: lda ptr2 ;file number - ldx curunit - ldy ptr2+1 ;secondary address - jsr SETLFS - jsr OPEN ;open - bcs oerr - ldx cmdc - beq opok ;error channel open - jsr CHKIN - bcs error - jsr CHRIN - pha - jsr CHRIN - sta ptr1 -@L4: jsr CHRIN - lda ST - beq @L4 - jsr CLRCHN - pla - tax - lsr - cmp #$18 ;no serious error - beq opok - txa - pha - lda ptr2 - jsr CLOSE ;close - pla - ldx ptr1 - cmp #$37 ;no channel? - bne nnoc - cpx #$30 - bne error ;not no channel - lda ptr2+1 - cmp #14 - bcc nextsa ;try next channel - bcs error ;give up - -opok: ldx ptr2 - lda #F_OPEN - sta flags-1,x - txa ;ok, return file number - ldx #0 -ret: ldy #F_MAXLEN+8 ; free filename - jmp addysp - -oerr: dec ptr2+1 - cmp #2 ;already open, - beq next ;retry with next - -error: lda #$FF - tax ;failed - bne ret - -nnoc: inc ptr3 - bne error ;no retry - cmp #$36 - bne error ;no exists - cpx #$33 - bne error - ldx cmdc - jsr CHKOUT - bcs error - lda FNL - sec - sbc #5 - tax - lda #$53 ;scratch - jsr CHROUT - ldy #1 -@L4: lda (FN),y - iny - jsr CHROUT - dex - bne @L4 - lda #$3D - jsr CHROUT - iny - lda (FN),y - jsr CHROUT - lda #$0d - jsr CHROUT - jsr CLRCHN - jmp retr +badchr: lda #0 + beq namset .proc _pfs_read jsr pfs_rwcommon ; pop params, check handle beq error2 ; not open bmi eof - .if F_IDE64 - asl + +.if F_IDE64 + asl a bmi nblk ; no block operation jsr CHKIN bcs error2 - + ; check support jsr ide64_rwprepare bcs norm - - ; read + + ; do a block read jsr READ bcs nosup jmp ide64_rwfinish nosup: lda #F_NBLK jsr pfs_rwsetflags - .endif +.endif ; Valid lfn. Make it the input file nblk: jsr CHKIN @@ -292,15 +314,15 @@ norm: ldy #0 @L3: inc ptr1 bne @L0 inc ptr1+1 - beq done ; branch always + beq done ; Read the next byte @L0: jsr CHRIN tax ; save the input byte - lda ST ; read the IEEE status - cmp #1 ; save it - and #%10111111 ; check anything but the EOI bit + lda ST ; read the file status + cmp #$01 ; save it + and #%10111111 ; check anything but the EOF bit bne error5 ; assume device not present ; Store the byte just read @@ -310,45 +332,60 @@ norm: ldy #0 bne @L1 inc ptr2+1 ; *buf++ = A; - ; Get the status again and check the EOI bit -@L1: bcc @L3 ; loop if no end of file + ; Get the status again; and, check the EOF bit +@L1: bcc @L3 ; loop if not end of file - ; Set the EOI flag and bail out + ; Set the EOF flag; and, bail out lda #F_EOF jsr pfs_rwsetflags - ; Read done, close the input channel -done: jsr CLRCHN ; clrchn + ; Read done; cancel the input channel +done: jsr CLRCHN ; Return the number of chars read -eof: jmp pfs_rwcommonend +eof: +; jmp pfs_rwcommonend ; (fall through) +.endproc + +.proc pfs_rwcommonend + lda ptr2 + sec + sbc ptr3 + pha + lda ptr2+1 + sbc ptr3+1 + tax + pla + rts .endproc - ; Error entry, file is not open done_pfs: - ldx #10 -@L2: ldy flags-1,x ; file open? + ldx #.sizeof(flags) +@L2: ldy flags - 1,x ; file open? beq @L1 txa - jsr _pfs_close + jsr close1 @L1: dex - bne @L2 + bne @L2 rts -error5: jsr CLRCHN ; clrchn +error5: jsr CLRCHN -error2: ldx #255 + ; Error entry, file is not open +error2: ldx #>-1 txa rts _pfs_close: - pha - jsr CLOSE ;close + cmp #.sizeof(flags) + 1 + bcs close0 ; don't close if not valid file number +close1: pha + jsr CLOSE pla tax - lda #0 - sta flags-1,x - rts + lda #$00 + sta flags - 1,x +close0: rts ; .X = file number .proc pfs_rwcommon eor #$FF @@ -366,70 +403,56 @@ _pfs_close: jsr popax ; get the handle sta LF - lda #0 - beq pfs_rwsetflags + lda #$00 +; beq pfs_rwsetflags ; (fall through) .endproc - .if F_IDE64 -.proc ide64_rwprepare - sec - lda ptr1+1 - eor #255 - beq small ; too small, not worth it - tay - lda ptr1 ; setup registers - eor #255 - tax - lda $031B - eor #$DE - bne noide ; open vector set? - lda $DE60 - eor #$49 - bne noide ; check identification - lda $DE61 - eor #$44 - bne noide - lda $DE62 - eor #$45 - bne noide - clc - lda #ptr2 -small: rts - -noide: lda #F_NBLK - bne pfs_rwsetflags -.endproc - .endif - .proc pfs_rwsetflags ldx LF - ora flags-1,x - sta flags-1,x + ora flags - 1,x + sta flags - 1,x rts .endproc - .if F_IDE64 +.if F_IDE64 +.proc ide64_rwprepare + sec ; assume it won't use IDEDOS + lda ptr1+1 + eor #$FF ; convert -count-1 back to count + beq small ; too small, not worth it + tay + lda ptr1 ; set up registers + eor #$FF + tax + lda OPNVec+1 + eor #>$DE00 + bne noide ; is OPEN vector set to IDEDOS? + lda $DE60 + eor #'i' + bne noide ; check identification + lda $DE61 + eor #'d' + bne noide + lda $DE62 + eor #'e' + bne noide + clc ; it will use IDEDOS + lda #ptr2 +small: rts + +noide: lda #F_NBLK + bne pfs_rwsetflags +.endproc + .proc ide64_rwfinish - txa + txa ; push .YX pha tya pha jsr CLRCHN - pla - tax - pla - rts -.endproc - .endif - -.proc pfs_rwcommonend - lda ptr2 - sec - sbc ptr3 - pha - lda ptr2+1 - sbc ptr3+1 + pla ; pull .XA tax pla rts .endproc +.endif diff --git a/platform/c64/lib/pfs_remove.S b/platform/c64/lib/pfs_remove.S new file mode 100644 index 000000000..7477e4314 --- /dev/null +++ b/platform/c64/lib/pfs_remove.S @@ -0,0 +1,59 @@ +; +; Copyright (c) 2016, Greg King +; 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 author nor the names of contributors +; may be used to endorse or promote products derived from this software +; without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +; +; Author: Greg King +; +;--------------------------------------------------------------------- + .importzp ptr2 + .import addysp + .import pfs_makename, pfs_scratch + + .export _pfs_remove +;--------------------------------------------------------------------- +MAXLEN = 80 ; max. filename length + +FNL := $B7 ; filename length +;--------------------------------------------------------------------- +.proc _pfs_remove + asl ptr2 ; force pfs_makename to format for pfs_scratch + jsr pfs_makename + ldx FNL + beq error ; no name + + jsr pfs_scratch + ldx #>$0000 + bcs error +ret: txa + ldy #MAXLEN + 8 ; free filename space + jmp addysp + +error: dex ;(ldx #>-1) + bne ret +.endproc diff --git a/platform/c64/lib/pfs_seek.S b/platform/c64/lib/pfs_seek.S new file mode 100644 index 000000000..4ef0014d1 --- /dev/null +++ b/platform/c64/lib/pfs_seek.S @@ -0,0 +1,46 @@ +; +; Copyright (c) 2016, Greg King +; 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 author nor the names of contributors +; may be used to endorse or promote products derived from this software +; without specific prior written permission. +; +; THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. +; +; Author: Greg King +; +;--------------------------------------------------------------------- + .importzp sp, sreg, ptr1, ptr2, ptr3 + .import popax, incsp6 + .import cmdc, flags + + .export _pfs_seek +;--------------------------------------------------------------------- +.proc _pfs_seek + lda #<-1 ; seek not implemented + tax + stx sreg ; return long data type + stx sreg+1 + jmp incsp6 ; drop int and long arguments from stack +.endproc diff --git a/platform/c64/lib/pfs_write.S b/platform/c64/lib/pfs_write.S index 7e511e513..82632df8f 100644 --- a/platform/c64/lib/pfs_write.S +++ b/platform/c64/lib/pfs_write.S @@ -31,27 +31,33 @@ ; Author: Kajtar Zsolt ; ;--------------------------------------------------------------------- - .define F_IDE64 1 ; support IDE64, 100 byte only +.define F_IDE64 1 ; support IDE64, >= $0100 bytes only - .importzp ptr1, ptr2 - .import pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend - .if F_IDE64 - .import ide64_rwprepare, ide64_rwfinish - .endif - .export _pfs_write + .importzp ptr1, ptr2 + .import pfs_rwcommon, pfs_rwsetflags, pfs_rwcommonend +.if F_IDE64 + .import ide64_rwprepare, ide64_rwfinish +.endif + + .export _pfs_write ;--------------------------------------------------------------------- -F_NBLK = $40 -ST = $90 ;status -CHKOUT = $FFC9 -CLRCHN = $FFCC -CHROUT = $FFD2 -WRITE = $DEF1 +F_NBLK = %01000000 ;block read/write not available + +ST := $90 ;status + +; IDEDOS function +WRITE := $DEF1 + +; Kernal functions +CHKOUT := $FFC9 +CLRCHN := $FFCC +CHROUT := $FFD2 ;--------------------------------------------------------------------- .code -error5: jsr CLRCHN ; clrchn +error5: jsr CLRCHN -error2: ldx #255 +error2: ldx #>-1 txa rts @@ -59,8 +65,8 @@ error2: ldx #255 jsr pfs_rwcommon ; pop params, check handle beq error2 ; not open - .if F_IDE64 - asl +.if F_IDE64 + asl a bmi nblk ; no block operation jsr CHKOUT @@ -70,7 +76,7 @@ error2: ldx #255 jsr ide64_rwprepare bcs norm - ; write + ; do a block write jsr WRITE bcs nosup jmp ide64_rwfinish @@ -98,10 +104,9 @@ norm: ldy #0 lda ST beq @L3 bne error5 ; bail out on errors -@L2: - ; Wrote all chars, close the output channel - jsr CLRCHN + ; Wrote all chars.; cancel the output channel +@L2: jsr CLRCHN ; Return the number of chars written jmp pfs_rwcommonend diff --git a/platform/cc2530dk/contiki-conf.h b/platform/cc2530dk/contiki-conf.h index 5d3beb6bb..9c79aa828 100644 --- a/platform/cc2530dk/contiki-conf.h +++ b/platform/cc2530dk/contiki-conf.h @@ -259,8 +259,8 @@ /* Define our IPv6 prefixes/contexts here */ #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 1 #define SICSLOWPAN_CONF_ADDR_CONTEXT_0 { \ - addr_contexts[0].prefix[0] = 0xaa; \ - addr_contexts[0].prefix[1] = 0xaa; \ + addr_contexts[0].prefix[0] = UIP_DS6_DEFAULT_PREFIX_0; \ + addr_contexts[0].prefix[1] = UIP_DS6_DEFAULT_PREFIX_1; \ } #define MAC_CONF_CHANNEL_CHECK_RATE 8 diff --git a/platform/cc2530dk/uip-debug.c b/platform/cc2530dk/uip-debug.c index 5f5b23ca8..1a1660e65 100644 --- a/platform/cc2530dk/uip-debug.c +++ b/platform/cc2530dk/uip-debug.c @@ -68,15 +68,3 @@ uip_debug_ipaddr_print(const uip_ipaddr_t *addr) #endif /* NETSTACK_CONF_WITH_IPV6 */ } /*---------------------------------------------------------------------------*/ -void -uip_debug_lladdr_print(const uip_lladdr_t *addr) -{ - unsigned int i; - for(i = 0; i < sizeof(uip_lladdr_t); i++) { - if(i > 0) { - putstring(":"); - } - puthex(addr->addr[i]); - } -} -/*---------------------------------------------------------------------------*/ diff --git a/platform/cc2530dk/viztool.c b/platform/cc2530dk/viztool.c index e6b2fbed3..1901e9f74 100644 --- a/platform/cc2530dk/viztool.c +++ b/platform/cc2530dk/viztool.c @@ -127,8 +127,8 @@ process_request() CC_NON_BANKED if(rt != NULL) { entry_size = sizeof(i) + sizeof(rt->ipaddr) + sizeof(rt->length) - + sizeof(rt->state.lifetime) - + sizeof(rt->state.learned_from); + + sizeof(rt->state.lifetime); + /* + sizeof(rt->state.learned_from); */ memcpy(buf + len, &i, sizeof(i)); len += sizeof(i); @@ -147,11 +147,11 @@ process_request() CC_NON_BANKED len += sizeof(flip); PRINTF(" - %08lx", rt->state.lifetime); - memcpy(buf + len, &rt->state.learned_from, - sizeof(rt->state.learned_from)); - len += sizeof(rt->state.learned_from); + /* memcpy(buf + len, &rt->state.learned_from, */ + /* sizeof(rt->state.learned_from)); */ + /* len += sizeof(rt->state.learned_from); */ - PRINTF(" - %02x [%u]\n", rt->state.learned_from, entry_size); + PRINTF(" - [%u]\n", entry_size); count++; left -= entry_size; diff --git a/platform/cc2538dk/README.md b/platform/cc2538dk/README.md index 998a574b3..4bcb2c6f4 100644 --- a/platform/cc2538dk/README.md +++ b/platform/cc2538dk/README.md @@ -308,14 +308,14 @@ Start by building a border router from `examples/ipv6/rpl-border-router` * Connect device to Linux or OS X over its XDS port. * `cd $(CONTIKI)/tools` * `make tunslip6` - * `sudo $(CONTIKI)/tools/tunslip6 -s /dev/ aaaa::1/64` + * `sudo $(CONTIKI)/tools/tunslip6 -s /dev/ fd00::1/64` * The router will print its own IPv6 address. Use it below. Got configuration message of type P - Setting prefix aaaa:: + Setting prefix fd00:: created a new RPL dag Server IPv6 addresses: - aaaa::212:4b00:89ab:cdef + fd00::212:4b00:89ab:cdef fe80::212:4b00:89ab:cdef * `ping6
` diff --git a/platform/cc2538dk/contiki-conf.h b/platform/cc2538dk/contiki-conf.h index 34a7f1673..c6f0e2b6a 100644 --- a/platform/cc2538dk/contiki-conf.h +++ b/platform/cc2538dk/contiki-conf.h @@ -34,12 +34,20 @@ typedef uint32_t uip_stats_t; /* * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define - * RTIMER_CLOCK_LT to override this + * RTIMER_CLOCK_DIFF to override this */ typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_LT(a,b) ((int32_t)((a)-(b)) < 0) +#define RTIMER_CLOCK_DIFF(a,b) ((int32_t)((a)-(b))) /** @} */ /*---------------------------------------------------------------------------*/ +#define TSCH_CONF_HW_FRAME_FILTERING 0 + +/* 352us from calling transmit() until the SFD byte has been sent */ +#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(352)) +/* 192us as in datasheet but ACKs are not always received, so adjusted to 250us */ +#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(250)) +#define RADIO_DELAY_BEFORE_DETECT 0 +/*---------------------------------------------------------------------------*/ /** * \name Serial Boot Loader Backdoor configuration * @@ -472,8 +480,8 @@ typedef uint32_t rtimer_clock_t; #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 1 #ifndef SICSLOWPAN_CONF_ADDR_CONTEXT_0 #define SICSLOWPAN_CONF_ADDR_CONTEXT_0 { \ - addr_contexts[0].prefix[0] = 0xaa; \ - addr_contexts[0].prefix[1] = 0xaa; \ + addr_contexts[0].prefix[0] = UIP_DS6_DEFAULT_PREFIX_0; \ + addr_contexts[0].prefix[1] = UIP_DS6_DEFAULT_PREFIX_1; \ } #endif diff --git a/platform/cc2538dk/contiki-main.c b/platform/cc2538dk/contiki-main.c index 8d55dc1d0..6534b103c 100644 --- a/platform/cc2538dk/contiki-main.c +++ b/platform/cc2538dk/contiki-main.c @@ -64,6 +64,7 @@ #include "net/ip/tcpip.h" #include "net/ip/uip.h" #include "net/mac/frame802154.h" +#include "soc.h" #include "cpu.h" #include "reg.h" #include "ieee-addr.h" @@ -185,6 +186,9 @@ main(void) PUTS(CONTIKI_VERSION_STRING); PUTS(BOARD_STRING); +#if STARTUP_CONF_VERBOSE + soc_print_info(); +#endif PRINTF(" Net: "); PRINTF("%s\n", NETSTACK_NETWORK.name); diff --git a/platform/cooja-ip64/contiki-cooja-ip64-main.c b/platform/cooja-ip64/contiki-cooja-ip64-main.c index 3bc94f864..02576a3be 100644 --- a/platform/cooja-ip64/contiki-cooja-ip64-main.c +++ b/platform/cooja-ip64/contiki-cooja-ip64-main.c @@ -217,7 +217,7 @@ contiki_init(void) printf("%02x%02x\n", lladdr->ipaddr.u8[14], lladdr->ipaddr.u8[15]); - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); printf("Tentative global IPv6 address "); diff --git a/platform/cooja/contiki-conf.h b/platform/cooja/contiki-conf.h index 04f1c4d43..91c93a3b4 100644 --- a/platform/cooja/contiki-conf.h +++ b/platform/cooja/contiki-conf.h @@ -136,6 +136,9 @@ #ifndef UIP_CONF_MAX_ROUTES #define UIP_CONF_MAX_ROUTES 300 #endif /* UIP_CONF_MAX_ROUTES */ +#ifndef RPL_NS_CONF_LINK_NUM +#define RPL_NS_CONF_LINK_NUM 300 +#endif /* RPL_NS_CONF_LINK_NUM */ #define TCPIP_CONF_ANNOTATE_TRANSMISSIONS 1 @@ -168,9 +171,6 @@ #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 -#ifndef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS -#define SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS 8 -#endif /* SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS */ #endif /* NETSTACK_CONF_WITH_IPV6 */ @@ -201,7 +201,7 @@ typedef unsigned short uip_stats_t; #define CLOCK_CONF_SECOND 1000L typedef unsigned long clock_time_t; typedef unsigned long rtimer_clock_t; -#define RTIMER_CLOCK_LT(a,b) ((signed long)((a)-(b)) < 0) +#define RTIMER_CLOCK_DIFF(a,b) ((signed long)((a)-(b))) #define AODV_COMPLIANCE #define AODV_NUM_RT_ENTRIES 32 diff --git a/platform/cooja/contiki-cooja-main.c b/platform/cooja/contiki-cooja-main.c index f251c9178..40dd49d1c 100644 --- a/platform/cooja/contiki-cooja-main.c +++ b/platform/cooja/contiki-cooja-main.c @@ -304,7 +304,7 @@ contiki_init() if(1) { uip_ipaddr_t ipaddr; int i; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); printf("Tentative global IPv6 address "); diff --git a/platform/ev-aducrf101mkxz/README.md b/platform/ev-aducrf101mkxz/README.md index a4cf4dcb4..5dd7c5b06 100644 --- a/platform/ev-aducrf101mkxz/README.md +++ b/platform/ev-aducrf101mkxz/README.md @@ -71,9 +71,9 @@ the SLIP tunnel on the host machine: sudo contiki/tools/tunslip6 \ -s /dev/serial/by-id/usb-SEGGER_J-Link_000541011111-if00 \ - -B 115200 -v3 aaaa::1/64 + -B 115200 -v3 fd00::1/64 -Open the border router's home page at: http://[aaaa::3230:3030:3132:3334]/ +Open the border router's home page at: http://[fd00::3230:3030:3132:3334]/ #### Web Server #### @@ -90,7 +90,7 @@ router: adi-cm3sd/cm3sd.py -a contiki/examples/webserver-ipv6/webserver6.ev-aducrf101mkxz.hex \ /dev/serial/by-id/usb-SEGGER_J-Link_000541022222-if00 -Open the web server's home page at: http://[aaaa::3230:3030:3536:3738]/ +Open the web server's home page at: http://[fd00::3230:3030:3536:3738]/ On Windows: ----------- diff --git a/platform/eval-adf7xxxmb4z/README.md b/platform/eval-adf7xxxmb4z/README.md index 1faa1a625..dc023e766 100644 --- a/platform/eval-adf7xxxmb4z/README.md +++ b/platform/eval-adf7xxxmb4z/README.md @@ -51,9 +51,9 @@ Build and run the SLIP tunnel on the host machine. Here it is assumed that the Secondary UART USB port (J3) is attached to /dev/ttyUSB1: make -C contiki/tools tunslip6 - sudo contiki/tools/tunslip6 -B 38400 -s /dev/ttyUSB1 -v3 aaaa::1/64 + sudo contiki/tools/tunslip6 -B 38400 -s /dev/ttyUSB1 -v3 fd00::1/64 -Open the border router home page at http://[aaaa::302:304:506:708]/ +Open the border router home page at http://[fd00::302:304:506:708]/ Build and run the IPv6 web server example on another eval board. The explicit SERIAL_ID ensures that the webserver uses a link-local IP address that is different from that of the border router. @@ -61,7 +61,7 @@ The explicit SERIAL_ID ensures that the webserver uses a link-local IP address t make -C contiki/examples/webserver-ipv6 TARGET=eval-adf7xxxmb4z SERIAL_ID='"\x01\x02\x03\x04\x05\x06\x07\x09"' webserver6.eval-adf7xxxmb4z.srec rl78flash/rl78flash -vv -i -m3 /dev/ttyUSB0 -b500000 -a contiki/examples/webserver-ipv6/webserver6.eval-adf7xxxmb4z.srec -Open the web server's home page at http://[aaaa::7a30:3178:3032:7830] +Open the web server's home page at http://[fd00::7a30:3178:3032:7830] On Windows: diff --git a/platform/exp5438/contiki-conf.h b/platform/exp5438/contiki-conf.h index bb7a5fcdd..9220ba890 100644 --- a/platform/exp5438/contiki-conf.h +++ b/platform/exp5438/contiki-conf.h @@ -174,9 +174,6 @@ #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 -#ifndef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS -#define SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS 5 -#endif /* SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS */ #else /* NETSTACK_CONF_WITH_IPV6 */ #define UIP_CONF_IP_FORWARD 1 #define UIP_CONF_BUFFER_SIZE 108 diff --git a/platform/exp5438/contiki-exp5438-main.c b/platform/exp5438/contiki-exp5438-main.c index 2f85f6ba2..321bb9171 100644 --- a/platform/exp5438/contiki-exp5438-main.c +++ b/platform/exp5438/contiki-exp5438-main.c @@ -236,7 +236,7 @@ main(int argc, char **argv) if(!UIP_CONF_IPV6_RPL) { uip_ipaddr_t ipaddr; int i; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); printf("Tentative global IPv6 address "); diff --git a/platform/galileo/Makefile.customrules-galileo b/platform/galileo/Makefile.customrules-galileo index cb5bc26a9..b141ee211 100644 --- a/platform/galileo/Makefile.customrules-galileo +++ b/platform/galileo/Makefile.customrules-galileo @@ -9,7 +9,17 @@ MULTIBOOT = $(CONTIKI_PROJECT).$(MULTIBOOT_SFX) # UEFI binary UEFI_DLL_SFX = $(TARGET).dll UEFI_DLL = $(CONTIKI_PROJECT).$(UEFI_SFX) -UEFI_LDFLAGS += -Xlinker --emit-relocs -Xlinker --entry=uefi_start +# The GenFw program is unable to process absolute symbols like _stext_addr, +# etc., that are defined in quarkX1000_dma.ld and quarkX1000_multi_seg.ld +# and used to configure segments in multi-segment.c, etc. Furthermore, +# relocating the UEFI image during load would result in those symbols not +# pointing to the expected image locations. So, relocation data is omitted +# from the intermediate UEFI DLL. This will only result in a +# correctly-functioning build if the UEFI firmware does not attempt to +# relocate the UEFI image, so it may be desirable in the future to revisit +# this design. To emit relocation data, '-Xlinker --emit-relocs' should be +# appended to the following line. +UEFI_LDFLAGS = -Xlinker --entry=uefi_start UEFI_SFX = $(TARGET).efi UEFI = $(CONTIKI_PROJECT).$(UEFI_SFX) diff --git a/platform/galileo/README.md b/platform/galileo/README.md index b99ad7d65..e441876db 100644 --- a/platform/galileo/README.md +++ b/platform/galileo/README.md @@ -30,6 +30,11 @@ Device drivers: * Real-Time Clock (RTC) * UART * Ethernet + * I2C + * GPIO (default pinmux configuration is listed in + platform/galileo/drivers/galileo-pinmux.c) + * Intel Quark X1000 SoC message bus + * Isolated Memory Regions (IMRs) Contiki APIs: * Clock module @@ -39,6 +44,9 @@ Standard APIs: * Stdio library (stdout and stderr only). Console output through UART 1 device (connected to Galileo Gen2 FTDI header) +Optional support for protection domains is also implemented and is +described in cpu/x86/mm/README.md. + Building -------- @@ -81,6 +89,12 @@ you can run the following command prior to building applications: $ cpu/x86/uefi/build_uefi.sh ``` +To restrict DMA so that peripherals are blocked from accessing memory +regions that do not contain any data that needs to be DMA-accessible, +specify X86_CONF_RESTRICT_DMA=1 as a command-line argument to the make +command that is used to build the image. This will configure and lock +the IMRs. + Running ------- diff --git a/platform/galileo/bsp/libc/build_newlib.sh b/platform/galileo/bsp/libc/build_newlib.sh index cef167e14..0e104802e 100755 --- a/platform/galileo/bsp/libc/build_newlib.sh +++ b/platform/galileo/bsp/libc/build_newlib.sh @@ -1,5 +1,7 @@ #!/bin/bash +set -e + JOBS=5 TARGET=i586-elf VERSION=2.2.0-1 @@ -38,7 +40,7 @@ prepare() { tar xf ${TARBALL} cd ${SRC_DIR} - for i in `ls ${PATCH_DIR}`; do patch -p0 < ${PATCH_DIR}/${i}; done + for i in `ls ${PATCH_DIR}/*.patch`; do patch -p0 < ${i}; done } @@ -99,7 +101,9 @@ cleanup() { # By default we always call prepare, build and setup. -prepare && build && setup +prepare +build +setup # But we only cleanup if -c is used. case $1 in diff --git a/platform/galileo/contiki-conf.h b/platform/galileo/contiki-conf.h index dca42b8de..2d64c440f 100644 --- a/platform/galileo/contiki-conf.h +++ b/platform/galileo/contiki-conf.h @@ -46,7 +46,7 @@ typedef unsigned long clock_time_t; typedef uint64_t rtimer_clock_t; #define RTIMER_ARCH_SECOND 1024 -#define RTIMER_CLOCK_LT(a, b) ((int64_t)((a) - (b)) < 0) +#define RTIMER_CLOCK_DIFF(a, b) ((int64_t)((a) - (b))) /* We define the following macros and types otherwise Contiki does not * compile. diff --git a/platform/galileo/contiki-main.c b/platform/galileo/contiki-main.c index 943ac3174..ccc1f519f 100644 --- a/platform/galileo/contiki-main.c +++ b/platform/galileo/contiki-main.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -33,9 +33,19 @@ #include "contiki.h" #include "contiki-net.h" #include "cpu.h" -#include "interrupt.h" -#include "uart.h" +#include "eth.h" #include "eth-conf.h" +#include "galileo-pinmux.h" +#include "gpio.h" +#include "helpers.h" +#include "i2c.h" +#include "imr-conf.h" +#include "interrupt.h" +#include "irq.h" +#include "pci.h" +#include "prot-domains.h" +#include "shared-isr.h" +#include "uart.h" PROCINIT( &etimer_process , &tcpip_process @@ -44,19 +54,14 @@ PROCINIT( &etimer_process #endif ); -int -main(void) +extern int _sdata_kern_startup_func, _edata_kern_startup_func; + +/*---------------------------------------------------------------------------*/ +void +app_main(void) { - cpu_init(); - /* Initialize UART connected to Galileo Gen2 FTDI header */ - quarkX1000_uart_init(QUARK_X1000_UART_1); - clock_init(); - rtimer_init(); - printf("Starting Contiki\n"); - ENABLE_IRQ(); - process_init(); procinit_init(); ctimer_init(); @@ -68,5 +73,50 @@ main(void) process_run(); } + halt(); +} +/*---------------------------------------------------------------------------*/ +/* Kernel entrypoint */ +int +main(void) +{ + uintptr_t *func_ptr; + +#ifdef X86_CONF_RESTRICT_DMA + quarkX1000_imr_conf(); +#endif + irq_init(); + /* Initialize UART connected to Galileo Gen2 FTDI header */ + quarkX1000_uart_init(QUARK_X1000_UART_1); + clock_init(); + rtimer_init(); + + pci_root_complex_init(); + quarkX1000_eth_init(); + quarkX1000_i2c_init(); + quarkX1000_i2c_configure(QUARKX1000_I2C_SPEED_STANDARD, + QUARKX1000_I2C_ADDR_MODE_7BIT); + /* use default pinmux configuration */ + if(galileo_pinmux_initialize() < 0) { + fprintf(stderr, "Failed to initialize pinmux\n"); + } + quarkX1000_gpio_init(); + shared_isr_init(); + + /* The ability to remap interrupts is not needed after this point and should + * thus be disabled according to the principle of least privilege. + */ + pci_root_complex_lock(); + + func_ptr = (uintptr_t *)&_sdata_kern_startup_func; + while(func_ptr != (uintptr_t *)&_edata_kern_startup_func) { + ((void (*)(void))*func_ptr)(); + + func_ptr++; + } + + prot_domains_leave_main(); + return 0; } +/*---------------------------------------------------------------------------*/ diff --git a/platform/galileo/drivers/galileo-pinmux.c b/platform/galileo/drivers/galileo-pinmux.c index c66036ea2..3059bdb36 100644 --- a/platform/galileo/drivers/galileo-pinmux.c +++ b/platform/galileo/drivers/galileo-pinmux.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/platform/galileo/net/eth-conf.c b/platform/galileo/net/eth-conf.c index ff3a771bf..061e0aae7 100644 --- a/platform/galileo/net/eth-conf.c +++ b/platform/galileo/net/eth-conf.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015, Intel Corporation. All rights reserved. + * Copyright (C) 2015-2016, Intel Corporation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -29,7 +29,6 @@ */ #include "eth-conf.h" -#include "eth.h" #include "net/eth-proc.h" #include "contiki-net.h" #include "net/linkaddr.h" @@ -45,6 +44,7 @@ const linkaddr_t linkaddr_null = { { 0, 0, 0, 0, 0, 0 } }; #define NAMESERVER_IP GATEWAY_IP #endif +/*---------------------------------------------------------------------------*/ void eth_init(void) { @@ -69,7 +69,6 @@ eth_init(void) #endif #endif - quarkX1000_eth_init(); - process_start(ð_process, NULL); } +/*---------------------------------------------------------------------------*/ diff --git a/platform/jn516x/Makefile.jn516x b/platform/jn516x/Makefile.jn516x index 27587ccaf..ca41ce3ae 100644 --- a/platform/jn516x/Makefile.jn516x +++ b/platform/jn516x/Makefile.jn516x @@ -80,7 +80,7 @@ SIZE:=$(CROSS_COMPILE)-size OBJCOPY:=$(CROSS_COMPILE)-objcopy OBJDUMP:=$(CROSS_COMPILE)-objdump -ARCH = ccm-star.c exceptions.c rtimer-arch.c rtimer-arch-slow.c \ +ARCH = jn516x-ccm-star.c exceptions.c rtimer-arch.c rtimer-arch-slow.c \ slip_uart0.c clock.c micromac-radio.c \ mtarch.c node-id.c watchdog.c log.c slip.c sprintf.c # Default uart0 for printf and slip diff --git a/platform/jn516x/contiki-conf.h b/platform/jn516x/contiki-conf.h index 8b702a56e..1a326f62b 100644 --- a/platform/jn516x/contiki-conf.h +++ b/platform/jn516x/contiki-conf.h @@ -154,9 +154,6 @@ #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 -#ifndef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS -#define SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS 5 -#endif /* SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS */ #define UIP_CONF_ICMP_DEST_UNREACH 1 #define UIP_CONF_DHCP_LIGHT diff --git a/platform/jn516x/contiki-jn516x-main.c b/platform/jn516x/contiki-jn516x-main.c index 8c88a10df..9a64365e6 100644 --- a/platform/jn516x/contiki-jn516x-main.c +++ b/platform/jn516x/contiki-jn516x-main.c @@ -226,7 +226,7 @@ start_uip6(void) if(!UIP_CONF_IPV6_RPL) { uip_ipaddr_t ipaddr; int i; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); PRINTF("Tentative global IPv6 address "); @@ -409,7 +409,6 @@ main(void) #endif /* NETSTACK_CONF_WITH_IPV4 */ watchdog_start(); - NETSTACK_LLSEC.init(); #if NETSTACK_CONF_WITH_IPV6 start_uip6(); diff --git a/platform/jn516x/dev/clock.c b/platform/jn516x/dev/clock.c index b1927f5d6..8b2c316c0 100644 --- a/platform/jn516x/dev/clock.c +++ b/platform/jn516x/dev/clock.c @@ -258,7 +258,7 @@ clock_arch_time_to_etimer(void) clock_time_t time_to_etimer; if(etimer_pending()) { time_to_etimer = etimer_next_expiration_time() - clock_time(); - if(time_to_etimer < 0) { + if((int32_t)time_to_etimer < 0) { time_to_etimer = 0; } } else { diff --git a/platform/jn516x/dev/ccm-star.c b/platform/jn516x/dev/jn516x-ccm-star.c similarity index 100% rename from platform/jn516x/dev/ccm-star.c rename to platform/jn516x/dev/jn516x-ccm-star.c diff --git a/platform/jn516x/platform-conf.h b/platform/jn516x/platform-conf.h index c1c372b64..408b4957e 100644 --- a/platform/jn516x/platform-conf.h +++ b/platform/jn516x/platform-conf.h @@ -80,9 +80,9 @@ #define JN516X_EXTERNAL_CRYSTAL_OSCILLATOR (RTIMER_USE_32KHZ || JN516X_SLEEP_ENABLED) #endif /* JN516X_EXTERNAL_CRYSTAL_OSCILLATOR */ -/* Core rtimer.h defaults to 16 bit timer unless RTIMER_CLOCK_LT is defined */ +/* Core rtimer.h defaults to 16 bit timer unless RTIMER_CLOCK_DIFF is defined */ typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_LT(a, b) ((int32_t)((a) - (b)) < 0) +#define RTIMER_CLOCK_DIFF(a, b) ((int32_t)((a) - (b))) /* 8ms timer tick */ #define CLOCK_CONF_SECOND 125 diff --git a/platform/mbxxx/contiki-main.c b/platform/mbxxx/contiki-main.c index c383b0f61..f1ad1d8d4 100644 --- a/platform/mbxxx/contiki-main.c +++ b/platform/mbxxx/contiki-main.c @@ -179,7 +179,7 @@ main(void) NETSTACK_RDC.channel_check_interval())); printf("802.15.4 PAN ID 0x%x, EUI-%d:", IEEE802154_CONF_PANID, UIP_CONF_LL_802154?64:16); - uip_debug_lladdr_print((const uip_lladdr_t *)&linkaddr_node_addr); + net_debug_lladdr_print((const uip_lladdr_t *)&linkaddr_node_addr); printf(", radio channel %u\n", RF_CHANNEL); procinit_init(); @@ -214,7 +214,7 @@ main(void) if(!UIP_CONF_IPV6_RPL) { uip_ipaddr_t ipaddr; int i; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); printf("Tentative global IPv6 address "); diff --git a/platform/mbxxx/platform-conf.h b/platform/mbxxx/platform-conf.h index 6b811ec96..98870980d 100644 --- a/platform/mbxxx/platform-conf.h +++ b/platform/mbxxx/platform-conf.h @@ -87,7 +87,7 @@ typedef unsigned long clock_time_t; typedef unsigned long rtimer_clock_t; -#define RTIMER_CLOCK_LT(a,b) ((signed long)((a)-(b)) < 0) +#define RTIMER_CLOCK_DIFF(a,b) ((signed long)((a)-(b))) #define LEDS_CONF_RED_PIN boardDescription->io->leds[1].gpioPin #define LEDS_CONF_GREEN_PIN boardDescription->io->leds[0].gpioPin diff --git a/platform/micaz/contiki-conf.h b/platform/micaz/contiki-conf.h index 16e74567a..50e2ace1e 100644 --- a/platform/micaz/contiki-conf.h +++ b/platform/micaz/contiki-conf.h @@ -125,10 +125,11 @@ #define UIP_CONF_ROUTER 0 /* configure number of neighbors and routes */ -#define NBR_TABLE_CONF_MAX_NEIGHBORS 5 -#define UIP_CONF_MAX_ROUTES 5 +#define NBR_TABLE_CONF_MAX_NEIGHBORS 4 +#define UIP_CONF_MAX_ROUTES 4 -#define RPL_CONF_MAX_PARENTS 4 +#define RPL_CONF_MAX_PARENTS 4 +#define RPL_CONF_MAX_DAG_PER_INSTANCE 1 #define UIP_CONF_ND6_SEND_RA 0 #define UIP_CONF_ND6_REACHABLE_TIME 600000 @@ -140,12 +141,12 @@ #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 #define UIP_CONF_IP_FORWARD 0 -#define UIP_CONF_BUFFER_SIZE 240 +#define UIP_CONF_BUFFER_SIZE 200 #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #ifndef SICSLOWPAN_CONF_FRAG #define SICSLOWPAN_CONF_FRAG 1 -#define SICSLOWPAN_CONF_FRAGMENT_BUFFERS 4 +#define SICSLOWPAN_CONF_FRAGMENT_BUFFERS 3 #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 diff --git a/platform/micaz/init-net.c b/platform/micaz/init-net.c index 271b402c8..9c09fe4ae 100644 --- a/platform/micaz/init-net.c +++ b/platform/micaz/init-net.c @@ -177,7 +177,7 @@ init_net(void) if(!UIP_CONF_IPV6_RPL) { uip_ipaddr_t ipaddr; int i; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); printf_P(PSTR("Tentative global IPv6 address ")); diff --git a/platform/minimal-net/contiki-main.c b/platform/minimal-net/contiki-main.c index 35b466a39..90d700876 100644 --- a/platform/minimal-net/contiki-main.c +++ b/platform/minimal-net/contiki-main.c @@ -289,7 +289,7 @@ main(int argc, char **argv) #ifdef HARD_CODED_ADDRESS uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr); #else - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); #endif if((ipaddr.u16[0] != 0) || (ipaddr.u16[1] != 0) || diff --git a/platform/native/cfs-coffee-arch.h b/platform/native/cfs-coffee-arch.h index d7622cd46..763e1ebae 100644 --- a/platform/native/cfs-coffee-arch.h +++ b/platform/native/cfs-coffee-arch.h @@ -55,7 +55,6 @@ #define COFFEE_LOG_SIZE 8192 #define COFFEE_LOG_TABLE_LIMIT 256 #define COFFEE_MICRO_LOGS 0 -#define COFFEE_IO_SEMANTICS 1 #define COFFEE_WRITE(buf, size, offset) \ xmem_pwrite((char *)(buf), (size), COFFEE_START + (offset)) diff --git a/platform/native/contiki-conf.h b/platform/native/contiki-conf.h index e011bff96..03eacbbde 100644 --- a/platform/native/contiki-conf.h +++ b/platform/native/contiki-conf.h @@ -110,9 +110,6 @@ typedef unsigned short uip_stats_t; #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 -#ifndef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS -#define SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS 5 -#endif /* SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS */ #define UIP_CONF_IPV6_CHECKS 1 #define UIP_CONF_IPV6_QUEUE_PKT 1 diff --git a/platform/nrf52dk/Makefile.nrf52dk b/platform/nrf52dk/Makefile.nrf52dk new file mode 100644 index 000000000..8fa911cc4 --- /dev/null +++ b/platform/nrf52dk/Makefile.nrf52dk @@ -0,0 +1,34 @@ +ifndef CONTIKI + $(error CONTIKI not defined! You must specify where CONTIKI resides!) +endif + +### Include the board-specific makefile +PLATFORM_ROOT_DIR = $(CONTIKI)/platform/$(TARGET) + +CONTIKI_TARGET_DIRS += . dev config +CONTIKI_SOURCEFILES += contiki-main.c leds-arch.c nrf52dk-sensors.c button-sensor.c temperature-sensor.c + +ifeq ($(NRF52_USE_RTT),1) +### Use the existing debug I/O in cpu/arm/common +CONTIKI_TARGET_DIRS += rtt +CONTIKI_SOURCEFILES += rtt-printf.c segger-rtt.c segger-rtt-printf.c +else +CONTIKI_TARGET_DIRS += dbg-io +CONTIKI_SOURCEFILES += dbg.c +CONTIKI_CPU_DIRS += ../arm/common/dbg-io +CONTIKI_CPU_SOURCEFILES += dbg-printf.c dbg-putchar.c dbg-snprintf.c dbg-sprintf.c strformat.c +endif + +CLEAN += *.nrf52dk + +### Unless the example dictates otherwise, build with code size optimisations switched +### off +ifndef SMALL + SMALL = 0 +endif + +### Define the CPU directory and pull in the correct CPU makefile. +CONTIKI_CPU=$(CONTIKI)/cpu/nrf52832 +include $(CONTIKI_CPU)/Makefile.nrf52832 + +MODULES += core/net core/net/mac core/net/llsec diff --git a/platform/nrf52dk/README-BLE-6LoWPAN.md b/platform/nrf52dk/README-BLE-6LoWPAN.md new file mode 100644 index 000000000..e4c9ef5f6 --- /dev/null +++ b/platform/nrf52dk/README-BLE-6LoWPAN.md @@ -0,0 +1,100 @@ +This README contains information how to establish an IPv6 connecton between +Linux BLE router and an IPSP enabled BLE device. + +Prerequisites +============= +In general, any device capable of running Linux operating system, can be used +as a BLE router provided the following conditions are met: + +* Linux Kernel >3.18 is used +* bluez, libcap-ng0, radvd tools are present. + +If a built-in Bluetooth device is not available then Bluetooth 4.0 compatible +USB dongle can be used. + +The following procedures have been tested on Ubuntu 15.10. + +Establishing an IPv6 connection +=============================== +Use the following procedure to establish a connection between an nRF52 device +and Linux router: + +First enable 6LoWPAN module. This is neccessary only once per session: + + # Log in as a root user. + sudo su + + # Mount debugfs file system. + mount -t debugfs none /sys/kernel/debug + + # Load 6LoWPAN module. + modprobe bluetooth_6lowpan + + # Enable the bluetooth 6lowpan module. + echo 1 > /sys/kernel/debug/bluetooth/6lowpan_enable + + # Look for available HCI devices. + hciconfig + + # Reset HCI device - for example hci0 device. + hciconfig hci0 reset + + # Read 00:AA:BB:XX:YY:ZZ address of the nRF5x device. + hcitool lescan + +If you see device name and address in lescan output then you can connect to the +device: + + echo "connect 00:AA:BB:XX:YY:ZZ 1" > /sys/kernel/debug/bluetooth/6lowpan_control + +If above is successful then LED1 will stop blinking and LED2 will switch on. +You can then check the connection using the following commands: + + # Check if bt0 interface is present and up + ifconfig + + # Try to ping the device using its link-local address, for example, on bt0 interface. + ping6 -I bt0 fe80::2aa:bbff:fexx:yyzz + +If you'd like to learn more about the procedure please refer to +[Connecting devices to the router]. + +Distributing routable IPv6 prefix +================================= +In Linux, Router Advertisement Daemon (RADVD) can be used to distribute prefixes +in the network, hance configure routable IPv6 address. + +To configure RADVD create `/etc/radvd.conf` file and paste the following contents: + + interface bt0 + { + AdvSendAdvert on; + prefix 2001:db8::/64 + { + AdvOnLink off; + AdvAutonomous on; + AdvRouterAddr on; + }; + }; + +Next, start RADVD daemon: + + # Set IPv6 forwarding (must be present). + sudo echo 1 > /proc/sys/net/ipv6/conf/all/forwarding + # Run radvd daemon. + sudo service radvd restart + +If successfull then all devices connected to the host will receive +a routable `2001:db8` prefix. + +This can be verified by sending echo request to the full address: + + ping6 -I bt0 2001:db8::2aa:bbff:fexx:yyzz + +where `aa:bbff:fexx:yyzz` is device Bluetooth address. + +If you'd like to learn more about the procedure please refer to +[Distributing a global IPv6 prefix]. + +* [Connecting devices to the router]: http://developer.nordicsemi.com/nRF5_IoT_SDK/doc/0.9.0/html/a00089.html +* [Distributing a global IPv6 prefix]: http://developer.nordicsemi.com/nRF5_IoT_SDK/doc/0.9.0/html/a00090.html \ No newline at end of file diff --git a/platform/nrf52dk/README.md b/platform/nrf52dk/README.md new file mode 100644 index 000000000..236892858 --- /dev/null +++ b/platform/nrf52dk/README.md @@ -0,0 +1,254 @@ +Contiki for nRF52 Development Kit +================================= +This guide's aim is to help you with using Contiki for +Nordic Semiconductor's nRF52 DK. + +The port depends on Nordic Semiconductor IoT SDK for nRF52. +The IoT SDK contains source code and libraries which are +required for successfull port compilation. It also contains +SoftDevice binary driver which is required for BLE operation. +See prerequisites section for details on how to set up the SDK. + +For more information about SoftDevice please refer to the SDK +docummentation [nRF52 Datasheet and SDK documentation]. + +This port supports DK versions PCA10040 and PCA10036. + +Port Features +============= +The following features have been implemented: +* Support for IPv6 over BLE using Contiki 6LoWPAN implementation +* Contiki system clock and rtimers (using 32kHz and 1MHz timers) +* UART driver +* Watchdog driver +* Hardware RNG +* Temperature sensor driver +* DK LED driver +* DK Buttons driver +* Real Time Transfer (RTT) I/O support + +Note that this port supports only IPv6 network stack. + +The port is organized as follows: +* nRF52832 CPU and BLE drivers are located in `cpu/nrf52832` folder +* nRF52 Development Kit drivers are located in `platform/nrf52dk` folder +* Platform examples are located in `examples/nrf52dk` folder + +Prerequisites and Setup +======================= +In order to compile for the nRF52 DK platform you'll need: + +* nRF5 IOT SDK + https://developer.nordicsemi.com + + Download nRF5 IOT SDK, extract it to a folder of your choice, + and point `NRF52_SDK_ROOT` environmental variable to it, e.g.,: + + ``` + wget https://developer.nordicsemi.com/nRF5_IoT_SDK/nRF5_IoT_SDK_v0.9.x/nrf5_iot_sdk_3288530.zip + unzip nrf5_iot_sdk_3288530.zip -d /path/to/sdk + export NRF52_SDK_ROOT=/path/to/sdk + ``` + +* An ARM compatible toolchain + The port has been tested with GNU Tools for ARM Embedded Processors + version 5.2.1. + + For Ubuntu you can use package version provided by your distribution: + ``` + sudo apt-get install gcc-arm-none-eabi + ``` + + Alternatively, install the toolchain from PPA to get the latest version + of the compiler: https://launchpad.net/~team-gcc-arm-embedded/+archive/ubuntu/ppa + + For other systems please download and install toolchain available at + https://launchpad.net/gcc-arm-embedded + +* GNU make + +* Segger JLink Software for Linux + https://www.segger.com/jlink-software.html + + This package contains tools necessary for programming and debugging nRF52 DK. + + For Ubuntu you can download and install a .deb package. Alternatively download + tar.gz archive and extract it to a folder of your choice. In this case you + need to set `NRF52_JLINK_PATH` environmental variable to point to the + JLink tools location: + + ``` + export NRF52_JLINK_PATH=/path/to/jlink/tools + ``` + + To keep this variable set between sessions please add the above line to your + `rc.local` file. + + In order to access the DK as a regular Linux user create a `99-jlink.rules` + file in your udev rules folder (e.g., `/etc/udev/rules.d/`) and add the + following line to it: + + ``` + ATTRS{idProduct}=="1015", ATTRS{idVendor}=="1366", MODE="0666" + ``` + When installing from a deb package, the `99-jlink.rules` file is added + automatically to /etc/udev/rules.d folder. However, the syntax of the file + doesn't work on newer udev versions. To fix this problem edit this file and + replace ATTR keyword with ATTRS. + +To fully use the platform a BLE enabled router device is needed. Please refer +to `Preqrequisites` section in `README-BLE-6LoWPAN.md` for details. + +Getting Started +=============== +Once all tools are installed it is recommended to start by compiling +and flashing `examples/hello-word` application. This allows to verify +that toolchain setup is correct. + +To compile the example, go to `examples/hello-world` and execute: + + make TARGET=nrf52dk + +If you haven't used the device with Contiki before we advise to +erase the device and flash new SoftDevice: + + make TARGET=nrf52dk erase + make TARGET=nrf52dk softdevice.flash + +If the compilation is completed without errors flash the board: + + make TARGET=nrf52dk hello-world.flash + +The device will start BLE advertising as soon as initialized. By +default the device name is set to 'Contiki nRF52 DK'. To verify +that the device is advertising properly run: + + sudo hcitool lescan + +And observe if the device name appears in the output. Also, observe +if LED1 is blinking what indicates that device is waiting for a connection +from BLE master. + +If device is functioning as expected you can test IPv6 connection +to the device. Please refer to `README-BLE-6LoWPAN.md` on details how to do +this. + +Examples +======== +Examples specific for nRF52 DK can be found in `examples/nrf52dk` folder. Please +refer to README.md in respective examples for detailed description. + +The DK has also been tested with the `examples/hello-world` and `examples/webserver-ipv6` +generic examples. + +Compilation Options +=================== +The Contiki TARGET name for this port is `nrf52dk`, so in order to compile +an application you need to invoke GNU make as follows: + + make TARGET=nrf52dk + +In addition to this port supports the following variables which can be +set on the compilation command line: + +* `NRF52_SDK_ROOT=` + This variable allows to specify a path to the nRF52 SDK which should + be used for the build. + +* `NRF52_WITHOUT_SOFTDEVICE={0|1}` + Disables SoftDevice support if set to 1. By default, SoftDevice support + is used. Note that SoftDevice must be present (flashed) in the device + before you run an application that requires it's presence. + +* `NRF52_USE_RTT={0|1}` + Enables RealTime Terminal I/O. See VCOM and RTT for details. By default, + RTT is disabled and IO is done using Virtual COM port. + +* `NRF52_JLINK_SN=` + Allows to choose a particular DK by its serial number (printed on the + label). This is useful if you have more than one DK connected to your + PC and whish to flash a particular device. + +* `NRF52_DK_REVISION={pca10040|pca10036}` + Allows to specify DK revision. By default, pca10040 is used. + +Compilation Targets +=================== +Invoking make solely with the `TARGET` variable set will build all +applications in a given folder. A particular application can be built +by invoking make with its name as a compilation target: + + make TARGET=nrf52dk hello-world + +In order to flash the application binary to the device use `.flash` +as make target, e.g.: + + make TARGET=nrf52dk hello-world.flash + +In addition, the SoftDevice binary can be flashed to the DK by invoking: + + make TARGET=nrf52dk softdevice.flash + +To remove all build results invoke: + + make TARGET=nrf52dk clean + +The device memory can be erased using: + + make TARGET=nrf52dk erase + +Note, that once the device is erased, the SoftDevice must be programmed again. + +Virtual COM and Real Time Transfer +================================== +By default, the nRF52 DK uses a Virtual COM port to output logs. Once +the DK is plugged in a `/tty/ACM` or `/ttyUSB` device should appear in +your filesystem. A terminal emulator, such as picocom or minicom, can be +used to connect to the device. Default serial port speed is 38400 bps. + +To connect to serial port using picocom invoke: + + picocom -fh -b 38400 --imap lfcrlf /dev/ttyACM0 + +Note, that if you have not fixed file permissions for `/dev/ttyACM0` +according to section `Segger JLink Software for Linux` you'll need to use +root or sudo to open the port with `picocom`. + +In addition to Virtual COM the port supports SEGGER's Real Time Transfer +for low overhead I/O support. This allows for outputting debugging information +at much higher rate with significantly lower overhead than regular I/O. + +To compile an application with RTT rather that VCOM set `NRF52_USE_RTT` to 1 on +the compilation command line: + + make TARGET=nrf52dk NRF52_USE_RTT=1 hello-world + +You can then connect to the device terminal using `JLinkRTTClient`. Note that +a JLlink gdb or commander must be connected to the target for the RTT to work. + +More details regarding RTT can be found at https://www.segger.com/jlink-rtt.html + +Docummentation +============== +This port provides doxygen source code docummentation. To build the +docummentation please run: + + sudo apt-get install doxygen + cd \doc + make + +Support +======= +This port is officially supported by Nordic Semiconductor. Please send bug +reports or/and suggestions to . + +License +======= +All files in the port are under BSD license. nRF52 SDK and SoftDevice are +licensed on a separate terms. + +Resources +========= +* nRF52 Datasheet and SDK documentation (http://infocenter.nordicsemi.com) +* nRF52 SDK Downloads (https://developer.nordicsemi.com/) +* JLink Tools (https://www.segger.com/) \ No newline at end of file diff --git a/platform/nrf52dk/config/nrf_drv_config.h b/platform/nrf52dk/config/nrf_drv_config.h new file mode 100644 index 000000000..cfc3595b2 --- /dev/null +++ b/platform/nrf52dk/config/nrf_drv_config.h @@ -0,0 +1,329 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk + * @{ + * + * \defgroup nrf52dk-config nRF52 SDK configuration + * @{ + */ + +#ifndef NRF_DRV_CONFIG_H +#define NRF_DRV_CONFIG_H + +/* CLOCK */ +#define CLOCK_CONFIG_XTAL_FREQ NRF_CLOCK_XTALFREQ_Default +#define CLOCK_CONFIG_LF_SRC NRF_CLOCK_LF_SRC_Xtal +#define CLOCK_CONFIG_LF_RC_CAL_INTERVAL RC_2000MS_CALIBRATION_INTERVAL +#define CLOCK_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +/* GPIOTE */ +#define GPIOTE_ENABLED 1 + +#if (GPIOTE_ENABLED == 1) +#define GPIOTE_CONFIG_USE_SWI_EGU false +#define GPIOTE_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH +#define GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS 4 +#endif + +/* TIMER */ +#define TIMER0_ENABLED 0 + +#if (TIMER0_ENABLED == 1) +#define TIMER0_CONFIG_FREQUENCY NRF_TIMER_FREQ_16MHz +#define TIMER0_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER0_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_32Bit +#define TIMER0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER0_INSTANCE_INDEX 0 +#endif + +#define TIMER1_ENABLED 1 + +#if (TIMER1_ENABLED == 1) +#define TIMER1_CONFIG_FREQUENCY NRF_TIMER_FREQ_62500Hz +#define TIMER1_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER1_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_32Bit +#define TIMER1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER1_INSTANCE_INDEX (TIMER0_ENABLED) +#endif + +#define TIMER2_ENABLED 0 + +#if (TIMER2_ENABLED == 1) +#define TIMER2_CONFIG_FREQUENCY NRF_TIMER_FREQ_16MHz +#define TIMER2_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER2_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_16Bit +#define TIMER2_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER2_INSTANCE_INDEX (TIMER1_ENABLED+TIMER0_ENABLED) +#endif + +#define TIMER3_ENABLED 0 + +#if (TIMER3_ENABLED == 1) +#define TIMER3_CONFIG_FREQUENCY NRF_TIMER_FREQ_16MHz +#define TIMER3_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER3_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_16Bit +#define TIMER3_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER3_INSTANCE_INDEX (TIMER2_ENABLED+TIMER2_INSTANCE_INDEX) +#endif + +#define TIMER4_ENABLED 0 + +#if (TIMER4_ENABLED == 1) +#define TIMER4_CONFIG_FREQUENCY NRF_TIMER_FREQ_16MHz +#define TIMER4_CONFIG_MODE TIMER_MODE_MODE_Timer +#define TIMER4_CONFIG_BIT_WIDTH TIMER_BITMODE_BITMODE_16Bit +#define TIMER4_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define TIMER4_INSTANCE_INDEX (TIMER3_ENABLED+TIMER3_INSTANCE_INDEX) +#endif + + +#define TIMER_COUNT (TIMER0_ENABLED + TIMER1_ENABLED + TIMER2_ENABLED + TIMER3_ENABLED + TIMER4_ENABLED) + +/* RTC */ +#define RTC0_ENABLED 0 + +#if (RTC0_ENABLED == 1) +#define RTC0_CONFIG_FREQUENCY 32678 +#define RTC0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define RTC0_CONFIG_RELIABLE false + +#define RTC0_INSTANCE_INDEX 0 +#endif + +#define RTC1_ENABLED 1 + +#if (RTC1_ENABLED == 1) +#define RTC1_CONFIG_FREQUENCY 128 +#define RTC1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define RTC1_CONFIG_RELIABLE false + +#define RTC1_INSTANCE_INDEX (RTC0_ENABLED) +#endif + +#define RTC_COUNT (RTC0_ENABLED+RTC1_ENABLED) + +#define NRF_MAXIMUM_LATENCY_US 2000 + +/* RNG */ +#define RNG_ENABLED 1 + +#if (RNG_ENABLED == 1) +#define RNG_CONFIG_ERROR_CORRECTION true +#define RNG_CONFIG_POOL_SIZE 8 +#define RNG_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#endif + +/* SPI */ +#define SPI0_ENABLED 0 + +#if (SPI0_ENABLED == 1) +#define SPI0_USE_EASY_DMA 0 + +#define SPI0_CONFIG_SCK_PIN 2 +#define SPI0_CONFIG_MOSI_PIN 3 +#define SPI0_CONFIG_MISO_PIN 4 +#define SPI0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define SPI0_INSTANCE_INDEX 0 +#endif + +#define SPI1_ENABLED 0 + +#if (SPI1_ENABLED == 1) +#define SPI1_USE_EASY_DMA 0 + +#define SPI1_CONFIG_SCK_PIN 2 +#define SPI1_CONFIG_MOSI_PIN 3 +#define SPI1_CONFIG_MISO_PIN 4 +#define SPI1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define SPI1_INSTANCE_INDEX (SPI0_ENABLED) +#endif + +#define SPI2_ENABLED 0 + +#if (SPI2_ENABLED == 1) +#define SPI2_USE_EASY_DMA 0 + +#define SPI2_CONFIG_SCK_PIN 2 +#define SPI2_CONFIG_MOSI_PIN 3 +#define SPI2_CONFIG_MISO_PIN 4 +#define SPI2_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW + +#define SPI2_INSTANCE_INDEX (SPI0_ENABLED + SPI1_ENABLED) +#endif + +#define SPI_COUNT (SPI0_ENABLED + SPI1_ENABLED + SPI2_ENABLED) + +/* UART */ +#define UART0_ENABLED 1 + +#if (UART0_ENABLED == 1) +#define UART0_CONFIG_HWFC NRF_UART_HWFC_DISABLED +#define UART0_CONFIG_PARITY NRF_UART_PARITY_EXCLUDED +#define UART0_CONFIG_BAUDRATE NRF_UART_BAUDRATE_38400 +#define UART0_CONFIG_PSEL_TXD 6 +#define UART0_CONFIG_PSEL_RXD 8 +#define UART0_CONFIG_PSEL_CTS 7 +#define UART0_CONFIG_PSEL_RTS 5 +#define UART0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#ifdef NRF52 +#define UART0_CONFIG_USE_EASY_DMA false +//Compile time flag +#define UART_EASY_DMA_SUPPORT 1 +#define UART_LEGACY_SUPPORT 1 +#endif //NRF52 +#endif + +#define TWI0_ENABLED 0 + +#if (TWI0_ENABLED == 1) +#define TWI0_CONFIG_FREQUENCY NRF_TWI_FREQ_100K +#define TWI0_CONFIG_SCL 0 +#define TWI0_CONFIG_SDA 1 +#define TWI0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH + +#define TWI0_INSTANCE_INDEX 0 +#endif + +#define TWI1_ENABLED 0 + +#if (TWI1_ENABLED == 1) +#define TWI1_CONFIG_FREQUENCY NRF_TWI_FREQ_100K +#define TWI1_CONFIG_SCL 0 +#define TWI1_CONFIG_SDA 1 +#define TWI1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH + +#define TWI1_INSTANCE_INDEX (TWI0_ENABLED) +#endif + +#define TWI_COUNT (TWI0_ENABLED+TWI1_ENABLED) + +/* TWIS */ +#define TWIS0_ENABLED 0 + +#if (TWIS0_ENABLED == 1) + #define TWIS0_CONFIG_ADDR0 0 + #define TWIS0_CONFIG_ADDR1 0 /* 0: Disabled */ + #define TWIS0_CONFIG_SCL 0 + #define TWIS0_CONFIG_SDA 1 + #define TWIS0_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH + + #define TWIS0_INSTANCE_INDEX 0 +#endif + +#define TWIS1_ENABLED 0 + +#if (TWIS1_ENABLED == 1) + #define TWIS1_CONFIG_ADDR0 0 + #define TWIS1_CONFIG_ADDR1 0 /* 0: Disabled */ + #define TWIS1_CONFIG_SCL 0 + #define TWIS1_CONFIG_SDA 1 + #define TWIS1_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH + + #define TWIS1_INSTANCE_INDEX (TWIS0_ENABLED) +#endif + +#define TWIS_COUNT (TWIS0_ENABLED + TWIS1_ENABLED) +/* For more documentation see nrf_drv_twis.h file */ +#define TWIS_ASSUME_INIT_AFTER_RESET_ONLY 0 +/* For more documentation see nrf_drv_twis.h file */ +#define TWIS_NO_SYNC_MODE 0 +/** + * \brief Definition for patching PAN problems + * + * Set this definition to nonzero value to patch anomalies + * from MPW3 - first lunch microcontroller. + * + * Concerns: + * - PAN-29: TWIS: incorrect bits in ERRORSRC + * - PAN-30: TWIS: STOP task does not work as expected + */ +#define NRF_TWIS_PATCH_FOR_MPW3 1 + + +/* QDEC */ +#define QDEC_ENABLED 0 + +#if (QDEC_ENABLED == 1) +#define QDEC_CONFIG_REPORTPER NRF_QDEC_REPORTPER_10 +#define QDEC_CONFIG_SAMPLEPER NRF_QDEC_SAMPLEPER_16384us +#define QDEC_CONFIG_PIO_A 1 +#define QDEC_CONFIG_PIO_B 2 +#define QDEC_CONFIG_PIO_LED 3 +#define QDEC_CONFIG_LEDPRE 511 +#define QDEC_CONFIG_LEDPOL NRF_QDEC_LEPOL_ACTIVE_HIGH +#define QDEC_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define QDEC_CONFIG_DBFEN false +#define QDEC_CONFIG_SAMPLE_INTEN false +#endif + +/* SAADC */ +#define SAADC_ENABLED 0 + +#if (SAADC_ENABLED == 1) +#define SAADC_CONFIG_RESOLUTION NRF_SAADC_RESOLUTION_10BIT +#define SAADC_CONFIG_OVERSAMPLE NRF_SAADC_OVERSAMPLE_DISABLED +#define SAADC_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#endif + +/* LPCOMP */ +#define LPCOMP_ENABLED 0 + +#if (LPCOMP_ENABLED == 1) +#define LPCOMP_CONFIG_REFERENCE NRF_LPCOMP_REF_SUPPLY_4_8 +#define LPCOMP_CONFIG_DETECTION NRF_LPCOMP_DETECT_DOWN +#define LPCOMP_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW +#define LPCOMP_CONFIG_INPUT NRF_LPCOMP_INPUT_0 +#endif + +/* WDT */ +#define WDT_ENABLED 1 + +#if (WDT_ENABLED == 1) +#define WDT_CONFIG_BEHAVIOUR NRF_WDT_BEHAVIOUR_RUN_SLEEP +#define WDT_CONFIG_RELOAD_VALUE 2000 +#define WDT_CONFIG_IRQ_PRIORITY APP_IRQ_PRIORITY_HIGH +#endif + +#include "nrf_drv_config_validation.h" +#endif // NRF_DRV_CONFIG_H + +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/config/pstorage_platform.h b/platform/nrf52dk/config/pstorage_platform.h new file mode 100644 index 000000000..3102b2097 --- /dev/null +++ b/platform/nrf52dk/config/pstorage_platform.h @@ -0,0 +1,74 @@ +/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved. + * + * The information contained herein is property of Nordic Semiconductor ASA. + * Terms and conditions of usage are described in detail in NORDIC + * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT. + * + * Licensees are granted free, non-transferable use of the information. NO + * WARRANTY of ANY KIND is provided. This heading must NOT be removed from + * the file. + * + */ + + /** @cond To make doxygen skip this file */ + +/** @file + * This header contains defines with respect persistent storage that are specific to + * persistent storage implementation and application use case. + */ +#ifndef PSTORAGE_PL_H__ +#define PSTORAGE_PL_H__ + +#include +#include "nrf.h" + +static __INLINE uint16_t pstorage_flash_page_size() +{ + return (uint16_t)NRF_FICR->CODEPAGESIZE; +} + +#define PSTORAGE_FLASH_PAGE_SIZE pstorage_flash_page_size() /**< Size of one flash page. */ +#define PSTORAGE_FLASH_EMPTY_MASK 0xFFFFFFFF /**< Bit mask that defines an empty address in flash. */ + +#ifdef NRF51 +#define BOOTLOADER_ADDRESS (NRF_UICR->BOOTLOADERADDR) +#elif defined NRF52 +#define BOOTLOADER_ADDRESS (PSTORAGE_FLASH_EMPTY_MASK) +#endif + +#define PSTORAGE_FLASH_PAGE_END \ + ((BOOTLOADER_ADDRESS != PSTORAGE_FLASH_EMPTY_MASK) \ + ? (BOOTLOADER_ADDRESS / PSTORAGE_FLASH_PAGE_SIZE) \ + : NRF_FICR->CODESIZE) + + +#define PSTORAGE_NUM_OF_PAGES 2 /**< Number of flash pages allocated for the pstorage module excluding the swap page, configurable based on system requirements. */ +#define PSTORAGE_MIN_BLOCK_SIZE 0x0010 /**< Minimum size of block that can be registered with the module. Should be configured based on system requirements, recommendation is not have this value to be at least size of word. */ + +#define PSTORAGE_DATA_START_ADDR ((PSTORAGE_FLASH_PAGE_END - PSTORAGE_NUM_OF_PAGES - 1) \ + * PSTORAGE_FLASH_PAGE_SIZE) /**< Start address for persistent data, configurable according to system requirements. */ +#define PSTORAGE_DATA_END_ADDR ((PSTORAGE_FLASH_PAGE_END - 1) * PSTORAGE_FLASH_PAGE_SIZE) /**< End address for persistent data, configurable according to system requirements. */ +#define PSTORAGE_SWAP_ADDR PSTORAGE_DATA_END_ADDR /**< Top-most page is used as swap area for clear and update. */ + +#define PSTORAGE_MAX_BLOCK_SIZE PSTORAGE_FLASH_PAGE_SIZE /**< Maximum size of block that can be registered with the module. Should be configured based on system requirements. And should be greater than or equal to the minimum size. */ +#define PSTORAGE_CMD_QUEUE_SIZE 30 /**< Maximum number of flash access commands that can be maintained by the module for all applications. Configurable. */ + + +/** Abstracts persistently memory block identifier. */ +typedef uint32_t pstorage_block_t; + +typedef struct +{ + uint32_t module_id; /**< Module ID.*/ + pstorage_block_t block_id; /**< Block ID.*/ +} pstorage_handle_t; + +typedef uint16_t pstorage_size_t; /** Size of length and offset fields. */ + +/**\brief Handles Flash Access Result Events. To be called in the system event dispatcher of the application. */ +void pstorage_sys_event_handler (uint32_t sys_evt); + +#endif // PSTORAGE_PL_H__ + +/** @} */ +/** @endcond */ diff --git a/platform/nrf52dk/contiki-conf.h b/platform/nrf52dk/contiki-conf.h new file mode 100644 index 000000000..6303c90db --- /dev/null +++ b/platform/nrf52dk/contiki-conf.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-contikic-conf Contiki configuration + * @{ + * + * \file + * Contiki configuration for the nRF52 DK + */ +#ifndef CONTIKI_CONF_H +#define CONTIKI_CONF_H + +#include +/*---------------------------------------------------------------------------*/ +/* Include Project Specific conf */ +#ifdef PROJECT_CONF_H +#include PROJECT_CONF_H +#endif /* PROJECT_CONF_H */ +/*---------------------------------------------------------------------------*/ +/* Include platform peripherals configuration */ +#include "platform-conf.h" +/*---------------------------------------------------------------------------*/ +/** + * \name Network Stack Configuration + * + * @{ + */ +#ifndef NETSTACK_CONF_NETWORK +#define NETSTACK_CONF_NETWORK sicslowpan_driver +#endif /* NETSTACK_CONF_NETWORK */ + +#ifndef NETSTACK_CONF_MAC +#define NETSTACK_CONF_MAC ble_ipsp_mac_driver +#endif /* NETSTACK_CONF_MAC */ + +/* 6LoWPAN */ +#define SICSLOWPAN_CONF_MAC_MAX_PAYLOAD 1280 +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 +#define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 0 /**< Always compress IPv6 packets. */ +#define SICSLOWPAN_CONF_FRAG 0 /**< We don't use 6LoWPAN fragmentation as IPSP takes care of that for us.*/ +#define SICSLOWPAN_FRAMER_HDRLEN 0 /**< Use fixed header len rather than framer.length() function */ + +/* Packet buffer */ +#define PACKETBUF_CONF_SIZE 1280 /**< Required IPv6 MTU size */ +/** @} */ + +/** + * \name BLE configuration + * @{ + */ +#ifndef DEVICE_NAME +#define DEVICE_NAME "Contiki nRF52dk" /**< Device name used in BLE undirected advertisement. */ +#endif +/** + * @} + */ + +/** + * \name IPv6 network buffer configuration + * + * @{ + */ +/* Don't let contiki-default-conf.h decide if we are an IPv6 build */ +#ifndef NETSTACK_CONF_WITH_IPV6 +#define NETSTACK_CONF_WITH_IPV6 0 +#endif + +#if NETSTACK_CONF_WITH_IPV6 +/*---------------------------------------------------------------------------*/ +/* Addresses, Sizes and Interfaces */ +#define LINKADDR_CONF_SIZE 8 +#define UIP_CONF_LL_802154 1 +#define UIP_CONF_LLH_LEN 0 + +/* The size of the uIP main buffer */ +#ifndef UIP_CONF_BUFFER_SIZE +#define UIP_CONF_BUFFER_SIZE 1280 +#endif + +/* ND and Routing */ +#define UIP_CONF_ROUTER 0 /**< BLE master role, which allows for routing, isn't supported. */ +#define UIP_CONF_ND6_SEND_NA 1 +#define UIP_CONF_IP_FORWARD 0 /**< No packet forwarding. */ + +#define UIP_CONF_ND6_REACHABLE_TIME 600000 +#define UIP_CONF_ND6_RETRANS_TIMER 10000 + +#ifndef NBR_TABLE_CONF_MAX_NEIGHBORS +#define NBR_TABLE_CONF_MAX_NEIGHBORS 20 +#endif + +#ifndef UIP_CONF_MAX_ROUTES +#define UIP_CONF_MAX_ROUTES 20 +#endif + +#ifndef UIP_CONF_TCP +#define UIP_CONF_TCP 1 +#endif + +#ifndef UIP_CONF_TCP_MSS +#define UIP_CONF_TCP_MSS 64 +#endif + +#define UIP_CONF_UDP 1 +#define UIP_CONF_UDP_CHECKSUMS 1 +#define UIP_CONF_ICMP6 1 +#endif /* NETSTACK_CONF_WITH_IPV6 */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Generic Configuration directives + * + * @{ + */ +#ifndef ENERGEST_CONF_ON +#define ENERGEST_CONF_ON 1 /**< Energest Module */ +#endif +/** @} */ +#endif /* CONTIKI_CONF_H */ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/contiki-main.c b/platform/nrf52dk/contiki-main.c new file mode 100644 index 000000000..9181d7faf --- /dev/null +++ b/platform/nrf52dk/contiki-main.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup nrf52dk nRF52 Development Kit + * @{ + */ +#include +#include + +#include "nordic_common.h" +#include "nrf_drv_config.h" +#include "nrf_drv_gpiote.h" +#ifdef SOFTDEVICE_PRESENT +#include "softdevice_handler.h" +#include "ble/ble-core.h" +#include "ble/ble-mac.h" +#endif + +#include "contiki.h" +#include "contiki-net.h" +#include "leds.h" +#include "lib/sensors.h" + +#include "dev/watchdog.h" +#include "dev/serial-line.h" +#include "dev/uart0.h" +#include "dev/lpm.h" + +#define DEBUG 0 + +#if NETSTACK_CONF_WITH_IPV6 +#include "uip-debug.h" +#include "net/ipv6/uip-ds6.h" +#else +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +#endif + +#if defined(SOFTDEVICE_PRESENT) && PLATFORM_INDICATE_BLE_STATE +PROCESS(ble_iface_observer, "BLE interface observer"); + +/** + * \brief A process that handles adding/removing + * BLE IPSP interfaces. + */ +PROCESS_THREAD(ble_iface_observer, ev, data) +{ + static struct etimer led_timer; + + PROCESS_BEGIN(); + + etimer_set(&led_timer, CLOCK_SECOND/2); + + while(1) { + PROCESS_WAIT_EVENT(); + if(ev == ble_event_interface_added) { + etimer_stop(&led_timer); + leds_off(LEDS_1); + leds_on(LEDS_2); + } else if(ev == ble_event_interface_deleted) { + etimer_set(&led_timer, CLOCK_SECOND/2); + leds_off(LEDS_2); + } else if(ev == PROCESS_EVENT_TIMER && etimer_expired(&led_timer)) { + etimer_reset(&led_timer); + leds_toggle(LEDS_1); + } + } + PROCESS_END(); +} +#endif +/*---------------------------------------------------------------------------*/ +/** + * \brief Board specific initialization + * + * This function will enable SoftDevice is present. + */ +static void +board_init(void) +{ +#ifdef SOFTDEVICE_PRESENT + /* Initialize the SoftDevice handler module */ + SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, NULL); +#endif +#ifdef PLATFORM_HAS_BUTTON + if (!nrf_drv_gpiote_is_init()) { + nrf_drv_gpiote_init(); + } +#endif +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Main function for nRF52dk platform. + * \note This function doesn't return. + */ +int +main(void) +{ + board_init(); + leds_init(); + + clock_init(); + rtimer_init(); + + watchdog_init(); + process_init(); + + // Seed value is ignored since hardware RNG is used. + random_init(0); + +#ifdef UART0_ENABLED + uart0_init(); +#if SLIP_ARCH_CONF_ENABLE + slip_arch_init(0); +#else + uart0_set_input(serial_line_input_byte); + serial_line_init(); +#endif +#endif + + PRINTF("Starting " CONTIKI_VERSION_STRING "\n"); + + process_start(&etimer_process, NULL); + ctimer_init(); + +#if ENERGEST_CONF_ON + energest_init(); + ENERGEST_ON(ENERGEST_TYPE_CPU); +#endif + +#ifdef SOFTDEVICE_PRESENT + ble_stack_init(); + ble_advertising_init(DEVICE_NAME); + +#if NETSTACK_CONF_WITH_IPV6 + netstack_init(); + linkaddr_t linkaddr; + ble_get_mac(linkaddr.u8); + /* Set link layer address */ + linkaddr_set_node_addr(&linkaddr); + /* Set device link layer address in uip stack */ + memcpy(&uip_lladdr.addr, &linkaddr, sizeof(uip_lladdr.addr)); + process_start(&ble_iface_observer, NULL); + process_start(&tcpip_process, NULL); +#endif /* NETSTACK_CONF_WITH_IPV6 */ +#endif /* SOFTDEVICE_PRESENT */ + + process_start(&sensors_process, NULL); + autostart_start(autostart_processes); + + watchdog_start(); + +#ifdef SOFTDEVICE_PRESENT + ble_advertising_start(); + PRINTF("Advertising name [%s]\n", DEVICE_NAME); +#endif + + while(1) { + uint8_t r; + do { + r = process_run(); + watchdog_periodic(); + } while(r > 0); + + lpm_drop(); + } +} +/** + * @} + */ diff --git a/platform/nrf52dk/dbg-io/dbg.c b/platform/nrf52dk/dbg-io/dbg.c new file mode 100644 index 000000000..db9bb63c0 --- /dev/null +++ b/platform/nrf52dk/dbg-io/dbg.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-dbg-io Debug IO over UART + * @{ + * + * \file + * Function implementations for debug io module. + * \author + * Wojciech Bober + * + */ +#include "dev/uart0.h" +/*---------------------------------------------------------------------------*/ +unsigned int +dbg_send_bytes(const unsigned char *s, unsigned int len) +{ + unsigned int i = 0; + + while (s && *s != 0) { + if (i >= len) { + break; + } + uart0_writeb(*s++); + i++; + } + + return i; +} +/*---------------------------------------------------------------------------*/ +int +dbg_putchar(int c) +{ + uart0_writeb(c); + return c; +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dbg-io/dbg.h b/platform/nrf52dk/dbg-io/dbg.h new file mode 100644 index 000000000..7c623336b --- /dev/null +++ b/platform/nrf52dk/dbg-io/dbg.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * +3 * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-dbg-io Debug IO over UART + * @{ + * + * \file + * Header file for the debug module. + * \author + * Wojciech Bober + * + */ +#ifndef DBG_H_ +#define DBG_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +/*---------------------------------------------------------------------------*/ +/** + * \brief Print a stream of bytes + * \param seq A pointer to the stream + * \param len The number of bytes to print + * \return The number of printed bytes + */ +unsigned int dbg_send_bytes(const unsigned char *seq, unsigned int len); +/** + * \brief Print a character to debug output + * \param c Character to print + * \return Printed character + */ +int dbg_putchar(int c); +/*---------------------------------------------------------------------------*/ +#endif /* DBG_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dbg-io/debug-uart.h b/platform/nrf52dk/dbg-io/debug-uart.h new file mode 100644 index 000000000..b52d2fb50 --- /dev/null +++ b/platform/nrf52dk/dbg-io/debug-uart.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-dbg-io Debug IO over UART + * @{ + * + * \file + * A header file to maintain compatibility with DBG I/O. + * \author + * Wojciech Bober + * + */ +/*---------------------------------------------------------------------------*/ +#ifndef DEBUG_UART_H_ +#define DEBUG_UART_H_ +/*---------------------------------------------------------------------------*/ +#include "dbg.h" +/*---------------------------------------------------------------------------*/ +#endif /* DEBUG_UART_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/button-sensor.c b/platform/nrf52dk/dev/button-sensor.c new file mode 100644 index 000000000..3c218a439 --- /dev/null +++ b/platform/nrf52dk/dev/button-sensor.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``as-is'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-devices-button Buttons driver + * @{ + * + * \file + * Driver for nRF52 DK buttons. + * \author + * Wojciech Bober + */ +/*---------------------------------------------------------------------------*/ +#include +#include "nordic_common.h" +#include "nrf_drv_gpiote.h" +#include "nrf_assert.h" +#include "boards.h" +#include "contiki.h" +#include "lib/sensors.h" +#include "button-sensor.h" + +/*---------------------------------------------------------------------------*/ +#define DEBOUNCE_DURATION (CLOCK_SECOND >> 5) /**< Delay before button state is assumed to be stable */ + +/*---------------------------------------------------------------------------*/ +struct btn_timer +{ + struct timer debounce; + clock_time_t start; + clock_time_t duration; +}; + +static struct btn_timer btn_timer[BUTTONS_NUMBER]; +static int btn_state = 0; + +/*---------------------------------------------------------------------------*/ +/** + * \brief Button toggle handler + * \param pin GPIO pin which has been triggered + * \param action toggle direction + * + */ +static void +gpiote_event_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) +{ + int id = pin - BUTTON_START; + + if(!timer_expired(&(btn_timer[id].debounce))) { + return; + } + + /* Set timer to ignore consecutive changes for + * DEBOUNCE_DURATION. + */ + timer_set(&(btn_timer[id].debounce), DEBOUNCE_DURATION); + + /* + * Start measuring duration on falling edge, stop on rising edge. + */ + if(nrf_drv_gpiote_in_is_set(pin) == 0) { + btn_timer[id].start = clock_time(); + btn_timer[id].duration = 0; + } else { + btn_timer[id].duration = clock_time() - btn_timer[id].start; + } + sensors_changed(&buttons[id]); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the button sensor for all buttons. + * + * \param type if \a SENSORS_HW_INIT is passed the function will initialize + * given button + * if \a SENSORS_ACTIVE is passed then \p c parameter defines + * whether button should be set active or inactive + * \param c 0 to disable the button, non-zero: enable + * \param pin GPIOE pin number + */ +static int +config(int type, int c, nrf_drv_gpiote_pin_t pin) +{ + int id = pin - BUTTON_START; + + switch(type) { + case SENSORS_HW_INIT: { + nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false); + config.pull = NRF_GPIO_PIN_PULLUP; + nrf_drv_gpiote_in_init(pin, &config, gpiote_event_handler); + timer_set(&(btn_timer[id].debounce), DEBOUNCE_DURATION); + return 1; + } + case SENSORS_ACTIVE: { + if(c) { + nrf_drv_gpiote_in_event_enable(pin, true); + btn_state |= (1 << id); + } else { + nrf_drv_gpiote_in_event_disable(pin); + btn_state &= ~(1 << id); + } + return 1; + } + default: + return 0; + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for button 1 + * + * \param type passed to config() as-is + * \param value passed to config() as-is + * \return same as config() return value + */ +static int +config_button_1(int type, int value) +{ + return config(type, value, BSP_BUTTON_0); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for button 2 + * + * \param type passed to config() as-is + * \param value passed to config() as-is + * \return same as config() return value + */ +static int +config_button_2(int type, int value) +{ + return config(type, value, BSP_BUTTON_1); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for button 3 + * + * \param type passed to config() as-is + * \param value passed to config() as-is + * \return same as config() return value + */ +static int +config_button_3(int type, int value) +{ + return config(type, value, BSP_BUTTON_2); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for button 4 + * + * \param type passed to config() as-is + * \param value passed to config() as-is + * \return same as config() return value + */ +static int +config_button_4(int type, int value) +{ + return config(type, value, BSP_BUTTON_3); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return current state of a button + * \param type pass \ref BUTTON_SENSOR_VALUE_STATE to get current button state + * or \ref BUTTON_SENSOR_VALUE_DURATION to get active state duration + * \param pin GPIOE pin number + * + * \retval BUTTON_SENSOR_VALUE_PRESSED + * \retval BUTTON_SENSOR_VALUE_RELEASED when \a type is \ref BUTTON_SENSOR_VALUE_STATE + * \retval duration Active state duration in clock ticks + */ +static int +value(int type, nrf_drv_gpiote_pin_t pin) +{ + + if(type == BUTTON_SENSOR_VALUE_STATE) { + return nrf_drv_gpiote_in_is_set(pin) == 0 ? + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + } else if(type == BUTTON_SENSOR_VALUE_DURATION) { + return btn_timer[pin - BUTTON_START].duration; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return current state of a button 1 + * \param type passed to value() as-is + * \return same as value returned by value() + */ +static int +value_button_1(int type) +{ + return value(type, BSP_BUTTON_0); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return current state of a button 2 + * \param type passed to value() as-is + * \return same as value returned by value() + */ +static int +value_button_2(int type) +{ + return value(type, BSP_BUTTON_1); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return current state of a button 3 + * \param type passed to value() as-is + * \return same as value returned by value() + */ +static int +value_button_3(int type) +{ + return value(type, BSP_BUTTON_2); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Return current state of a button 4 + * \param type passed to value() as-is + * \return same as value returned by value() + */ +static int +value_button_4(int type) +{ + return value(type, BSP_BUTTON_3); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Get status of a given button + * \param type \a SENSORS_ACTIVE or \a SENSORS_READY + * \param pin GPIOE pin number + * \return 1 if the button's port interrupt is enabled + */ +static int +status(int type, nrf_drv_gpiote_pin_t pin) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return (btn_state & (1 << (pin - BUTTON_START))); + default: + break; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for button 1 + * \param type passed to state() as-is + * \return value returned by state() + */ +static int +status_button_1(int type) +{ + return status(type, BSP_BUTTON_0); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for button 2 + * \param type passed to state() as-is + * \return value returned by state() + */ +static int +status_button_2(int type) +{ + return status(type, BSP_BUTTON_1); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for button 3 + * \param type passed to state() as-is + * \return value returned by state() + */ +static int +status_button_3(int type) +{ + return status(type, BSP_BUTTON_2); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Status function for button 3 + * \param type passed to state() as-is + * \return value returned by state() + */ +static int +status_button_4(int type) +{ + return status(type, BSP_BUTTON_3); +} +/*---------------------------------------------------------------------------*/ +const struct sensors_sensor buttons[BUTTONS_NUMBER] = { + {BUTTON_SENSOR, value_button_1, config_button_1, status_button_1}, + {BUTTON_SENSOR, value_button_2, config_button_2, status_button_2}, + {BUTTON_SENSOR, value_button_3, config_button_3, status_button_3}, + {BUTTON_SENSOR, value_button_4, config_button_4, status_button_4}, }; +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/button-sensor.h b/platform/nrf52dk/dev/button-sensor.h new file mode 100644 index 000000000..ababb1c1c --- /dev/null +++ b/platform/nrf52dk/dev/button-sensor.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-devices-button Buttons driver + * @{ + * + * \file + * Header file for the nRF52dk button driver. + * \author + * Wojciech Bober + * + */ +/*---------------------------------------------------------------------------*/ +#ifndef BUTTON_SENSOR_H_ +#define BUTTON_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define BUTTON_SENSOR "Button" +/*---------------------------------------------------------------------------*/ +#define BUTTON_SENSOR_VALUE_STATE 0 /**< Can be passed to value() function + to get current button state */ +#define BUTTON_SENSOR_VALUE_DURATION 1 /**< Can be passed to value() function + to get low state duration */ + +#define BUTTON_SENSOR_VALUE_RELEASED 0 +#define BUTTON_SENSOR_VALUE_PRESSED 1 +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor buttons[]; +/*---------------------------------------------------------------------------*/ +#define button_1 buttons[0] +#define button_2 buttons[1] +#define button_3 buttons[2] +#define button_4 buttons[3] +/*---------------------------------------------------------------------------*/ +#endif /* BUTTON_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/leds-arch.c b/platform/nrf52dk/dev/leds-arch.c new file mode 100644 index 000000000..019589493 --- /dev/null +++ b/platform/nrf52dk/dev/leds-arch.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-devices-led LED driver + * @{ + * + * \file + * Architecture specific LED driver implementation for nRF52 DK. + * \author + * Wojciech Bober + */ +#include "boards.h" +#include "contiki.h" +#include "dev/leds.h" + +/*---------------------------------------------------------------------------*/ +void +leds_arch_init(void) +{ + LEDS_CONFIGURE(LEDS_MASK); + LEDS_OFF(LEDS_MASK); +} +/*---------------------------------------------------------------------------*/ +unsigned char +leds_arch_get(void) +{ + return (unsigned char)(LED_IS_ON(LEDS_MASK) >> LED_START); +} +/*---------------------------------------------------------------------------*/ +void +leds_arch_set(unsigned char leds) +{ + unsigned int mask = (unsigned int)leds << LED_START; + LEDS_OFF(LEDS_MASK); + LEDS_ON(mask); +} +/*---------------------------------------------------------------------------*/ + +/** + * @} + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/nrf52dk-sensors.c b/platform/nrf52dk/dev/nrf52dk-sensors.c new file mode 100644 index 000000000..3d56e91d1 --- /dev/null +++ b/platform/nrf52dk/dev/nrf52dk-sensors.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk + * @{ + * + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-sensors Sensors + * The nRF52 DK exports 4 button sensors and an internal temperature sensor. + * @{ + * + * \file + * This file exports a global sensors table. + * \author + * Wojciech Bober + */ +/*---------------------------------------------------------------------------*/ +#include +#include "contiki.h" +#include "lib/sensors.h" +#include "dev/button-sensor.h" +#include "dev/temperature-sensor.h" +/*---------------------------------------------------------------------------*/ +SENSORS( + &button_1, + &button_2, + &button_3, + &button_4, + &temperature_sensor +); +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/temperature-sensor.c b/platform/nrf52dk/dev/temperature-sensor.c new file mode 100644 index 000000000..5aac8b3ef --- /dev/null +++ b/platform/nrf52dk/dev/temperature-sensor.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-devices-temp Temperature sensor driver + * This is a driver for nRF52832 hardware sensor. + * + * @{ + * + * \file + * Temperature sensor implementation. + * \author + * Wojciech Bober + * + */ +#ifndef SOFTDEVICE_PRESENT +#include "nrf_temp.h" +#else +#include "nrf_soc.h" +#endif +#include "contiki.h" +#include "dev/temperature-sensor.h" + + +const struct sensors_sensor temperature_sensor; + +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns device temperature + * \param type ignored + * \return Device temperature in degrees Celsius + */ +static int +value(int type) +{ +#ifndef SOFTDEVICE_PRESENT + return nrf_temp_read(); +#else + int32_t temp; + sd_temp_get(&temp); + return temp >> 2; +#endif +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configures temperature sensor + * \param type initializes the hardware sensor when \a type is set to + * \a SENSORS_HW_INIT + * \param c ignored + * \return 1 + * \note This function does nothing when SoftDevice is present + */ +static int +configure(int type, int c) +{ +#ifndef SOFTDEVICE_PRESENT + if (type == SENSORS_HW_INIT) { + nrf_temp_init(); + } +#endif + return 1; +} +/** + * \brief Return temperature sensor status + * \param type ignored + * \return 1 + */ +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(temperature_sensor, TEMPERATURE_SENSOR, value, configure, status); +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/dev/temperature-sensor.h b/platform/nrf52dk/dev/temperature-sensor.h new file mode 100644 index 000000000..27b246b2d --- /dev/null +++ b/platform/nrf52dk/dev/temperature-sensor.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup nrf52dk-devices Device drivers + * @{ + * + * \addtogroup nrf52dk-devices-temp Temperature sensor driver + * @{ + * + * \file + * Temperature sensor header file. + * \author + * Wojciech Bober + * + */ + +#ifndef TEMPERATURE_SENSOR_H_ +#define TEMPERATURE_SENSOR_H_ + +#include "lib/sensors.h" + +extern const struct sensors_sensor temperature_sensor; + +#define TEMPERATURE_SENSOR "Temperature" + +#endif /* TEMPERATURE_SENSOR_H_ */ + +/** + * @} + * @} + */ diff --git a/platform/nrf52dk/platform-conf.h b/platform/nrf52dk/platform-conf.h new file mode 100644 index 000000000..d40fd2b3e --- /dev/null +++ b/platform/nrf52dk/platform-conf.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2015, Nordic Semiconductor + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \addtogroup platform + * @{ + * + * \addtogroup nrf52dk nRF52 Development Kit + * @{ + * + * \addtogroup nrf52dk-platform-conf Platform configuration + * @{ + * \file + * Platform features configuration. + * \author + * Wojciech Bober + * + */ +#ifndef PLATFORM_CONF_H_ +#define PLATFORM_CONF_H_ + +#include "boards.h" + +#define PLATFORM_HAS_BATTERY 0 +#define PLATFORM_HAS_RADIO 0 +#define PLATFORM_HAS_TEMPERATURE 1 + +/** + * \name Leds configurations + * + * On nRF52dk all leds are green. + * + * @{ + */ +#define PLATFORM_HAS_LEDS 1 + +#define LEDS_1 (1 << (LED_1 - LED_START)) // 1 +#define LEDS_2 (1 << (LED_2 - LED_START)) // 2 +#define LEDS_3 (1 << (LED_3 - LED_START)) // 4 +#define LEDS_4 (1 << (LED_4 - LED_START)) // 8 + +#define LEDS_GREEN LEDS_1 +#define LEDS_YELLOW LEDS_2 +#define LEDS_RED LEDS_3 +#define LEDS_BLUE LEDS_4 + +#define LEDS_CONF_ALL (LEDS_1 | LEDS_2 | LEDS_3 | LEDS_4) + +/** + * \brief If set to 1 then LED1 and LED2 are used by the + * platform to indicate BLE connection state. + */ +#define PLATFORM_INDICATE_BLE_STATE 1 +/** @} */ + +/** + * \name Button configurations + * + * @{ + */ +/* Notify various examples that we have Buttons */ +#define PLATFORM_HAS_BUTTON 1 + +/* + * Override button symbols from dev/button-sensor.h, for the examples that + * include it + */ +#define button_sensor button_1 +#define button_sensor2 button_2 + +/** + * \brief nRF52 RTC instance to be used for Contiki clock driver. + * \note RTC 0 is used by the SoftDevice. + */ +#define PLATFORM_RTC_INSTANCE_ID 1 + +/** + * \brief nRF52 timer instance to be used for Contiki rtimer driver. + * \note Timer 0 is used by the SoftDevice. + */ +#define PLATFORM_TIMER_INSTANCE_ID 1 + +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Compiler configuration and platform-specific type definitions + * + * Those values are not meant to be modified by the user + * @{ + */ +#define CLOCK_CONF_SECOND 128 + +/* Compiler configurations */ +#define CCIF +#define CLIF + +/* Platform typedefs */ +typedef uint32_t clock_time_t; +typedef uint32_t uip_stats_t; + +/* Clock (time) comparison macro */ +#define CLOCK_LT(a, b) ((signed long)((a) - (b)) < 0) + +#define RTIMER_ARCH_SECOND 62500 +/* + * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define + * RTIMER_CLOCK_DIFF to override this + */ +typedef uint32_t rtimer_clock_t; +#define RTIMER_CLOCK_DIFF(a,b) ((int32_t)((a)-(b))) + +/** @} */ +/*---------------------------------------------------------------------------*/ +/** @} + * @} + * @} + */ +#endif /* PLATFORM_CONF_H_ */ diff --git a/platform/nrf52dk/rtt/rtt-printf.c b/platform/nrf52dk/rtt/rtt-printf.c new file mode 100644 index 000000000..416fff0ab --- /dev/null +++ b/platform/nrf52dk/rtt/rtt-printf.c @@ -0,0 +1,24 @@ +#include +#include "segger-rtt.h" + +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); + +int +putchar(int c) +{ + SEGGER_RTT_Write(0, &c, 1); + return c; +} + +int +printf(const char *fmt, ...) +{ + int res; + va_list ap; + va_start(ap, fmt); + res = SEGGER_RTT_vprintf(0, fmt, &ap); + va_end(ap); + return res; +} + + diff --git a/platform/nrf52dk/rtt/segger-rtt-conf.h b/platform/nrf52dk/rtt/segger-rtt-conf.h new file mode 100644 index 000000000..ac996644f --- /dev/null +++ b/platform/nrf52dk/rtt/segger-rtt-conf.h @@ -0,0 +1,135 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +---------------------------------------------------------------------- +File : SEGGER_RTT_Conf.h +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. +---------------------------END-OF-HEADER------------------------------ +*/ + +#ifndef SEGGER_RTT_CONF_H +#define SEGGER_RTT_CONF_H + +#ifdef __ICCARM__ + #include +#endif + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ + +#define SEGGER_RTT_MAX_NUM_UP_BUFFERS (2) // Max. number of up-buffers (T->H) available on this target (Default: 2) +#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (2) // Max. number of down-buffers (H->T) available on this target (Default: 2) + +#define BUFFER_SIZE_UP (1024) // Size of the buffer for terminal output of target, up to host (Default: 1k) +#define BUFFER_SIZE_DOWN (16) // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16) + +#define SEGGER_RTT_PRINTF_BUFFER_SIZE (64u) // Size of buffer for RTT printf to bulk-send chars via RTT (Default: 64) + +#define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP // Mode for pre-initialized terminal channel (buffer 0) + +// +// Target is not allowed to perform other RTT operations while string still has not been stored completely. +// Otherwise we would probably end up with a mixed string in the buffer. +// If using RTT from within interrupts, multiple tasks or multi processors, define the SEGGER_RTT_LOCK() and SEGGER_RTT_UNLOCK() function here. +// +/********************************************************************* +* +* RTT lock configuration for SEGGER Embedded Studio, +* Rowley CrossStudio and GCC +*/ +#if (defined __SES_ARM) || (defined __CROSSWORKS_ARM) || (defined __GNUC__) + #ifdef __ARM_ARCH_6M__ + #define SEGGER_RTT_LOCK(SavedState) { \ + asm volatile ("mrs %0, primask \n\t" \ + "mov r1, $1 \n\t" \ + "msr primask, r1 \n\t" \ + : "=r" (SavedState) \ + : \ + : "r1" \ + ); \ + } + + #define SEGGER_RTT_UNLOCK(SavedState) { \ + asm volatile ("msr primask, %0 \n\t" \ + : \ + : "r" (SavedState) \ + : \ + ); \ + } + + #elif (defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)) + #define SEGGER_RTT_LOCK(SavedState) { \ + asm volatile ("mrs %0, basepri \n\t" \ + "mov r1, $128 \n\t" \ + "msr basepri, r1 \n\t" \ + : "=r" (SavedState) \ + : \ + : "r1" \ + ); \ + } + #define SEGGER_RTT_UNLOCK(SavedState) { \ + asm volatile ("msr basepri, %0 \n\t" \ + : \ + : "r" (SavedState) \ + : \ + ); \ + } + #else + #define SEGGER_RTT_LOCK(SavedState) (void)(SavedState) + #define SEGGER_RTT_UNLOCK(SavedState) (void)(SavedState) + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration for IAR EWARM +*/ +#ifdef __ICCARM__ + #if (defined (__ARM7M__) && (__CORE__ == __ARM7M__)) + #define SEGGER_RTT_LOCK(SavedState) { \ + SavedState = __get_PRIMASK(); \ + __set_PRIMASK(1); \ + } + + #define SEGGER_RTT_UNLOCK(SavedState) { \ + __set_PRIMASK(SavedState); \ + } + #elif (defined (__ARM7EM__) && (__CORE__ == __ARM7EM__)) + #define SEGGER_RTT_LOCK(SavedState) { \ + SavedState = __get_BASEPRI(); \ + __set_BASEPRI(128); \ + } + + #define SEGGER_RTT_UNLOCK(SavedState) { \ + __set_BASEPRI(SavedState); \ + } + #endif +#endif + +/********************************************************************* +* +* RTT lock configuration fallback +*/ +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK(SavedState) (void)(SavedState) +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK(SavedState) (void)(SavedState) +#endif + +#endif +/*************************** End of file ****************************/ diff --git a/platform/nrf52dk/rtt/segger-rtt-printf.c b/platform/nrf52dk/rtt/segger-rtt-printf.c new file mode 100644 index 000000000..e992e7a36 --- /dev/null +++ b/platform/nrf52dk/rtt/segger-rtt-printf.c @@ -0,0 +1,510 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT_printf.c +Purpose : Replacement for printf to write formatted data via RTT +---------------------------------------------------------------------- +*/ +#include "segger-rtt.h" +#include "segger-rtt-conf.h" + +/********************************************************************* +* +* Defines, configurable +* +********************************************************************** +*/ + +#ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE + #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64) +#endif + +#include +#include + + +#define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) +#define FORMAT_FLAG_PAD_ZERO (1u << 1) +#define FORMAT_FLAG_PRINT_SIGN (1u << 2) +#define FORMAT_FLAG_ALTERNATE (1u << 3) + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ + +typedef struct { + char* pBuffer; + unsigned BufferSize; + unsigned Cnt; + + int ReturnValue; + + unsigned RTTBufferIndex; +} SEGGER_RTT_PRINTF_DESC; + +/********************************************************************* +* +* Function prototypes +* +********************************************************************** +*/ +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); + +/********************************************************************* +* +* Static code +* +********************************************************************** +*/ +/********************************************************************* +* +* _StoreChar +*/ +static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) { + unsigned Cnt; + + Cnt = p->Cnt; + if ((Cnt + 1u) <= p->BufferSize) { + *(p->pBuffer + Cnt) = c; + p->Cnt = Cnt + 1u; + p->ReturnValue++; + } + // + // Write part of string, when the buffer is full + // + if (p->Cnt == p->BufferSize) { + if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) { + p->ReturnValue = -1; + } else { + p->Cnt = 0u; + } + } +} + +/********************************************************************* +* +* _PrintUnsigned +*/ +static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { + static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + unsigned Div; + unsigned Digit; + unsigned Number; + unsigned Width; + char c; + + Number = v; + Digit = 1u; + // + // Get actual field width + // + Width = 1u; + while (Number >= Base) { + Number = (Number / Base); + Width++; + } + if (NumDigits > Width) { + Width = NumDigits; + } + // + // Print leading chars if necessary + // + if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) { + if (FieldWidth != 0u) { + if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) { + c = '0'; + } else { + c = ' '; + } + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, c); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Compute Digit. + // Loop until Digit has the value of the highest digit required. + // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. + // + while (1) { + if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned) + NumDigits--; + } else { + Div = v / Digit; + if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done + break; + } + } + Digit *= Base; + } + // + // Output digits + // + do { + Div = v / Digit; + v -= Div * Digit; + _StoreChar(pBufferDesc, _aV2C[Div]); + if (pBufferDesc->ReturnValue < 0) { + break; + } + Digit /= Base; + } while (Digit); + // + // Print trailing spaces if necessary + // + if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, ' '); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + } +} + +/********************************************************************* +* +* _PrintInt +*/ +static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { + unsigned Width; + int Number; + + Number = (v < 0) ? -v : v; + + // + // Get actual field width + // + Width = 1u; + while (Number >= (int)Base) { + Number = (Number / (int)Base); + Width++; + } + if (NumDigits > Width) { + Width = NumDigits; + } + if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) { + FieldWidth--; + } + + // + // Print leading spaces if necessary + // + if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, ' '); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + // + // Print sign if necessary + // + if (pBufferDesc->ReturnValue >= 0) { + if (v < 0) { + v = -v; + _StoreChar(pBufferDesc, '-'); + } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) { + _StoreChar(pBufferDesc, '+'); + } else { + + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Print leading zeros if necessary + // + if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) { + if (FieldWidth != 0u) { + while ((FieldWidth != 0u) && (Width < FieldWidth)) { + FieldWidth--; + _StoreChar(pBufferDesc, '0'); + if (pBufferDesc->ReturnValue < 0) { + break; + } + } + } + } + if (pBufferDesc->ReturnValue >= 0) { + // + // Print number without sign + // + _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags); + } + } + } +} + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ +/********************************************************************* +* +* SEGGER_RTT_vprintf +* +* Function description +* Stores a formatted string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") +* sFormat Pointer to format string +* pParamList Pointer to the list of arguments for the format string +* +* Return values +* >= 0: Number of bytes which have been stored in the "Up"-buffer. +* < 0: Error +*/ +int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) { + char c; + SEGGER_RTT_PRINTF_DESC BufferDesc; + int v; + unsigned NumDigits; + unsigned FormatFlags; + unsigned FieldWidth; + char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE]; + + BufferDesc.pBuffer = acBuffer; + BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE; + BufferDesc.Cnt = 0u; + BufferDesc.RTTBufferIndex = BufferIndex; + BufferDesc.ReturnValue = 0; + + do { + c = *sFormat; + sFormat++; + if (c == 0u) { + break; + } + if (c == '%') { + // + // Filter out flags + // + FormatFlags = 0u; + v = 1; + do { + c = *sFormat; + switch (c) { + case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break; + case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break; + case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break; + case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break; + default: v = 0; break; + } + } while (v); + // + // filter out field with + // + FieldWidth = 0u; + do { + c = *sFormat; + if ((c < '0') || (c > '9')) { + break; + } + sFormat++; + FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0'); + } while (1); + + // + // Filter out precision (number of digits to display) + // + NumDigits = 0u; + c = *sFormat; + if (c == '.') { + sFormat++; + do { + c = *sFormat; + if (c == '*') { + sFormat++; + v = va_arg(*pParamList, int); + NumDigits = (unsigned)v; + break; + } + if ((c < '0') || (c > '9')) { + break; + } + sFormat++; + NumDigits = NumDigits * 10u + ((unsigned)c - '0'); + } while (1); + } + // + // Filter out length modifier + // + c = *sFormat; + do { + if ((c == 'l') || (c == 'h')) { + c = *sFormat; + sFormat++; + } else { + break; + } + } while (1); + // + // Handle specifiers + // + switch (c) { + case 'c': { + char c0; + v = va_arg(*pParamList, int); + c0 = (char)v; + _StoreChar(&BufferDesc, c0); + break; + } + case 'd': + v = va_arg(*pParamList, int); + _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); + break; + case 'u': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags); + break; + case 'x': + case 'X': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags); + break; + case 's': + { + const char * s = va_arg(*pParamList, const char *); + if (NumDigits > 0) { + do { + c = *s; + s++; + if (NumDigits == 0) { + break; + } + NumDigits--; + _StoreChar(&BufferDesc, c); + } while (BufferDesc.ReturnValue >= 0); + } else { + do { + c = *s; + s++; + if (c == '\0' || NumDigits == 0) { + break; + } + _StoreChar(&BufferDesc, c); + } while (BufferDesc.ReturnValue >= 0); + } + } + break; + case 'p': + v = va_arg(*pParamList, int); + _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u); + break; + case '%': + _StoreChar(&BufferDesc, '%'); + break; + default: + break; + } + sFormat++; + } else { + _StoreChar(&BufferDesc, c); + } + } while (BufferDesc.ReturnValue >= 0); + + if (BufferDesc.ReturnValue > 0) { + // + // Write remaining data, if any + // + if (BufferDesc.Cnt != 0u) { + SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt); + } + BufferDesc.ReturnValue += (int)BufferDesc.Cnt; + } + return BufferDesc.ReturnValue; +} + +/********************************************************************* +* +* SEGGER_RTT_printf +* +* Function description +* Stores a formatted string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") +* sFormat Pointer to format string, followed by the arguments for conversion +* +* Return values +* >= 0: Number of bytes which have been stored in the "Up"-buffer. +* < 0: Error +* +* Notes +* (1) Conversion specifications have following syntax: +* %[flags][FieldWidth][.Precision]ConversionSpecifier +* (2) Supported flags: +* -: Left justify within the field width +* +: Always print sign extension for signed conversions +* 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision +* Supported conversion specifiers: +* c: Print the argument as one char +* d: Print the argument as a signed integer +* u: Print the argument as an unsigned integer +* x: Print the argument as an hexadecimal integer +* s: Print the string pointed to by the argument +* p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.) +*/ +int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) { + va_list ParamList; + + va_start(ParamList, sFormat); + return SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList); +} +/*************************** End of file ****************************/ diff --git a/platform/nrf52dk/rtt/segger-rtt.c b/platform/nrf52dk/rtt/segger-rtt.c new file mode 100644 index 000000000..453a6a0e4 --- /dev/null +++ b/platform/nrf52dk/rtt/segger-rtt.c @@ -0,0 +1,1102 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.c +Purpose : Implementation of SEGGER real-time transfer (RTT) which + allows real-time communication on targets which support + debugger memory accesses while the CPU is running. + +Additional information: + Type "int" is assumed to be 32-bits in size + H->T Host to target communication + T->H Target to host communication + + RTT channel 0 is always present and reserved for Terminal usage. + Name is fixed to "Terminal" + +---------------------------------------------------------------------- +*/ + +#include "segger-rtt.h" + +#include // for memcpy + +/********************************************************************* +* +* Configuration, default values +* +********************************************************************** +*/ + +#ifndef BUFFER_SIZE_UP + #define BUFFER_SIZE_UP 1024 // Size of the buffer for terminal output of target, up to host +#endif + +#ifndef BUFFER_SIZE_DOWN + #define BUFFER_SIZE_DOWN 16 // Size of the buffer for terminal input to target from host (Usually keyboard input) +#endif + +#ifndef SEGGER_RTT_MAX_NUM_UP_BUFFERS + #define SEGGER_RTT_MAX_NUM_UP_BUFFERS 2 // Number of up-buffers (T->H) available on this target +#endif + +#ifndef SEGGER_RTT_MAX_NUM_DOWN_BUFFERS + #define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS 2 // Number of down-buffers (H->T) available on this target +#endif + +#ifndef SEGGER_RTT_MODE_DEFAULT + #define SEGGER_RTT_MODE_DEFAULT SEGGER_RTT_MODE_NO_BLOCK_SKIP +#endif + +#ifndef SEGGER_RTT_LOCK + #define SEGGER_RTT_LOCK(SavedState) +#endif + +#ifndef SEGGER_RTT_UNLOCK + #define SEGGER_RTT_UNLOCK(SavedState) +#endif + +#ifndef STRLEN + #define STRLEN(a) strlen((a)) +#endif + +#ifndef MEMCPY + #define MEMCPY(pDest, pSrc, NumBytes) memcpy((pDest), (pSrc), (NumBytes)) +#endif + +#ifndef MIN + #define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX + #define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif +// +// For some environments, NULL may not be defined until certain headers are included +// +#ifndef NULL + #define NULL 0 +#endif + +/********************************************************************* +* +* Static const data +* +********************************************************************** +*/ + +static unsigned char _aTerminalId[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + +/********************************************************************* +* +* Static data +* +********************************************************************** +*/ +// +// Allocate buffers for channel 0 +// +static char _acUpBuffer [BUFFER_SIZE_UP]; +static char _acDownBuffer[BUFFER_SIZE_DOWN]; +// +// Initialize SEGGER Real-time-Terminal control block (CB) +// +SEGGER_RTT_CB _SEGGER_RTT; + +static char _ActiveTerminal; + +/********************************************************************* +* +* Static functions +* +********************************************************************** +*/ + +/********************************************************************* +* +* _DoInit() +* +* Function description +* Initializes the control block an buffers. +* May only be called via INIT() to avoid overriding settings. +* +*/ +#define INIT() do { \ + if (_SEGGER_RTT.acID[0] == '\0') { _DoInit(); } \ + } while (0) +static void _DoInit(void) { + SEGGER_RTT_CB* p; + // + // Initialize control block + // + p = &_SEGGER_RTT; + p->MaxNumUpBuffers = SEGGER_RTT_MAX_NUM_UP_BUFFERS; + p->MaxNumDownBuffers = SEGGER_RTT_MAX_NUM_DOWN_BUFFERS; + // + // Initialize up buffer 0 + // + p->aUp[0].sName = "Terminal"; + p->aUp[0].pBuffer = _acUpBuffer; + p->aUp[0].SizeOfBuffer = sizeof(_acUpBuffer); + p->aUp[0].RdOff = 0u; + p->aUp[0].WrOff = 0u; + p->aUp[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Initialize down buffer 0 + // + p->aDown[0].sName = "Terminal"; + p->aDown[0].pBuffer = _acDownBuffer; + p->aDown[0].SizeOfBuffer = sizeof(_acDownBuffer); + p->aDown[0].RdOff = 0u; + p->aDown[0].WrOff = 0u; + p->aDown[0].Flags = SEGGER_RTT_MODE_DEFAULT; + // + // Finish initialization of the control block. + // Copy Id string in three steps to make sure "SEGGER RTT" is not found + // in initializer memory (usually flash) by J-Link + // + strcpy(&p->acID[7], "RTT"); + strcpy(&p->acID[0], "SEGGER"); + p->acID[6] = ' '; +} + +/********************************************************************* +* +* _WriteBlocking() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* The caller is responsible for managing the write chunk sizes as +* _WriteBlocking() will block until all data has been posted successfully. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* >= 0 - Number of bytes written into buffer. +*/ +static unsigned _WriteBlocking(SEGGER_RTT_RING_BUFFER *pRing, const char* pBuffer, unsigned NumBytes) { + unsigned NumBytesToWrite; + unsigned NumBytesWritten; + unsigned RdOff; + unsigned WrOff; + // + // Write data to buffer and handle wrap-around if necessary + // + NumBytesWritten = 0u; + WrOff = pRing->WrOff; + do { + RdOff = pRing->RdOff; // May be changed by host (debug probe) in the meantime + if (RdOff > WrOff) { + NumBytesToWrite = RdOff - WrOff - 1u; + } else { + NumBytesToWrite = pRing->SizeOfBuffer - (WrOff - RdOff + 1u); + } + NumBytesToWrite = MIN(NumBytesToWrite, (pRing->SizeOfBuffer - WrOff)); // Number of bytes that can be written until buffer wrap-around + NumBytesToWrite = MIN(NumBytesToWrite, NumBytes); + memcpy(pRing->pBuffer + WrOff, pBuffer, NumBytesToWrite); + NumBytesWritten += NumBytesToWrite; + pBuffer += NumBytesToWrite; + NumBytes -= NumBytesToWrite; + WrOff += NumBytesToWrite; + if (WrOff == pRing->SizeOfBuffer) { + WrOff = 0u; + } + pRing->WrOff = WrOff; + } while (NumBytes); + // + return NumBytesWritten; +} + +/********************************************************************* +* +* _WriteNoCheck() +* +* Function description +* Stores a specified number of characters in SEGGER RTT ring buffer +* and updates the associated write pointer which is periodically +* read by the host. +* It is callers responsibility to make sure data actually fits in buffer. +* +* Parameters +* pRing Ring buffer to post to. +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Notes +* (1) If there might not be enough space in the "Up"-buffer, call _WriteBlocking +*/ +static void _WriteNoCheck(SEGGER_RTT_RING_BUFFER *pRing, const char* pData, unsigned NumBytes) { + unsigned NumBytesAtOnce; + unsigned WrOff; + unsigned Rem; + + WrOff = pRing->WrOff; + Rem = pRing->SizeOfBuffer - WrOff; + if (Rem > NumBytes) { + // + // All data fits before wrap around + // + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + } else { + // + // We reach the end of the buffer, so need to wrap around + // + NumBytesAtOnce = Rem; + memcpy(pRing->pBuffer + WrOff, pData, NumBytesAtOnce); + NumBytesAtOnce = NumBytes - Rem; + memcpy(pRing->pBuffer, pData + Rem, NumBytesAtOnce); + pRing->WrOff = NumBytesAtOnce; + } +} + +/********************************************************************* +* +* _PostTerminalSwitch() +* +* Function description +* Switch terminal to the given terminal ID. It is the caller's +* responsibility to ensure the terminal ID is correct and there is +* enough space in the buffer for this to complete successfully. +* +* Parameters +* pRing Ring buffer to post to. +* TerminalId Terminal ID to switch to. +*/ +static void _PostTerminalSwitch(SEGGER_RTT_RING_BUFFER *pRing, char TerminalId) { + char ac[2]; + + ac[0] = 0xFFu; + ac[1] = _aTerminalId[(int)TerminalId]; // Caller made already sure that TerminalId does not exceed our terminal limit + _WriteBlocking(pRing, ac, 2u); +} + +/********************************************************************* +* +* _GetAvailWriteSpace() +* +* Function description +* Returns the number of bytes that can be written to the ring +* buffer without blocking. +* +* Parameters +* pRing Ring buffer to check. +* +* Return value +* Number of bytes that are free in the buffer. +*/ +static unsigned _GetAvailWriteSpace(SEGGER_RTT_RING_BUFFER *pRing) { + unsigned RdOff; + unsigned WrOff; + unsigned r; + // + // Avoid warnings regarding volatile access order. It's not a problem + // in this case, but dampen compiler enthusiasm. + // + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + if (RdOff <= WrOff) { + r = pRing->SizeOfBuffer - 1u - WrOff + RdOff; + } else { + r = RdOff - WrOff - 1u; + } + return r; +} + +/********************************************************************* +* +* Public code +* +********************************************************************** +*/ +/********************************************************************* +* +* SEGGER_RTT_ReadNoLock() +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* Do not lock against interrupts and multiple access. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) { + unsigned NumBytesRem; + unsigned NumBytesRead; + unsigned RdOff; + unsigned WrOff; + unsigned char* pBuffer; + SEGGER_RTT_RING_BUFFER* pRing; + // + INIT(); + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + pBuffer = (unsigned char*)pData; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + NumBytesRead = 0u; + // + // Read from current read position to wrap-around of buffer, first + // + if (RdOff > WrOff) { + NumBytesRem = pRing->SizeOfBuffer - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); + memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + // + // Handle wrap-around of buffer + // + if (RdOff == pRing->SizeOfBuffer) { + RdOff = 0u; + } + } + // + // Read remaining items of buffer + // + NumBytesRem = WrOff - RdOff; + NumBytesRem = MIN(NumBytesRem, BufferSize); + if (NumBytesRem > 0u) { + memcpy(pBuffer, pRing->pBuffer + RdOff, NumBytesRem); + NumBytesRead += NumBytesRem; + pBuffer += NumBytesRem; + BufferSize -= NumBytesRem; + RdOff += NumBytesRem; + } + if (NumBytesRead) { + pRing->RdOff = RdOff; + } + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_Read +* +* Function description +* Reads characters from SEGGER real-time-terminal control block +* which have been previously stored by the host. +* +* Parameters +* BufferIndex Index of Down-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to buffer provided by target application, to copy characters from RTT-down-buffer to. +* BufferSize Size of the target application buffer. +* +* Return value +* Number of bytes that have been read. +*/ +unsigned SEGGER_RTT_Read(unsigned BufferIndex, void* pBuffer, unsigned BufferSize) { + unsigned NumBytesRead; + volatile unsigned SavedState; + // + SEGGER_RTT_LOCK(SavedState); + // + // Call the non-locking read function + // + NumBytesRead = SEGGER_RTT_ReadNoLock(BufferIndex, pBuffer, BufferSize); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(SavedState); + // + return NumBytesRead; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteSkipNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteSkipNoLock does not lock the application and +* skips all data, if the data does not fit into the buffer. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, all data is dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + const char* pData; + SEGGER_RTT_RING_BUFFER* pRing; + unsigned Avail; + unsigned RdOff; + unsigned WrOff; + unsigned Rem; + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer and copy some elements into local variables. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + RdOff = pRing->RdOff; + WrOff = pRing->WrOff; + // + // Handle the most common cases fastest. + // Which is: + // RdOff <= WrOff -> Space until wrap around is free. + // AND + // WrOff + NumBytes < SizeOfBuffer -> No Wrap around necessary. + // + // OR + // + // RdOff > WrOff -> Space until RdOff - 1 is free. + // AND + // WrOff + NumBytes < RdOff -> Data fits into buffer + // + if (RdOff <= WrOff) { + // + // Get space until WrOff will be at wrap around. + // + Avail = pRing->SizeOfBuffer - 1u - WrOff ; + if (Avail >= NumBytes) { + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + return 1; + } + // + // If data did not fit into space until wrap around calculate complete space in buffer. + // + Avail += RdOff; + // + // If there is still no space for the whole of this output, don't bother. + // + if (Avail >= NumBytes) { + // + // OK, we have enough space in buffer. Copy in one or 2 chunks + // + Rem = pRing->SizeOfBuffer - WrOff; // Space until end of buffer + if (Rem > NumBytes) { + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + } else { + // + // We reach the end of the buffer, so need to wrap around + // + memcpy(pRing->pBuffer + WrOff, pData, Rem); + memcpy(pRing->pBuffer, pData + Rem, NumBytes - Rem); + pRing->WrOff = NumBytes - Rem; + } + return 1; + } + } else { + Avail = RdOff - WrOff - 1u; + if (Avail >= NumBytes) { + memcpy(pRing->pBuffer + WrOff, pData, NumBytes); + pRing->WrOff = WrOff + NumBytes; + return 1; + } + } + // + // If we reach this point no data has been written + // + return 0; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteNoLock +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* SEGGER_RTT_WriteNoLock does not lock the application. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. +* (2) For performance reasons this function does not call Init() +* and may only be called after RTT has been initialized. +* Either by calling SEGGER_RTT_Init() or calling another RTT API function first. +*/ +unsigned SEGGER_RTT_WriteNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + unsigned Avail; + const char* pData; + SEGGER_RTT_RING_BUFFER *pRing; + + pData = (const char *)pBuffer; + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[BufferIndex]; + // + // How we output depends upon the mode... + // + switch (pRing->Flags) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother. + // + Avail = _GetAvailWriteSpace(pRing); + if (Avail < NumBytes) { + Status = 0u; + } else { + Status = NumBytes; + _WriteNoCheck(pRing, pData, NumBytes); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode, trim to what we can output without blocking. + // + Avail = _GetAvailWriteSpace(pRing); + Status = Avail < NumBytes ? Avail : NumBytes; + _WriteNoCheck(pRing, pData, Status); + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + Status = _WriteBlocking(pRing, pData, NumBytes); + break; + default: + Status = 0u; + break; + } + // + // Finish up. + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_Write +* +* Function description +* Stores a specified number of characters in SEGGER RTT +* control block which is then read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* pBuffer Pointer to character array. Does not need to point to a \0 terminated string. +* NumBytes Number of bytes to be stored in the SEGGER RTT control block. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, remaining characters of pBuffer are dropped. +*/ +unsigned SEGGER_RTT_Write(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) { + unsigned Status; + volatile unsigned SavedState; + // + INIT(); + SEGGER_RTT_LOCK(SavedState); + // + // Call the non-locking write function + // + Status = SEGGER_RTT_WriteNoLock(BufferIndex, pBuffer, NumBytes); + // + // Finish up. + // + SEGGER_RTT_UNLOCK(SavedState); + // + return Status; +} + +/********************************************************************* +* +* SEGGER_RTT_WriteString +* +* Function description +* Stores string in SEGGER RTT control block. +* This data is read by the host. +* +* Parameters +* BufferIndex Index of "Up"-buffer to be used (e.g. 0 for "Terminal"). +* s Pointer to string. +* +* Return value +* Number of bytes which have been stored in the "Up"-buffer. +* +* Notes +* (1) If there is not enough space in the "Up"-buffer, depending on configuration, +* remaining characters may be dropped or RTT module waits until there is more space in the buffer. +* (2) String passed to this function has to be \0 terminated +* (3) \0 termination character is *not* stored in RTT buffer +*/ +unsigned SEGGER_RTT_WriteString(unsigned BufferIndex, const char* s) { + unsigned Len; + + Len = STRLEN(s); + return SEGGER_RTT_Write(BufferIndex, s, Len); +} + +/********************************************************************* +* +* SEGGER_RTT_GetKey +* +* Function description +* Reads one character from the SEGGER RTT buffer. +* Host has previously stored data there. +* +* Return value +* < 0 - No character available (buffer empty). +* >= 0 - Character which has been read. (Possible values: 0 - 255) +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0. +*/ +int SEGGER_RTT_GetKey(void) { + char c; + int r; + + r = (int)SEGGER_RTT_Read(0u, &c, 1u); + if (r == 1) { + r = (int)(unsigned char)c; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_WaitKey +* +* Function description +* Waits until at least one character is avaible in the SEGGER RTT buffer. +* Once a character is available, it is read and this function returns. +* +* Return value +* >=0 - Character which has been read. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +* (2) This function is blocking if no character is present in RTT buffer +*/ +int SEGGER_RTT_WaitKey(void) { + int r; + + do { + r = SEGGER_RTT_GetKey(); + } while (r < 0); + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasKey +* +* Function description +* Checks if at least one character for reading is available in the SEGGER RTT buffer. +* +* Return value +* == 0 - No characters are available to read. +* == 1 - At least one character is available. +* +* Notes +* (1) This function is only specified for accesses to RTT buffer 0 +*/ +int SEGGER_RTT_HasKey(void) { + unsigned RdOff; + int r; + + INIT(); + RdOff = _SEGGER_RTT.aDown[0].RdOff; + if (RdOff != _SEGGER_RTT.aDown[0].WrOff) { + r = 1; + } else { + r = 0; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_HasData +* +* Function description +* Check if there is data from the host in the given buffer. +* +* Return value: +* ==0: No data +* !=0: Data in buffer +* +*/ +unsigned SEGGER_RTT_HasData(unsigned BufferIndex) { + SEGGER_RTT_RING_BUFFER *pRing; + unsigned v; + + pRing = &_SEGGER_RTT.aDown[BufferIndex]; + v = pRing->WrOff; + return v - pRing->RdOff; +} + + +/********************************************************************* +* +* SEGGER_RTT_ConfigUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer (T->H). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 - O.K. +* < 0 - Error +*/ +int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + volatile unsigned SavedState; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(SavedState); + if (BufferIndex > 0u) { + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + _SEGGER_RTT.aUp[BufferIndex].pBuffer = pBuffer; + _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aUp[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aUp[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aUp[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(SavedState); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_ConfigDownBuffer +* +* Function description +* Run-time configuration of a specific down-buffer (H->T). +* Buffer to be configured is specified by index. +* This includes: Buffer address, size, name, flags, ... +* +* Parameters +* BufferIndex Index of the buffer to configure. +* sName Pointer to a constant name string. +* pBuffer Pointer to a buffer to be used. +* BufferSize Size of the buffer. +* Flags Operating modes. Define behavior if buffer is full (not enough space for entire message). +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) { + int r; + volatile unsigned SavedState; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(SavedState); + if (BufferIndex > 0u) { + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + _SEGGER_RTT.aDown[BufferIndex].pBuffer = pBuffer; + _SEGGER_RTT.aDown[BufferIndex].SizeOfBuffer = BufferSize; + _SEGGER_RTT.aDown[BufferIndex].RdOff = 0u; + _SEGGER_RTT.aDown[BufferIndex].WrOff = 0u; + } + _SEGGER_RTT.aDown[BufferIndex].Flags = Flags; + SEGGER_RTT_UNLOCK(SavedState); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameUpBuffer +* +* Function description +* Run-time configuration of a specific up-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameUpBuffer(unsigned BufferIndex, const char* sName) { + int r; + volatile unsigned SavedState; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) { + SEGGER_RTT_LOCK(SavedState); + _SEGGER_RTT.aUp[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(SavedState); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_SetNameDownBuffer +* +* Function description +* Run-time configuration of a specific Down-buffer name (T->H). +* Buffer to be configured is specified by index. +* +* Parameters +* BufferIndex Index of the buffer to renamed. +* sName Pointer to a constant name string. +* +* Return value +* >= 0 O.K. +* < 0 Error +*/ +int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName) { + int r; + volatile unsigned SavedState; + + INIT(); + if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumDownBuffers) { + SEGGER_RTT_LOCK(SavedState); + _SEGGER_RTT.aDown[BufferIndex].sName = sName; + SEGGER_RTT_UNLOCK(SavedState); + r = 0; + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_Init +* +* Function description +* Initializes the RTT Control Block. +* Should be used in RAM targets, at start of the application. +* +*/ +void SEGGER_RTT_Init (void) { + INIT(); +} + +/********************************************************************* +* +* SEGGER_RTT_SetTerminal +* +* Function description +* Sets the terminal to be used for output on channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* +* Return value +* >= 0 O.K. +* < 0 Error (e.g. if RTT is configured for non-blocking mode and there was no space in the buffer to set the new terminal Id) +*/ +int SEGGER_RTT_SetTerminal (char TerminalId) { + char ac[2]; + SEGGER_RTT_RING_BUFFER *pRing; + volatile unsigned SavedState; + unsigned Avail; + int r; + // + INIT(); + // + r = 0; + ac[0] = 0xFFU; + if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels + ac[1] = _aTerminalId[(int)TerminalId]; + pRing = &_SEGGER_RTT.aUp[0]; // Buffer 0 is always reserved for terminal I/O, so we can use index 0 here, fixed + SEGGER_RTT_LOCK(SavedState); // Lock to make sure that no other task is writing into buffer, while we are and number of free bytes in buffer does not change downwards after checking and before writing + if ((pRing->Flags & SEGGER_RTT_MODE_MASK) == SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL) { + _ActiveTerminal = TerminalId; + _WriteBlocking(pRing, ac, 2u); + } else { // Skipping mode or trim mode? => We cannot trim this command so handling is the same for both modes + Avail = _GetAvailWriteSpace(pRing); + if (Avail >= 2) { + _ActiveTerminal = TerminalId; // Only change active terminal in case of success + _WriteNoCheck(pRing, ac, 2u); + } else { + r = -1; + } + } + SEGGER_RTT_UNLOCK(SavedState); + } else { + r = -1; + } + return r; +} + +/********************************************************************* +* +* SEGGER_RTT_TerminalOut +* +* Function description +* Writes a string to the given terminal +* without changing the terminal for channel 0. +* +* Parameters +* TerminalId Index of the terminal. +* s String to be printed on the terminal. +* +* Return value +* >= 0 - Number of bytes written. +* < 0 - Error. +* +*/ +int SEGGER_RTT_TerminalOut (char TerminalId, const char* s) { + int Status; + unsigned FragLen; + unsigned Avail; + SEGGER_RTT_RING_BUFFER *pRing; + volatile unsigned SavedState; + // + INIT(); + // + // Validate terminal ID. + // + if (TerminalId < (char)sizeof(_aTerminalId)) { // We only support a certain number of channels + // + // Get "to-host" ring buffer. + // + pRing = &_SEGGER_RTT.aUp[0]; + // + // Need to be able to change terminal, write data, change back. + // Compute the fixed and variable sizes. + // + FragLen = strlen(s); + // + // How we output depends upon the mode... + // + SEGGER_RTT_LOCK(SavedState); + Avail = _GetAvailWriteSpace(pRing); + switch (pRing->Flags & SEGGER_RTT_MODE_MASK) { + case SEGGER_RTT_MODE_NO_BLOCK_SKIP: + // + // If we are in skip mode and there is no space for the whole + // of this output, don't bother switching terminals at all. + // + if (Avail < (FragLen + 4u)) { + Status = 0; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_NO_BLOCK_TRIM: + // + // If we are in trim mode and there is not enough space for everything, + // trim the output but always include the terminal switch. If no room + // for terminal switch, skip that totally. + // + if (Avail < 4u) { + Status = -1; + } else { + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, (FragLen < (Avail - 4u)) ? FragLen : (Avail - 4u)); + _PostTerminalSwitch(pRing, _ActiveTerminal); + } + break; + case SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL: + // + // If we are in blocking mode, output everything. + // + _PostTerminalSwitch(pRing, TerminalId); + Status = (int)_WriteBlocking(pRing, s, FragLen); + _PostTerminalSwitch(pRing, _ActiveTerminal); + break; + default: + Status = -1; + break; + } + // + // Finish up. + // + SEGGER_RTT_UNLOCK(SavedState); + } else { + Status = -1; + } + return Status; +} + + +/*************************** End of file ****************************/ diff --git a/platform/nrf52dk/rtt/segger-rtt.h b/platform/nrf52dk/rtt/segger-rtt.h new file mode 100644 index 000000000..e3436c462 --- /dev/null +++ b/platform/nrf52dk/rtt/segger-rtt.h @@ -0,0 +1,204 @@ +/********************************************************************* +* SEGGER MICROCONTROLLER GmbH & Co. KG * +* Solutions for real time microcontroller applications * +********************************************************************** +* * +* (c) 2014 - 2015 SEGGER Microcontroller GmbH & Co. KG * +* * +* www.segger.com Support: support@segger.com * +* * +********************************************************************** +* * +* All rights reserved. * +* * +* * This software may in its unmodified form be freely redistributed * +* in source form. * +* * The source code may be modified, provided the source code * +* retains the above copyright notice, this list of conditions and * +* the following disclaimer. * +* * Modified versions of this software in source or linkable form * +* may not be distributed without prior consent of SEGGER. * +* * This software may only be used for communication with SEGGER * +* J-Link debug probes. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * +* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * +* DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * +* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * +* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * +* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * +* DAMAGE. * +* * +********************************************************************** +---------------------------END-OF-HEADER------------------------------ +File : SEGGER_RTT.h +Purpose : Implementation of SEGGER real-time transfer which allows + real-time communication on targets which support debugger + memory accesses while the CPU is running. +---------------------------------------------------------------------- +*/ + +#ifndef SEGGER_RTT_H +#define SEGGER_RTT_H + +#include "segger-rtt-conf.h" + +/********************************************************************* +* +* Defines, fixed +* +********************************************************************** +*/ + +/********************************************************************* +* +* Types +* +********************************************************************** +*/ + +// +// Description for a circular buffer (also called "ring buffer") +// which is used as up- (T->H) or down-buffer (H->T) +// +typedef struct { + const char* sName; // Optional name. Standard names so far are: "Terminal", "SysView", "J-Scope_t4i4" + char* pBuffer; // Pointer to start of buffer + unsigned SizeOfBuffer; // Buffer size in bytes. Note that one byte is lost, as this implementation does not fill up the buffer in order to avoid the problem of being unable to distinguish between full and empty. + volatile unsigned WrOff; // Position of next item to be written by either host (down-buffer) or target (up-buffer). Must be volatile since it may be modified by host (down-buffer) + volatile unsigned RdOff; // Position of next item to be read by target (down-buffer) or host (up-buffer). Must be volatile since it may be modified by host (up-buffer) + unsigned Flags; // Contains configuration flags +} SEGGER_RTT_RING_BUFFER; + +// +// RTT control block which describes the number of buffers available +// as well as the configuration for each buffer +// +// +typedef struct { + char acID[16]; // Initialized to "SEGGER RTT" + int MaxNumUpBuffers; // Initialized to SEGGER_RTT_MAX_NUM_UP_BUFFERS (type. 2) + int MaxNumDownBuffers; // Initialized to SEGGER_RTT_MAX_NUM_DOWN_BUFFERS (type. 2) + SEGGER_RTT_RING_BUFFER aUp[SEGGER_RTT_MAX_NUM_UP_BUFFERS]; // Up buffers, transferring information up from target via debug probe to host + SEGGER_RTT_RING_BUFFER aDown[SEGGER_RTT_MAX_NUM_DOWN_BUFFERS]; // Down buffers, transferring information down from host via debug probe to target +} SEGGER_RTT_CB; + +/********************************************************************* +* +* Global data +* +********************************************************************** +*/ +extern SEGGER_RTT_CB _SEGGER_RTT; + +/********************************************************************* +* +* RTT API functions +* +********************************************************************** +*/ +int SEGGER_RTT_ConfigUpBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_ConfigDownBuffer (unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags); +int SEGGER_RTT_GetKey (void); +unsigned SEGGER_RTT_HasData (unsigned BufferIndex); +int SEGGER_RTT_HasKey (void); +void SEGGER_RTT_Init (void); +unsigned SEGGER_RTT_Read (unsigned BufferIndex, void* pBuffer, unsigned BufferSize); +unsigned SEGGER_RTT_ReadNoLock (unsigned BufferIndex, void* pData, unsigned BufferSize); +int SEGGER_RTT_SetNameDownBuffer(unsigned BufferIndex, const char* sName); +int SEGGER_RTT_SetNameUpBuffer (unsigned BufferIndex, const char* sName); +int SEGGER_RTT_WaitKey (void); +unsigned SEGGER_RTT_Write (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteSkipNoLock (unsigned BufferIndex, const void* pBuffer, unsigned NumBytes); +unsigned SEGGER_RTT_WriteString (unsigned BufferIndex, const char* s); +// +// Function macro for performance optimization +// +#define SEGGER_RTT_HASDATA(n) (_SEGGER_RTT.aDown[n].WrOff - _SEGGER_RTT.aDown[n].RdOff) + +/********************************************************************* +* +* RTT "Terminal" API functions +* +********************************************************************** +*/ +int SEGGER_RTT_SetTerminal (char TerminalId); +int SEGGER_RTT_TerminalOut (char TerminalId, const char* s); + +/********************************************************************* +* +* RTT printf functions (require SEGGER_RTT_printf.c) +* +********************************************************************** +*/ +int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...); + +/********************************************************************* +* +* Defines +* +********************************************************************** +*/ + +// +// Operating modes. Define behavior if buffer is full (not enough space for entire message) +// +#define SEGGER_RTT_MODE_NO_BLOCK_SKIP (0U) // Skip. Do not block, output nothing. (Default) +#define SEGGER_RTT_MODE_NO_BLOCK_TRIM (1U) // Trim: Do not block, output as much as fits. +#define SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL (2U) // Block: Wait until there is space in the buffer. +#define SEGGER_RTT_MODE_MASK (3U) + +// +// Control sequences, based on ANSI. +// Can be used to control color, and clear the screen +// +#define RTT_CTRL_RESET "\e[0m" // Reset to default colors +#define RTT_CTRL_CLEAR "\e[2J" // Clear screen, reposition cursor to top left + +#define RTT_CTRL_TEXT_BLACK "\e[2;30m" +#define RTT_CTRL_TEXT_RED "\e[2;31m" +#define RTT_CTRL_TEXT_GREEN "\e[2;32m" +#define RTT_CTRL_TEXT_YELLOW "\e[2;33m" +#define RTT_CTRL_TEXT_BLUE "\e[2;34m" +#define RTT_CTRL_TEXT_MAGENTA "\e[2;35m" +#define RTT_CTRL_TEXT_CYAN "\e[2;36m" +#define RTT_CTRL_TEXT_WHITE "\e[2;37m" + +#define RTT_CTRL_TEXT_BRIGHT_BLACK "\e[1;30m" +#define RTT_CTRL_TEXT_BRIGHT_RED "\e[1;31m" +#define RTT_CTRL_TEXT_BRIGHT_GREEN "\e[1;32m" +#define RTT_CTRL_TEXT_BRIGHT_YELLOW "\e[1;33m" +#define RTT_CTRL_TEXT_BRIGHT_BLUE "\e[1;34m" +#define RTT_CTRL_TEXT_BRIGHT_MAGENTA "\e[1;35m" +#define RTT_CTRL_TEXT_BRIGHT_CYAN "\e[1;36m" +#define RTT_CTRL_TEXT_BRIGHT_WHITE "\e[1;37m" + +#define RTT_CTRL_BG_BLACK "\e[24;40m" +#define RTT_CTRL_BG_RED "\e[24;41m" +#define RTT_CTRL_BG_GREEN "\e[24;42m" +#define RTT_CTRL_BG_YELLOW "\e[24;43m" +#define RTT_CTRL_BG_BLUE "\e[24;44m" +#define RTT_CTRL_BG_MAGENTA "\e[24;45m" +#define RTT_CTRL_BG_CYAN "\e[24;46m" +#define RTT_CTRL_BG_WHITE "\e[24;47m" + +#define RTT_CTRL_BG_BRIGHT_BLACK "\e[4;40m" +#define RTT_CTRL_BG_BRIGHT_RED "\e[4;41m" +#define RTT_CTRL_BG_BRIGHT_GREEN "\e[4;42m" +#define RTT_CTRL_BG_BRIGHT_YELLOW "\e[4;43m" +#define RTT_CTRL_BG_BRIGHT_BLUE "\e[4;44m" +#define RTT_CTRL_BG_BRIGHT_MAGENTA "\e[4;45m" +#define RTT_CTRL_BG_BRIGHT_CYAN "\e[4;46m" +#define RTT_CTRL_BG_BRIGHT_WHITE "\e[4;47m" + + +#endif + +/*************************** End of file ****************************/ diff --git a/platform/openmote-cc2538/Makefile.openmote-cc2538 b/platform/openmote-cc2538/Makefile.openmote-cc2538 new file mode 100644 index 000000000..3439a3211 --- /dev/null +++ b/platform/openmote-cc2538/Makefile.openmote-cc2538 @@ -0,0 +1,50 @@ +# openmote-cc2538 platform makefile + +ifndef CONTIKI + $(error CONTIKI not defined! You must specify where CONTIKI resides!) +endif + +### Configure the build for the board and pull in board-specific sources +CONTIKI_TARGET_DIRS += . dev +PLATFORM_ROOT_DIR = $(CONTIKI)/platform/$(TARGET) + +### Include +CONTIKI_TARGET_SOURCEFILES += contiki-main.c board.c +CONTIKI_TARGET_SOURCEFILES += leds-arch.c button-sensor.c openmote-sensors.c +CONTIKI_TARGET_SOURCEFILES += antenna.c adxl346.c max44009.c sht21.c tps62730.c + +CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) + +CLEAN += *.openmote-cc2538 + +### Unless the example dictates otherwise, build with code size optimisations +ifndef SMALL + SMALL = 1 +endif + +### Define the CPU directory +CONTIKI_CPU=$(CONTIKI)/cpu/cc2538 +include $(CONTIKI_CPU)/Makefile.cc2538 + +MODULES += core/net core/net/mac \ + core/net/mac/contikimac \ + core/net/llsec core/net/llsec/noncoresec + +PYTHON = python +BSL_FLAGS += -e -w -v -b 450000 + +ifdef PORT + BSL_FLAGS += -p $(PORT) +endif + +BSL = $(CONTIKI)/tools/cc2538-bsl/cc2538-bsl.py + +%.upload: %.bin %.elf +ifeq ($(wildcard $(BSL)), ) + @echo "ERROR: Could not find the cc2538-bsl script. Did you run 'git submodule update --init' ?" +else + $(eval BSL_ADDRESS_ARG := -a $(shell $(OBJDUMP) -h $*.elf | grep -B1 LOAD | \ + grep -Ev 'LOAD|\-\-' | awk '{print "0x" $$5}' | \ + sort -g | head -1)) + $(PYTHON) $(BSL) $(BSL_FLAGS) $(BSL_ADDRESS_ARG) $< +endif diff --git a/platform/openmote-cc2538/README.md b/platform/openmote-cc2538/README.md new file mode 100644 index 000000000..2f3ee7d07 --- /dev/null +++ b/platform/openmote-cc2538/README.md @@ -0,0 +1,189 @@ +OpenMote-CC2538 platform +======================== +The OpenMote-CC2538 is based on TI's CC2538 SoC (System on Chip), featuring an ARM Cortex-M3 running at 16/32 MHz and with 32 kbytes of RAM and 512 kbytes of FLASH. It has the following key features: + + * Standard Cortex M3 peripherals (NVIC, SCB, SysTick) + * Sleep Timer (underpins rtimers) + * SysTick (underpins the platform clock and Contiki's timers infrastructure) + * RF (2.4 GHz) + * UART + * Watchdog (in watchdog mode) + * USB (in CDC-ACM) + * uDMA Controller (RAM to/from USB and RAM to/from RF) + * Random number generator + * Low Power Modes + * General-Purpose Timers + * ADC + * Cryptoprocessor (AES-ECB/CBC/CTR/CBC-MAC/GCM/CCM-128/192/256, SHA-256) + * Public Key Accelerator (ECDH, ECDSA) + * Flash-based port of Coffee + * PWM + * Built-in core temperature and battery sensor + +Requirements +============ +To start using Contiki with the OpenMote-CC2538, the following is required: + + * An OpenMote-CC2538 board. + * A toolchain to compile Contiki for the CC2538. + * Drivers so that your OS can communicate with your hardware. + * Software to upload images to the CC2538. + +Install a Toolchain +------------------- +The toolchain used to build contiki is arm-gcc, also used by other arm-based Contiki ports. If you are using Instant Contiki, you may have a version pre-installed in your system. + +The platform is currently being used/tested with "GNU Tools for ARM Embedded Processors" (). The current recommended version and the one being used by Contiki's regression tests on Travis is shown below. + + $ arm-none-eabi-gcc --version + arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 5.2.1 20151202 (release) [ARM/embedded-5-branch revision 231848] + Copyright (C) 2015 Free Software Foundation, Inc. + This is free software; see the source for copying conditions. There is NO + warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +Software to Program the Nodes +----------------------------- +The OpenMote-CC2538 can be programmed via the jtag interface or via the serial boot loader on the chip. + +The OpenMote-CC2538 has a mini JTAG 10-pin male header, compatible with the `SmartRF06` development board, which can be used to flash and debug the platforms. Alternatively one could use the `JLink` programmer with a 20-to-10 pin converter like the following: . + +The serial boot loader on the chip is exposed to the user via the USB interface. To activate the bootloader short the ON/SLEEP pin to GND and then press the reset button. + +Instructions to flash for different OS are given below. + +* On Windows: + * Nodes can be programmed with TI's ArmProgConsole or the SmartRF Flash Programmer 2. The README should be self-explanatory. With ArmProgConsole, upload the file with a `.bin` extension. + * Nodes can also be programmed via the serial boot loader in the cc2538. In `tools/cc2538-bsl/` you can find `cc2538-bsl.py` python script, which can download firmware to your node via a serial connection. If you use this option you just need to make sure you have a working version of python installed. You can read the README in the same directory for more info. + +* On Linux: + * Nodes can be programmed with TI's [UniFlash] tool. With UniFlash, use the file with `.elf` extension. + * Nodes can also be programmed via the serial boot loader in the cc2538. No extra software needs to be installed. + +* On OSX: + * The `cc2538-bsl.py` script in `tools/cc2538-bsl/` is the only option. No extra software needs to be installed. + +Use the Port +============ +The following examples are intended to work off-the-shelf: + +* Examples under `examples/openmote-cc2538` +* MQTT example `examples/cc2538dk/mqtt-demo` +* Border router: `examples/ipv6/rpl-border-router` +* Webserver: `examples/webserver-ipv6` +* CoAP example: `examples/er-rest-example` + +Build your First Examples +------------------------- +It is recommended to start with the `openmote-demo`, it is a simple example that demonstrates the OpenMote-CC2538 features, such as the built-in sensors, LEDs, user button and radio (using RIME broadcast). + +The `Makefile.target` includes the `TARGET=` argument, predefining which is the target platform to compile for, it is automatically included at compilation. + +To generate or override an existing one, you can run: + +`make TARGET=openmote-cc2538 savetarget` + +Then you can just run `make` to compile an application, otherwise you will need to do `make TARGET=openmote-cc2538`. + +If you want to upload the compiled firmware to a node via the serial boot loader you need first to either manually enable the boot loader. + +Then use `make openmote-demo.upload`. + +The `PORT` argument could be used to specify in which port the device is connected, in case we have multiple devices connected at the same time. + +To generate an assembly listing of the compiled firmware, run `make openmote-demo.lst`. This may be useful for debugging or optimizing your application code. To intersperse the C source code within the assembly listing, you must instruct the compiler to include debugging information by adding `CFLAGS += -g` to the project Makefile and rebuild by running `make clean openmote-demo.lst`. + +To enable printing debug output to your console, use the `make login` to get the information over the USB programming/debugging port, or alternatively use `make serialview` to also add a timestamp in each print. + +Node IEEE/RIME/IPv6 Addresses +----------------------------- + +Nodes will generally autoconfigure their IPv6 address based on their IEEE address. The IEEE address can be read directly from the CC2538 Info Page, or it can be hard-coded. Additionally, the user may specify a 2-byte value at build time, which will be used as the IEEE address' 2 LSBs. + +To configure the IEEE address source location (Info Page or hard-coded), use the `IEEE_ADDR_CONF_HARDCODED` define in contiki-conf.h: + +* 0: Info Page +* 1: Hard-coded + +If `IEEE_ADDR_CONF_HARDCODED` is defined as 1, the IEEE address will take its value from the `IEEE_ADDR_CONF_ADDRESS` define. If `IEEE_ADDR_CONF_HARDCODED` is defined as 0, the IEEE address can come from either the primary or secondary location in the Info Page. To use the secondary address, define `IEEE_ADDR_CONF_USE_SECONDARY_LOCATION` as 1. + +Additionally, you can override the IEEE's 2 LSBs, by using the `NODEID` make variable. The value of `NODEID` will become the value of the `IEEE_ADDR_NODE_ID` pre-processor define. If `NODEID` is not defined, `IEEE_ADDR_NODE_ID` will not get defined either. For example: + + make NODEID=0x79ab + +This will result in the 2 last bytes of the IEEE address getting set to 0x79 0xAB + +Note: Some early production devices do not have am IEEE address written on the Info Page. For those devices, using value 0 above will result in a Rime address of all 0xFFs. If your device is in this category, define `IEEE_ADDR_CONF_HARDCODED` to 1 and specify `NODEID` to differentiate between devices. + +Low-Power Modes +--------------- +The CC2538 port supports power modes for low energy consumption. The SoC will enter a low power mode as part of the main loop when there are no more events to service. + +LPM support can be disabled in its entirety by setting `LPM_CONF_ENABLE` to 0 in `contiki-conf.h` or `project-conf.h`. + +The Low-Power module uses a simple heuristic to determine the best power mode, depending on anticipated Deep Sleep duration and the state of various peripherals. + +In a nutshell, the algorithm first answers the following questions: + +* Is the RF off? +* Are all registered peripherals permitting PM1+? +* Is the Sleep Timer scheduled to fire an interrupt? + +If the answer to any of the above question is "No", the SoC will enter PM0. If the answer to all questions is "Yes", the SoC will enter one of PMs 0/1/2 depending on the expected Deep Sleep duration and subject to user configuration and application requirements. + +At runtime, the application may enable/disable some Power Modes by making calls to `lpm_set_max_pm()`. For example, to avoid PM2 an application could call `lpm_set_max_pm(1)`. Subsequently, to re-enable PM2 the application would call `lpm_set_max_pm(2)`. + +The LPM module can be configured with a hard maximum permitted power mode. + + #define LPM_CONF_MAX_PM N + +Where N corresponds to the PM number. Supported values are 0, 1, 2. PM3 is not supported. Thus, if the value of the define is 1, the SoC will only ever enter PMs 0 or 1 but never 2 and so on. + +The configuration directive `LPM_CONF_MAX_PM` sets a hard upper boundary. For instance, if `LPM_CONF_MAX_PM` is defined as 1, calls to `lpm_set_max_pm()` can only enable/disable PM1. In this scenario, PM2 can not be enabled at runtime. + +When setting `LPM_CONF_MAX_PM` to 0 or 1, the entire SRAM will be available. Crucially, when value 2 is used the linker will automatically stop using the SoC's SRAM non-retention area, resulting in a total available RAM of 16 kbytes instead of 32 kbytes. + +### LPM and Duty Cycling Driver +LPM is highly related to the operations of the Radio Duty Cycling (RDC) driver of the Contiki network stack and will work correctly with ContikiMAC and NullRDC. + +* With ContikiMAC, PMs 0/1/2 are supported subject to user configuration. +* When NullRDC is in use, the radio will be always on. As a result, the algorithm discussed above will always choose PM0 and will never attempt to drop to PM1/2. + +Build headless nodes +-------------------- +It is possible to turn off all character I/O for nodes not connected to a PC. Doing this will entirely disable the UART as well as the USB controller, preserving energy in the long term. The define used to achieve this is (1: Quiet, 0: Normal output): + + #define CC2538_CONF_QUIET 0 + +Setting this define to 1 will automatically set the following to 0: + +* `USB_SERIAL_CONF_ENABLE` +* `UART_CONF_ENABLE` +* `STARTUP_CONF_VERBOSE` + +Code Size Optimisations +----------------------- +The build system currently uses optimization level `-Os`, which is controlled indirectly through the value of the `SMALL` make variable. This value can be overridden by example makefiles, or it can be changed directly in `platform/openmote-cc2538/Makefile.openmote-cc2538`. + +Historically, the `-Os` flag has caused problems with some toolchains. If you are using one of the toolchains documented in this README, you should be able to use it without issues. If for whatever reason you do come across problems, try setting `SMALL=0` or replacing `-Os` with `-O2` in `cpu/cc2538/Makefile.cc2538`. + +Doxygen Documentation +===================== +This port's code has been documented with doxygen. To build the documentation, navigate to `$(CONTIKI)/doc` and run `make`. This will build the entire contiki documentation and may take a while. + +If you want to build this platform's documentation only and skip the remaining platforms, run this: + + make basedirs="platform/openmote-cc2538 core cpu/cc2538 examples/openmote-cc2538 examples/openmote-cc2538" + +Once you've built the docs, open `$(CONTIKI)/doc/html/index.html` and enjoy. + +Other Versions of this Guide +============================ +If you prefer this guide in other formats, use the excellent [pandoc] to convert it. + +* **pdf**: `pandoc -s --toc README.md -o README.pdf` +* **html**: `pandoc -s --toc README.md -o README.html` + +Maintainers +=========== +The OpenMote-CC2538 is maintained by OpenMote Technologies. +Main contributor: Pere Tuset diff --git a/platform/openmote-cc2538/board.c b/platform/openmote-cc2538/board.c new file mode 100644 index 000000000..c27812a9a --- /dev/null +++ b/platform/openmote-cc2538/board.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2014, 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. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-cc2538 + * @{ + * + * \file + * Board-initialisation for the OpenMote-CC2538 platform + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "dev/antenna.h" +#include +#include +/*---------------------------------------------------------------------------*/ +static void +configure_unused_pins(void) +{ + /* FIXME */ +} +/*---------------------------------------------------------------------------*/ +void +board_init() +{ + antenna_init(); + configure_unused_pins(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/platform/openmote-cc2538/board.h b/platform/openmote-cc2538/board.h new file mode 100644 index 000000000..9c9a62bc1 --- /dev/null +++ b/platform/openmote-cc2538/board.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2014, 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. + * + * This file is part of the Contiki operating system. + * + */ +/* -------------------------------------------------------------------------- */ +/** + * \addtogroup openmote-cc2538 + * @{ + * + * \file + * This file provides connectivity information on LEDs, Buttons, UART and + * other OpenMote-CC2538 peripherals. + * + * This file can be used as the basis to configure other platforms using the + * cc2538 SoC. + * + * \note Do not include this file directly. It gets included by contiki-conf + * after all relevant directives have been set. + */ + +#ifndef BOARD_H_ +#define BOARD_H_ +/*---------------------------------------------------------------------------*/ +#include "dev/gpio.h" +#include "dev/nvic.h" +/*---------------------------------------------------------------------------*/ +/** \name OpenMote-CC2538 LED configuration + * + * LEDs on the OpenMote-CC2538 are connected as follows: + * - LED1 (Red) -> PC4 + * - LED2 (Yellow) -> PC6 + * - LED3 (Green) -> PC7 + * - LED4 (Orange) -> PC5 + * + * @{ + */ +/*---------------------------------------------------------------------------*/ +/* Some files include leds.h before us, so we need to get rid of defaults in + * leds.h before we provide correct definitions */ +#undef LEDS_GREEN +#undef LEDS_YELLOW +#undef LEDS_RED +#undef LEDS_CONF_ALL + +#define LEDS_RED 16 /**< LED1 (Red) -> PC4 */ +#define LEDS_YELLOW 64 /**< LED2 (Yellow) -> PC6 */ +#define LEDS_GREEN 128 /**< LED3 (Green) -> PC7 */ +#define LEDS_ORANGE 32 /**< LED4 (Orange) -> PC5 */ +#define LEDS_CONF_ALL 240 + +/* Notify various examples that we have LEDs */ +#define PLATFORM_HAS_LEDS 1 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name USB configuration + * + * The USB pullup is driven by PC0 + */ +#define USB_PULLUP_PORT GPIO_C_NUM +#define USB_PULLUP_PIN 0 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name UART configuration + * + * On the OpenMote, the UART is connected to the + * following ports/pins + * - RX: PA0 + * - TX: PA1 + * - CTS: PB0 (Can only be used with UART1) + * - RTS: PD3 (Can only be used with UART1) + * + * We configure the port to use UART0. To use UART1, replace UART0_* with + * UART1_* below. + * @{ + */ +#define UART0_RX_PORT GPIO_A_NUM +#define UART0_RX_PIN 0 +#define UART0_TX_PORT GPIO_A_NUM +#define UART0_TX_PIN 1 + +#define UART1_RX_PORT GPIO_B_NUM +#define UART1_RX_PIN 0 +#define UART1_TX_PORT GPIO_D_NUM +#define UART1_TX_PIN 3 +#define UART1_CTS_PORT (-1) +#define UART1_CTS_PIN (-1) +#define UART1_RTS_PORT (-1) +#define UART1_RTS_PIN (-1) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name OpenMote-CC2538 Button configuration + * + * Buttons on the OpenMote-CC2538 are connected as follows: + * - BUTTON_USER -> PC3 + * @{ + */ +/** BUTTON_USER -> PC3 */ +#define BUTTON_USER_PORT GPIO_C_NUM +#define BUTTON_USER_PIN 3 +#define BUTTON_USER_VECTOR NVIC_INT_GPIO_PORT_C +/* Notify various examples that we have Buttons */ +#define PLATFORM_HAS_BUTTON 1 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name SPI (SSI0) configuration + * + * These values configure which CC2538 pins to use for the SPI (SSI0) lines. + * The SSI0 is currently used to interface with the Ethernet driver (ENC28J60) + * on the OpenBase board. + * @{ + */ +#define SPI_CLK_PORT GPIO_A_NUM +#define SPI_CLK_PIN 2 +#define SPI_MOSI_PORT GPIO_A_NUM +#define SPI_MOSI_PIN 5 +#define SPI_MISO_PORT GPIO_A_NUM +#define SPI_MISO_PIN 4 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name SPI (SSI1) configuration + * + * These values configure which CC2538 pins to use for the SPI (SSI1) lines. + * The SSI1 is currently not used. + * @{ + */ +#define SPI1_CLK_PORT GPIO_C_NUM +#define SPI1_CLK_PIN 4 +#define SPI1_TX_PORT GPIO_C_NUM +#define SPI1_TX_PIN 5 +#define SPI1_RX_PORT GPIO_C_NUM +#define SPI1_RX_PIN 6 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name I2C configuration + * + * These values configure which CC2538 pins to use for the I2C lines. + * @{ + */ +#define I2C_SCL_PORT GPIO_B_NUM +#define I2C_SCL_PIN 3 +#define I2C_SDA_PORT GPIO_B_NUM +#define I2C_SDA_PIN 4 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Device string used on startup + * @{ + */ +#define BOARD_STRING "OpenMote-CC2538" +/** @} */ +/*---------------------------------------------------------------------------*/ +#endif /* BOARD_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + */ diff --git a/platform/openmote-cc2538/contiki-conf.h b/platform/openmote-cc2538/contiki-conf.h new file mode 100644 index 000000000..87b58f299 --- /dev/null +++ b/platform/openmote-cc2538/contiki-conf.h @@ -0,0 +1,579 @@ +/* + * Copyright (c) 2014, OpenMote Technologies, S.L. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-cc2538 + * @{ + * + * \defgroup openmote-cc2538-platforms OpenMote-CC2538 platform + * + * The OpenMote-CC2538 platform was designed at UC Berkeley in 2013 and + * is comercialized by OpenMote Technologies since 2014. It is the first + * commercial platform based on the powerful TI CC2538 SoC. It uses a + * XBee form-factor to ease prototyping. + * + * \file + * Configuration for the OpenMote-CC2538 platform + */ +#ifndef CONTIKI_CONF_H_ +#define CONTIKI_CONF_H_ + +#include +#include +/*---------------------------------------------------------------------------*/ +/* Include Project Specific conf */ +#ifdef PROJECT_CONF_H +#include PROJECT_CONF_H +#endif /* PROJECT_CONF_H */ +/*---------------------------------------------------------------------------*/ +/** + * \name Compiler configuration and platform-specific type definitions + * + * Those values are not meant to be modified by the user + * @{ + */ +#define CLOCK_CONF_SECOND 128 + +/* Compiler configurations */ +#define CCIF +#define CLIF + +/* Platform typedefs */ +typedef uint32_t clock_time_t; +typedef uint32_t uip_stats_t; + +/* + * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define + * RTIMER_CLOCK_DIFF to override this + */ +typedef uint32_t rtimer_clock_t; +#define RTIMER_CLOCK_DIFF(a, b) ((int32_t)((a) - (b))) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Serial Boot Loader Backdoor configuration + * + * @{ + */ +#ifndef FLASH_CCA_CONF_BOOTLDR_BACKDOOR +#define FLASH_CCA_CONF_BOOTLDR_BACKDOOR 1 /** RAM DMA channel */ +#define USB_ARCH_CONF_TX_DMA_CHAN 1 /**< RAM -> USB DMA channel */ +#define CC2538_RF_CONF_TX_DMA_CHAN 2 /**< RF -> RAM DMA channel */ +#define CC2538_RF_CONF_RX_DMA_CHAN 3 /**< RAM -> RF DMA channel */ +#define UDMA_CONF_MAX_CHANNEL CC2538_RF_CONF_RX_DMA_CHAN +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Character I/O Configuration + * + * @{ + */ +#ifndef UART_CONF_ENABLE +#define UART_CONF_ENABLE 1 /**< Enable/Disable UART I/O */ +#endif + +#ifndef UART0_CONF_BAUD_RATE +#define UART0_CONF_BAUD_RATE 115200 /**< Default UART0 baud rate */ +#endif + +#ifndef UART1_CONF_BAUD_RATE +#define UART1_CONF_BAUD_RATE 115200 /**< Default UART1 baud rate */ +#endif + +#ifndef SLIP_ARCH_CONF_USB +#define SLIP_ARCH_CONF_USB 0 /**< SLIP over UART by default */ +#endif + +#ifndef CC2538_RF_CONF_SNIFFER_USB +#define CC2538_RF_CONF_SNIFFER_USB 0 /**< Sniffer out over UART by default */ +#endif + +#ifndef DBG_CONF_USB +#define DBG_CONF_USB 0 /**< All debugging over UART by default */ +#endif + +#ifndef SERIAL_LINE_CONF_UART +#define SERIAL_LINE_CONF_UART 0 /**< UART to use with serial line */ +#endif + +#if !SLIP_ARCH_CONF_USB +#ifndef SLIP_ARCH_CONF_UART +#define SLIP_ARCH_CONF_UART 0 /**< UART to use with SLIP */ +#endif +#endif + +#if !CC2538_RF_CONF_SNIFFER_USB +#ifndef CC2538_RF_CONF_SNIFFER_UART +#define CC2538_RF_CONF_SNIFFER_UART 0 /**< UART to use with sniffer */ +#endif +#endif + +#if !DBG_CONF_USB +#ifndef DBG_CONF_UART +#define DBG_CONF_UART 0 /**< UART to use for debugging */ +#endif +#endif + +#ifndef UART1_CONF_UART +#define UART1_CONF_UART 0 /**< UART to use for examples relying on + the uart1_* API */ +#endif + +/* Turn off example-provided putchars */ +#define SLIP_BRIDGE_CONF_NO_PUTCHAR 1 +#define SLIP_RADIO_CONF_NO_PUTCHAR 1 + +#ifndef SLIP_ARCH_CONF_ENABLED +/* + * Determine whether we need SLIP + * This will keep working while UIP_FALLBACK_INTERFACE and CMD_CONF_OUTPUT + * keep using SLIP + */ +#if defined(UIP_FALLBACK_INTERFACE) || defined(CMD_CONF_OUTPUT) +#define SLIP_ARCH_CONF_ENABLED 1 +#endif +#endif + +/* + * When set, the radio turns off address filtering and sends all captured + * frames down a peripheral (UART or USB, depending on the value of + * CC2538_RF_CONF_SNIFFER_USB) + */ +#ifndef CC2538_RF_CONF_SNIFFER +#define CC2538_RF_CONF_SNIFFER 0 +#endif + +/** + * \brief Define this as 1 to build a headless node. + * + * The UART will not be initialised its clock will be gated, offering some + * energy savings. The USB will not be initialised either + */ +#ifndef CC2538_CONF_QUIET +#define CC2538_CONF_QUIET 0 +#endif + +/* CC2538_CONF_QUIET is hard and overrides all other related defines */ +#if CC2538_CONF_QUIET +#undef USB_SERIAL_CONF_ENABLE +#define USB_SERIAL_CONF_ENABLE 0 + +#undef UART_CONF_ENABLE +#define UART_CONF_ENABLE 0 + +#undef STARTUP_CONF_VERBOSE +#define STARTUP_CONF_VERBOSE 0 + +/* Little sanity check: We can't have quiet sniffers */ +#if CC2538_RF_CONF_SNIFFER +#error "CC2538_RF_CONF_SNIFFER == 1 and CC2538_CONF_QUIET == 1" +#error "These values are conflicting. Please set either to 0" +#endif +#endif /* CC2538_CONF_QUIET */ + +/** + * \brief Enable the USB core only if we need it + */ +#ifndef USB_SERIAL_CONF_ENABLE +#define USB_SERIAL_CONF_ENABLE \ + ((SLIP_ARCH_CONF_USB & SLIP_ARCH_CONF_ENABLED) | \ + DBG_CONF_USB | \ + (CC2538_RF_CONF_SNIFFER & CC2538_RF_CONF_SNIFFER_USB)) +#endif + +/* + * If debugging and SLIP use the same peripheral, this will be 1. Don't modify + * this + */ +#if SLIP_ARCH_CONF_ENABLED +#define DBG_CONF_SLIP_MUX (SLIP_ARCH_CONF_USB == DBG_CONF_USB && \ + (SLIP_ARCH_CONF_USB || \ + SLIP_ARCH_CONF_UART == DBG_CONF_UART)) +#endif + +/* + * Automatic detection of whether a specific UART is in use + */ +#define UART_IN_USE_BY_SERIAL_LINE(u) (SERIAL_LINE_CONF_UART == (u)) +#define UART_IN_USE_BY_SLIP(u) (SLIP_ARCH_CONF_ENABLED && \ + !SLIP_ARCH_CONF_USB && \ + SLIP_ARCH_CONF_UART == (u)) +#define UART_IN_USE_BY_RF_SNIFFER(u) (CC2538_RF_CONF_SNIFFER && \ + !CC2538_RF_CONF_SNIFFER_USB && \ + CC2538_RF_CONF_SNIFFER_UART == (u)) +#define UART_IN_USE_BY_DBG(u) (!DBG_CONF_USB && DBG_CONF_UART == (u)) +#define UART_IN_USE_BY_UART1(u) (UART1_CONF_UART == (u)) + +#define UART_IN_USE(u) ( \ + UART_CONF_ENABLE && \ + (UART_IN_USE_BY_SERIAL_LINE(u) || \ + UART_IN_USE_BY_SLIP(u) || \ + UART_IN_USE_BY_RF_SNIFFER(u) || \ + UART_IN_USE_BY_DBG(u) || \ + UART_IN_USE_BY_UART1(u)) \ + ) +/** @} */ +/*---------------------------------------------------------------------------*/ +/* board.h assumes that basic configuration is done */ +#include "board.h" +/*---------------------------------------------------------------------------*/ +/** + * \name Network Stack Configuration + * + * @{ + */ +#ifndef NETSTACK_CONF_NETWORK +#if NETSTACK_CONF_WITH_IPV6 +#define NETSTACK_CONF_NETWORK sicslowpan_driver +#else +#define NETSTACK_CONF_NETWORK rime_driver +#endif /* NETSTACK_CONF_WITH_IPV6 */ +#endif /* NETSTACK_CONF_NETWORK */ + +#ifndef NETSTACK_CONF_MAC +#define NETSTACK_CONF_MAC csma_driver +#endif + +#ifndef NETSTACK_CONF_RDC +#define NETSTACK_CONF_RDC contikimac_driver +#endif + +/* Configure NullRDC for when it's selected */ +#define NULLRDC_802154_AUTOACK 1 +#define NULLRDC_802154_AUTOACK_HW 1 + +/* Configure ContikiMAC for when it's selected */ +#define CONTIKIMAC_CONF_WITH_PHASE_OPTIMIZATION 0 +#define WITH_FAST_SLEEP 1 + +#ifndef NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE +#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8 +#endif + +#ifndef NETSTACK_CONF_FRAMER +#if NETSTACK_CONF_WITH_IPV6 +#define NETSTACK_CONF_FRAMER framer_802154 +#else /* NETSTACK_CONF_WITH_IPV6 */ +#define NETSTACK_CONF_FRAMER contikimac_framer +#endif /* NETSTACK_CONF_WITH_IPV6 */ +#endif /* NETSTACK_CONF_FRAMER */ + +#ifndef NETSTACK_CONF_RADIO +#define NETSTACK_CONF_RADIO cc2538_rf_driver +#endif + +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name LPM configuration + * @{ + */ +#ifndef LPM_CONF_ENABLE +#define LPM_CONF_ENABLE 1 /**< Set to 0 to disable LPM entirely */ +#endif + +/** + * \brief Maximum PM + * + * The SoC will never drop to a Power Mode deeper than the one specified here. + * 0 for PM0, 1 for PM1 and 2 for PM2 + */ +#ifndef LPM_CONF_MAX_PM +#define LPM_CONF_MAX_PM 1 +#endif + +#ifndef LPM_CONF_STATS +#define LPM_CONF_STATS 0 /**< Set to 1 to enable LPM-related stats */ +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name IEEE address configuration + * + * Used to generate our RIME & IPv6 address + * @{ + */ +/** + * \brief Location of the IEEE address + * 0 => Read from InfoPage, + * 1 => Use a hardcoded address, configured by IEEE_ADDR_CONF_ADDRESS + */ +#ifndef IEEE_ADDR_CONF_HARDCODED +#define IEEE_ADDR_CONF_HARDCODED 0 +#endif + +/** + * \brief The hardcoded IEEE address to be used when IEEE_ADDR_CONF_HARDCODED + * is defined as 1 + */ +#ifndef IEEE_ADDR_CONF_ADDRESS +#define IEEE_ADDR_CONF_ADDRESS { 0x00, 0x12, 0x4B, 0x00, 0x89, 0xAB, 0xCD, 0xEF } +#endif + +/** + * \brief Location of the IEEE address in the InfoPage when + * IEEE_ADDR_CONF_HARDCODED is defined as 0 + * 0 => Use the primary address location + * 1 => Use the secondary address location + */ +#ifndef IEEE_ADDR_CONF_USE_SECONDARY_LOCATION +#define IEEE_ADDR_CONF_USE_SECONDARY_LOCATION 0 +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name RF configuration + * + * @{ + */ +/* RF Config */ +#ifndef IEEE802154_CONF_PANID +#define IEEE802154_CONF_PANID 0xABCD +#endif + +#ifndef CC2538_RF_CONF_CHANNEL +#define CC2538_RF_CONF_CHANNEL 26 +#endif /* CC2538_RF_CONF_CHANNEL */ + +#ifndef CC2538_RF_CONF_AUTOACK +#define CC2538_RF_CONF_AUTOACK 1 /**< RF H/W generates ACKs */ +#endif /* CC2538_CONF_AUTOACK */ + +#ifndef CC2538_RF_CONF_TX_USE_DMA +#define CC2538_RF_CONF_TX_USE_DMA 1 /**< RF TX over DMA */ +#endif + +#ifndef CC2538_RF_CONF_RX_USE_DMA +#define CC2538_RF_CONF_RX_USE_DMA 1 /**< RF RX over DMA */ +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name IPv6, RIME and network buffer configuration + * + * @{ + */ + +/* Don't let contiki-default-conf.h decide if we are an IPv6 build */ +#ifndef NETSTACK_CONF_WITH_IPV6 +#define NETSTACK_CONF_WITH_IPV6 0 +#endif + +#if NETSTACK_CONF_WITH_IPV6 +/* Addresses, Sizes and Interfaces */ +/* 8-byte addresses here, 2 otherwise */ +#define LINKADDR_CONF_SIZE 8 +#define UIP_CONF_LL_802154 1 +#define UIP_CONF_LLH_LEN 0 +#define UIP_CONF_NETIF_MAX_ADDRESSES 3 + +/* TCP, UDP, ICMP */ +#ifndef UIP_CONF_TCP +#define UIP_CONF_TCP 1 +#endif +#ifndef UIP_CONF_TCP_MSS +#define UIP_CONF_TCP_MSS 64 +#endif +#define UIP_CONF_UDP 1 +#define UIP_CONF_UDP_CHECKSUMS 1 +#define UIP_CONF_ICMP6 1 + +/* ND and Routing */ +#ifndef UIP_CONF_ROUTER +#define UIP_CONF_ROUTER 1 +#endif + +#define UIP_CONF_ND6_SEND_RA 0 +#define UIP_CONF_IP_FORWARD 0 +#define RPL_CONF_STATS 0 + +#ifndef RPL_CONF_OF +#define RPL_CONF_OF rpl_mrhof +#endif + +#define UIP_CONF_ND6_REACHABLE_TIME 600000 +#define UIP_CONF_ND6_RETRANS_TIMER 10000 + +#ifndef NBR_TABLE_CONF_MAX_NEIGHBORS +#define NBR_TABLE_CONF_MAX_NEIGHBORS 20 +#endif +#ifndef UIP_CONF_MAX_ROUTES +#define UIP_CONF_MAX_ROUTES 20 +#endif + +/* uIP */ +#ifndef UIP_CONF_BUFFER_SIZE +#define UIP_CONF_BUFFER_SIZE 1300 +#endif + +#define UIP_CONF_IPV6_QUEUE_PKT 0 +#define UIP_CONF_IPV6_CHECKS 1 +#define UIP_CONF_IPV6_REASSEMBLY 0 +#define UIP_CONF_MAX_LISTENPORTS 8 + +/* 6lowpan */ +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 +#ifndef SICSLOWPAN_CONF_COMPRESSION_THRESHOLD +#define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 63 +#endif +#ifndef SICSLOWPAN_CONF_FRAG +#define SICSLOWPAN_CONF_FRAG 1 +#endif +#define SICSLOWPAN_CONF_MAXAGE 8 + +/* Define our IPv6 prefixes/contexts here */ +#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 1 +#ifndef SICSLOWPAN_CONF_ADDR_CONTEXT_0 +#define SICSLOWPAN_CONF_ADDR_CONTEXT_0 { \ + addr_contexts[0].prefix[0] = UIP_DS6_DEFAULT_PREFIX_0; \ + addr_contexts[0].prefix[1] = UIP_DS6_DEFAULT_PREFIX_1; \ +} +#endif + +#define MAC_CONF_CHANNEL_CHECK_RATE 8 + +#ifndef QUEUEBUF_CONF_NUM +#define QUEUEBUF_CONF_NUM 8 +#endif +/*---------------------------------------------------------------------------*/ +#else /* NETSTACK_CONF_WITH_IPV6 */ +/* Network setup for non-IPv6 (rime). */ +#define UIP_CONF_IP_FORWARD 1 + +#ifndef UIP_CONF_BUFFER_SIZE +#define UIP_CONF_BUFFER_SIZE 108 +#endif + +#define RIME_CONF_NO_POLITE_ANNOUCEMENTS 0 + +#ifndef QUEUEBUF_CONF_NUM +#define QUEUEBUF_CONF_NUM 8 +#endif + +#endif /* NETSTACK_CONF_WITH_IPV6 */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Security + * + * @{ + */ +#ifndef CRYPTO_CONF_INIT +#define CRYPTO_CONF_INIT 1 /**< Whether to init cryptoprocessor */ +#endif + +#ifndef AES_128_CONF +#define AES_128_CONF cc2538_aes_128_driver /**< AES-128 driver */ +#endif + +#ifndef CCM_STAR_CONF +#define CCM_STAR_CONF cc2538_ccm_star_driver /**< AES-CCM* driver */ +#endif + +/*---------------------------------------------------------------------------*/ +#endif /* CONTIKI_CONF_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/openmote-cc2538/contiki-main.c b/platform/openmote-cc2538/contiki-main.c new file mode 100644 index 000000000..580f84f56 --- /dev/null +++ b/platform/openmote-cc2538/contiki-main.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2014, 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. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup platform + * @{ + * + * \defgroup openmote-cc2538 OpenMote-CC2538 platform + * + * The OpenMote-CC2538 is based on the CC2538, the new platform by Texas Instruments + * based on an ARM Cortex-M3 core and a IEEE 802.15.4 radio. + * @{ + * + * \file + * Main module for the OpenMote-CC2538 platform + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/leds.h" +#include "dev/sys-ctrl.h" +#include "dev/scb.h" +#include "dev/nvic.h" +#include "dev/uart.h" +#include "dev/i2c.h" +#include "dev/watchdog.h" +#include "dev/ioc.h" +#include "dev/button-sensor.h" +#include "dev/serial-line.h" +#include "dev/slip.h" +#include "dev/cc2538-rf.h" +#include "dev/udma.h" +#include "dev/crypto.h" +#include "usb/usb-serial.h" +#include "lib/random.h" +#include "net/netstack.h" +#include "net/queuebuf.h" +#include "net/ip/tcpip.h" +#include "net/ip/uip.h" +#include "net/mac/frame802154.h" +#include "soc.h" +#include "cpu.h" +#include "reg.h" +#include "ieee-addr.h" +#include "lpm.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#if STARTUP_CONF_VERBOSE +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#if UART_CONF_ENABLE +#define PUTS(s) puts(s) +#else +#define PUTS(s) +#endif +/*---------------------------------------------------------------------------*/ +/** + * \brief Board specific iniatialisation + */ +void board_init(void); +/*---------------------------------------------------------------------------*/ +static void +fade(unsigned char l) +{ + volatile int i; + int k, j; + for(k = 0; k < 800; ++k) { + j = k > 400 ? 800 - k : k; + + leds_on(l); + for(i = 0; i < j; ++i) { + asm("nop"); + } + leds_off(l); + for(i = 0; i < 400 - j; ++i) { + asm("nop"); + } + } +} +/*---------------------------------------------------------------------------*/ +static void +set_rf_params(void) +{ + uint16_t short_addr; + uint8_t ext_addr[8]; + + ieee_addr_cpy_to(ext_addr, 8); + + short_addr = ext_addr[7]; + short_addr |= ext_addr[6] << 8; + + /* Populate linkaddr_node_addr. Maintain endianness */ + memcpy(&linkaddr_node_addr, &ext_addr[8 - LINKADDR_SIZE], LINKADDR_SIZE); + +#if STARTUP_CONF_VERBOSE + { + int i; + printf("Rime configured with address "); + for(i = 0; i < LINKADDR_SIZE - 1; i++) { + printf("%02x:", linkaddr_node_addr.u8[i]); + } + printf("%02x\n", linkaddr_node_addr.u8[i]); + } +#endif + + NETSTACK_RADIO.set_value(RADIO_PARAM_PAN_ID, IEEE802154_PANID); + NETSTACK_RADIO.set_value(RADIO_PARAM_16BIT_ADDR, short_addr); + NETSTACK_RADIO.set_value(RADIO_PARAM_CHANNEL, CC2538_RF_CHANNEL); + NETSTACK_RADIO.set_object(RADIO_PARAM_64BIT_ADDR, ext_addr, 8); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Main routine for the OpenMote-CC2538 platforms + */ +int +main(void) +{ + nvic_init(); + ioc_init(); + sys_ctrl_init(); + clock_init(); + lpm_init(); + rtimer_init(); + gpio_init(); + leds_init(); + fade(LEDS_RED); + process_init(); + watchdog_init(); + +#if UART_CONF_ENABLE + uart_init(0); + uart_init(1); + uart_set_input(SERIAL_LINE_CONF_UART, serial_line_input_byte); +#endif + +#if USB_SERIAL_CONF_ENABLE + usb_serial_init(); + usb_serial_set_input(serial_line_input_byte); +#endif + + i2c_init(I2C_SDA_PORT, I2C_SDA_PIN, I2C_SCL_PORT, I2C_SCL_PIN, I2C_SCL_NORMAL_BUS_SPEED); + + serial_line_init(); + + INTERRUPTS_ENABLE(); + fade(LEDS_BLUE); + + PUTS(CONTIKI_VERSION_STRING); + PUTS(BOARD_STRING); +#if STARTUP_CONF_VERBOSE + soc_print_info(); +#endif + + random_init(0); + + udma_init(); + + process_start(&etimer_process, NULL); + ctimer_init(); + + board_init(); + +#if CRYPTO_CONF_INIT + crypto_init(); + crypto_disable(); +#endif + + netstack_init(); + set_rf_params(); + + PRINTF("Net: "); + PRINTF("%s\n", NETSTACK_NETWORK.name); + PRINTF("MAC: "); + PRINTF("%s\n", NETSTACK_MAC.name); + PRINTF("RDC: "); + PRINTF("%s\n", NETSTACK_RDC.name); + +#if NETSTACK_CONF_WITH_IPV6 + memcpy(&uip_lladdr.addr, &linkaddr_node_addr, sizeof(uip_lladdr.addr)); + queuebuf_init(); + process_start(&tcpip_process, NULL); +#endif /* NETSTACK_CONF_WITH_IPV6 */ + + process_start(&sensors_process, NULL); + + SENSORS_ACTIVATE(button_sensor); + + energest_init(); + ENERGEST_ON(ENERGEST_TYPE_CPU); + + autostart_start(autostart_processes); + + watchdog_start(); + fade(LEDS_GREEN); + + while(1) { + uint8_t r; + do { + watchdog_periodic(); + + r = process_run(); + } while(r > 0); + + lpm_enter(); + } +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/openmote-cc2538/dev/adxl346.c b/platform/openmote-cc2538/dev/adxl346.c new file mode 100644 index 000000000..400e3fdf6 --- /dev/null +++ b/platform/openmote-cc2538/dev/adxl346.c @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2014, OpenMote Technologies, S.L. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-adxl346-sensor + * @{ + * + * \file + * Driver for the ADXL346 acceleration sensor + * + * \author + * Pere Tuset + */ +/*---------------------------------------------------------------------------*/ +#include "dev/i2c.h" +#include "dev/adxl346.h" +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +/** + * \name ADXL346 address and device identifier + * @{ + */ +#define ADXL346_ADDRESS (0x53) +#define ADXL346_DEVID_VALUE (0xE6) +/** @} */ +/* -------------------------------------------------------------------------- */ +/** + * \name ADXL346 register addresses + * @{ + */ +#define ADXL346_DEVID_ADDR (0x00) +#define ADXL346_THRES_TAP_ADDR (0x1D) +#define ADXL346_OFSX_ADDR (0x1E) +#define ADXL346_OFSY_ADDR (0x1F) +#define ADXL346_OFSZ_ADDR (0x20) +#define ADXL346_DUR_ADDR (0x21) +#define ADXL346_LATENT_ADDR (0x22) +#define ADXL346_WINDOW_ADDR (0x23) +#define ADXL346_THRESH_ACT_ADDR (0x24) +#define ADXL346_THRESH_INACT_ADDR (0x25) +#define ADXL346_TIME_INACT_ADDR (0x26) +#define ADXL346_ACT_INACT_CTL_ADDR (0x27) +#define ADXL346_THRESH_FF_ADDR (0x28) +#define ADXL346_TIME_FF_ADDR (0x29) +#define ADXL346_TAP_AXES_ADDR (0x2A) +#define ADXL346_ACT_TAP_STATUS_ADDR (0x2B) +#define ADXL346_BW_RATE_ADDR (0x2C) +#define ADXL346_POWER_CTL_ADDR (0x2D) +#define ADXL346_INT_ENABLE_ADDR (0x2E) +#define ADXL346_INT_MAP_ADDR (0x2F) +#define ADXL346_INT_SOURCE_ADDR (0x30) +#define ADXL346_DATA_FORMAT_ADDR (0x31) +#define ADXL346_DATAX0_ADDR (0x32) +#define ADXL346_DATAX1_ADDR (0x33) +#define ADXL346_DATAY0_ADDR (0x34) +#define ADXL346_DATAY1_ADDR (0x35) +#define ADXL346_DATAZ0_ADDR (0x36) +#define ADXL346_DATAZ1_ADDR (0x37) +#define ADXL346_FIFO_CTL_ADDR (0x38) +#define ADXL346_FIFO_STATUS_ADDR (0x39) +#define ADXL346_TAP_SIGN_ADDR (0x3A) +#define ADXL346_ORIENT_CONF_ADDR (0x3B) +#define ADXL346_ORIENT_ADDR (0x3C) +/** @} */ +/* -------------------------------------------------------------------------- */ +/** + * \name ADXL346 register values + * @{ + */ +#define ADXL346_INT_ENABLE_DATA_READY (1 << 7) +#define ADXL346_INT_ENABLE_SINGLE_TAP (1 << 6) +#define ADXL346_INT_ENABLE_DOUBLE_TAP (1 << 5) +#define ADXL346_INT_ENABLE_ACTIVITY (1 << 4) +#define ADXL346_INT_ENABLE_INACTIVITY (1 << 3) +#define ADXL346_INT_ENABLE_FREE_FALL (1 << 2) +#define ADXL346_INT_ENABLE_WATERMARK (1 << 1) +#define ADXL346_INT_ENABLE_OVERRUN (1 << 0) + +#define ADXL346_ACT_INACT_CTL_ACT_ACDC (1 << 7) +#define ADXL346_ACT_INACT_CTL_ACT_X_EN (1 << 6) +#define ADXL346_ACT_INACT_CTL_ACT_Y_EN (1 << 5) +#define ADXL346_ACT_INACT_CTL_ACT_Z_EN (1 << 4) +#define ADXL346_ACT_INACT_CTL_INACT_ACDC (1 << 3) +#define ADXL346_ACT_INACT_CTL_INACT_X_EN (1 << 2) +#define ADXL346_ACT_INACT_CTL_INACT_Y_EN (1 << 1) +#define ADXL346_ACT_INACT_CTL_INACT_Z_EN (1 << 0) + +#define ADXL346_TAP_AXES_SUPPRESS (1 << 3) +#define ADXL346_TAP_AXES_TAP_X_EN (1 << 2) +#define ADXL346_TAP_AXES_TAP_Y_EN (1 << 1) +#define ADXL346_TAP_AXES_TAP_Z_EN (1 << 0) + +#define ADXL346_ACT_TAP_STATUS_ACT_X_SRC (1 << 6) +#define ADXL346_ACT_TAP_STATUS_ACT_Y_SRC (1 << 5) +#define ADXL346_ACT_TAP_STATUS_ACT_Z_SRC (1 << 4) +#define ADXL346_ACT_TAP_STATUS_ASLEEP (1 << 3) +#define ADXL346_ACT_TAP_STATUS_TAP_X_SRC (1 << 2) +#define ADXL346_ACT_TAP_STATUS_TAP_Y_SRC (1 << 1) +#define ADXL346_ACT_TAP_STATUS_TAP_Z_SRC (1 << 0) + +#define ADXL346_BW_RATE_POWER (1 << 4) +#define ADXL346_BW_RATE_RATE(x) ((x) & 0x0F) + +#define ADXL346_POWER_CTL_LINK (1 << 5) +#define ADXL346_POWER_CTL_AUTO_SLEEP (1 << 4) +#define ADXL346_POWER_CTL_MEASURE (1 << 3) +#define ADXL346_POWER_CTL_SLEEP (1 << 2) +#define ADXL346_POWER_CTL_WAKEUP(x) ((x) & 0x03) + +#define ADXL346_DATA_FORMAT_SELF_TEST (1 << 7) +#define ADXL346_DATA_FORMAT_SPI (1 << 6) +#define ADXL346_DATA_FORMAT_INT_INVERT (1 << 5) +#define ADXL346_DATA_FORMAT_FULL_RES (1 << 3) +#define ADXL346_DATA_FORMAT_JUSTIFY (1 << 2) +#define ADXL346_DATA_FORMAT_RANGE(x) ((x) & 0x03) +#define ADXL346_DATA_FORMAT_RANGE_PM_2g (0) +#define ADXL346_DATA_FORMAT_RANGE_PM_4g (1) +#define ADXL346_DATA_FORMAT_RANGE_PM_8g (2) +#define ADXL346_DATA_FORMAT_RANGE_PM_16g (3) + +#define ADXL346_USER_CONFIGURATION (ADXL346_DATA_FORMAT_RANGE_PM_2g) + +/** @} */ +/*---------------------------------------------------------------------------*/ +static uint8_t enabled; +/*---------------------------------------------------------------------------*/ +static void +adxl346_init(void) +{ + uint8_t config[2]; + + config[0] = ADXL346_BW_RATE_ADDR; + config[1] = (ADXL346_BW_RATE_RATE(6)); + i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); + + config[0] = ADXL346_DATA_FORMAT_ADDR; + config[1] = (ADXL346_USER_CONFIGURATION); + i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); + + config[0] = ADXL346_POWER_CTL_ADDR; + config[1] = (ADXL346_POWER_CTL_MEASURE); + i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); +} +/*---------------------------------------------------------------------------*/ +static uint8_t +adxl346_is_present(void) +{ + uint8_t is_present; + + i2c_single_send(ADXL346_ADDRESS, ADXL346_DEVID_ADDR); + i2c_single_receive(ADXL346_ADDRESS, &is_present); + + return is_present == ADXL346_DEVID_VALUE; +} +/*---------------------------------------------------------------------------*/ +static int16_t +adxl346_read_accel(uint8_t addr1, uint8_t addr2) +{ + uint8_t acceleration[2]; + int16_t result; + + i2c_single_send(ADXL346_ADDRESS, addr1); + i2c_single_receive(ADXL346_ADDRESS, &acceleration[0]); + i2c_single_send(ADXL346_ADDRESS, addr2); + i2c_single_receive(ADXL346_ADDRESS, &acceleration[1]); + + result = (acceleration[1] << 8) | acceleration[0]; + + return result; +} +/*---------------------------------------------------------------------------*/ +static int16_t +adxl346_convert_accel(int16_t accel) +{ + int32_t result; + + result = (1000 * accel) / 256; + + return (int16_t)result; +} +/*---------------------------------------------------------------------------*/ +static void +adxl346_calibrate_offset(void) +{ + int32_t accum_x = 0; + int32_t accum_y = 0; + int32_t accum_z = 0; + uint8_t config[2]; + int8_t offset; + + config[0] = ADXL346_OFSX_ADDR; + config[1] = 0; + i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); + config[0] = ADXL346_OFSY_ADDR; + config[1] = 0; + i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); + config[0] = ADXL346_OFSZ_ADDR; + config[1] = 0; + i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); + + uint16_t i; + for(i = 0; i < 100; i++) { + uint16_t x, y, z; + + x = adxl346_read_accel(ADXL346_DATAX0_ADDR, ADXL346_DATAX1_ADDR); + accum_x += x; + + y = adxl346_read_accel(ADXL346_DATAY0_ADDR, ADXL346_DATAY1_ADDR); + accum_y += y; + + z = adxl346_read_accel(ADXL346_DATAZ0_ADDR, ADXL346_DATAZ1_ADDR); + accum_z += z; + } + + offset = (64 * accum_x) / 25600; + config[0] = ADXL346_OFSX_ADDR; + config[1] = -offset; + i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); + PRINTF("ADXL346: X calibration offset is %d\n", offset); + + offset = (64 * accum_y) / 25600; + config[0] = ADXL346_OFSY_ADDR; + config[1] = -offset; + i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); + PRINTF("ADXL346: Y calibration offset is %d\n", offset); + + offset = (64 * accum_z) / 25600; + config[0] = ADXL346_OFSZ_ADDR; + config[1] = -offset; + i2c_burst_send(ADXL346_ADDRESS, config, sizeof(config)); + PRINTF("ADXL346: Z calibration offset is %d\n", offset); +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + int16_t accel; + if(!enabled) { + PRINTF("ADXL346: sensor not started\n"); + return ADXL346_ERROR; + } + + if(type == ADXL346_READ_X) { + return adxl346_read_accel(ADXL346_DATAX0_ADDR, ADXL346_DATAX1_ADDR); + } else if(type == ADXL346_READ_Y) { + return adxl346_read_accel(ADXL346_DATAY0_ADDR, ADXL346_DATAY1_ADDR); + } else if(type == ADXL346_READ_Z) { + return adxl346_read_accel(ADXL346_DATAZ0_ADDR, ADXL346_DATAZ1_ADDR); + } else if(type == ADXL346_READ_X_mG) { + accel = adxl346_read_accel(ADXL346_DATAX0_ADDR, ADXL346_DATAX1_ADDR); + return adxl346_convert_accel(accel); + } else if(type == ADXL346_READ_Y_mG) { + accel = adxl346_read_accel(ADXL346_DATAY0_ADDR, ADXL346_DATAY1_ADDR); + return adxl346_convert_accel(accel); + } else if(type == ADXL346_READ_Z_mG) { + accel = adxl346_read_accel(ADXL346_DATAZ0_ADDR, ADXL346_DATAZ1_ADDR); + return adxl346_convert_accel(accel); + } else { + PRINTF("ADXL346: invalid value requested\n"); + return ADXL346_ERROR; + } + + return ADXL346_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + if(type == ADXL346_ACTIVATE) { + if(!adxl346_is_present()) { + PRINTF("ADXL346: is not present\n"); + enabled = 0; + return ADXL346_ERROR; + } else { + adxl346_init(); + enabled = 1; + return ADXL346_SUCCESS; + } + } + + if(type == ADXL346_CALIB_OFFSET && enabled) { + adxl346_calibrate_offset(); + return ADXL346_SUCCESS; + } + + return ADXL346_ERROR; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(adxl346, ADXL346_SENSOR, value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/openmote-cc2538/dev/adxl346.h b/platform/openmote-cc2538/dev/adxl346.h new file mode 100644 index 000000000..401e601d1 --- /dev/null +++ b/platform/openmote-cc2538/dev/adxl346.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2014, OpenMote Technologies, S.L. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-sensors + * @{ + * + * \defgroup openmote-adxl346-sensor ADXL346 acceleration sensor + * @{ + * + * \file + * ADXL346 acceleration sensor driver header file + * + * \author + * Pere Tuset + */ +/*---------------------------------------------------------------------------*/ +#ifndef ADXL346_H_ +#define ADXL346_H_ +/*---------------------------------------------------------------------------*/ +#define ADXL346_ERROR (-1) +#define ADXL346_SUCCESS (0) +#define ADXL346_ACTIVATE (SENSORS_ACTIVE) +#define ADXL346_READ_X (2) +#define ADXL346_READ_X_mG (3) +#define ADXL346_READ_Y (4) +#define ADXL346_READ_Y_mG (5) +#define ADXL346_READ_Z (6) +#define ADXL346_READ_Z_mG (7) +#define ADXL346_CALIB_OFFSET (8) +#define ADXL346_NONE (9) +/*---------------------------------------------------------------------------*/ +#define ADXL346_SENSOR "ADXL346 Sensor" +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor adxl346; +/*---------------------------------------------------------------------------*/ +#endif /* ADXL346_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/openmote-cc2538/dev/antenna.c b/platform/openmote-cc2538/dev/antenna.c new file mode 100644 index 000000000..3672258f9 --- /dev/null +++ b/platform/openmote-cc2538/dev/antenna.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2014, Thingsquare, http://www.thingsquare.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. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-antenna + * @{ + * + * Driver for the OpenMote-CC2538 RF switch. + * INT is the internal antenna (chip) configured through ANT1_SEL (V1) + * EXT is the external antenna (connector) configured through ANT2_SEL (V2) + * @{ + * + * \file + * Driver implementation for the OpenMote-CC2538 antenna switch + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "dev/gpio.h" +#include "dev/antenna.h" +/*---------------------------------------------------------------------------*/ +#define BSP_RADIO_BASE GPIO_PORT_TO_BASE(GPIO_D_NUM) +#define BSP_RADIO_INT GPIO_PIN_MASK(5) +#define BSP_RADIO_EXT GPIO_PIN_MASK(4) +/*---------------------------------------------------------------------------*/ +void +antenna_init(void) +{ + /* Configure the ANT1 and ANT2 GPIO as output */ + GPIO_SET_OUTPUT(BSP_RADIO_BASE, BSP_RADIO_INT); + GPIO_SET_OUTPUT(BSP_RADIO_BASE, BSP_RADIO_EXT); + + /* Select external antenna by default. */ + antenna_external(); +} +/*---------------------------------------------------------------------------*/ +void +antenna_external(void) +{ + GPIO_WRITE_PIN(BSP_RADIO_BASE, BSP_RADIO_INT, 0); + GPIO_WRITE_PIN(BSP_RADIO_BASE, BSP_RADIO_EXT, 1); +} +/*---------------------------------------------------------------------------*/ +void +antenna_internal(void) +{ + GPIO_WRITE_PIN(BSP_RADIO_BASE, BSP_RADIO_EXT, 0); + GPIO_WRITE_PIN(BSP_RADIO_BASE, BSP_RADIO_INT, 1); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/openmote-cc2538/dev/antenna.h b/platform/openmote-cc2538/dev/antenna.h new file mode 100644 index 000000000..9c42bf885 --- /dev/null +++ b/platform/openmote-cc2538/dev/antenna.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, Thingsquare, http://www.thingsquare.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. + * + * This file is part of the Contiki operating system. + * + */ +/*--------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-cc2538 + * @{ + * + * \defgroup openmote-antenna OpenMote-CC2538 antenna switch + * + * Driver for the OpenMote-CC2538 antenna switch + * @{ + * + * \file + * Header for the OpenMote-CC2538 antenna switch + */ +/*---------------------------------------------------------------------------*/ +#ifndef ANTENNA_H_ +#define ANTENNA_H_ +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize the antenna switch, by default it uses the external + */ +void antenna_init(void); +/*---------------------------------------------------------------------------*/ +/** + * \brief Select the external (connector) antenna + */ +void antenna_internal(void); +/*---------------------------------------------------------------------------*/ +/** + * \brief Select the internal (chip) antenna + */ +void antenna_external(void); +/*---------------------------------------------------------------------------*/ +#endif /* ANTENNA_H_ */ +/** + * @} + * @} + */ diff --git a/platform/openmote-cc2538/dev/button-sensor.c b/platform/openmote-cc2538/dev/button-sensor.c new file mode 100644 index 000000000..6477045c5 --- /dev/null +++ b/platform/openmote-cc2538/dev/button-sensor.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-button-sensor + * @{ + * + * \file + * Driver for for the OpenMote-CC2538 user button + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/nvic.h" +#include "dev/ioc.h" +#include "dev/gpio.h" +#include "dev/button-sensor.h" +#include "sys/timer.h" +#include "sys/ctimer.h" +#include "sys/process.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +#define BUTTON_USER_PORT_BASE GPIO_PORT_TO_BASE(BUTTON_USER_PORT) +#define BUTTON_USER_PIN_MASK GPIO_PIN_MASK(BUTTON_USER_PIN) +/*---------------------------------------------------------------------------*/ +#define DEBOUNCE_DURATION (CLOCK_SECOND >> 4) + +static struct timer debouncetimer; +/*---------------------------------------------------------------------------*/ +static clock_time_t press_duration = 0; +static struct ctimer press_counter; +static uint8_t press_event_counter; + +process_event_t button_press_duration_exceeded; +/*---------------------------------------------------------------------------*/ +static void +duration_exceeded_callback(void *data) +{ + press_event_counter++; + process_post(PROCESS_BROADCAST, button_press_duration_exceeded, + &press_event_counter); + ctimer_set(&press_counter, press_duration, duration_exceeded_callback, + NULL); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Retrieves the value of the button pin + * \param type Returns the pin level or the counter of press duration events. + * type == BUTTON_SENSOR_VALUE_TYPE_LEVEL or + * type == BUTTON_SENSOR_VALUE_TYPE_PRESS_DURATION + * respectively + */ +static int +value(int type) +{ + switch(type) { + case BUTTON_SENSOR_VALUE_TYPE_LEVEL: + return GPIO_READ_PIN(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); + case BUTTON_SENSOR_VALUE_TYPE_PRESS_DURATION: + return press_event_counter; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Callback registered with the GPIO module. Gets fired with a button + * port/pin generates an interrupt + * \param port The port number that generated the interrupt + * \param pin The pin number that generated the interrupt. This is the pin + * absolute number (i.e. 0, 1, ..., 7), not a mask + */ +static void +btn_callback(uint8_t port, uint8_t pin) +{ + if(!timer_expired(&debouncetimer)) { + return; + } + + timer_set(&debouncetimer, DEBOUNCE_DURATION); + + if(press_duration) { + press_event_counter = 0; + if(value(BUTTON_SENSOR_VALUE_TYPE_LEVEL) == BUTTON_SENSOR_PRESSED_LEVEL) { + ctimer_set(&press_counter, press_duration, duration_exceeded_callback, + NULL); + } else { + ctimer_stop(&press_counter); + } + } + + sensors_changed(&button_sensor); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Init function for the User button. + * \param type SENSORS_ACTIVE: Activate / Deactivate the sensor (value == 1 + * or 0 respectively) + * + * \param value Depends on the value of the type argument + * \return Depends on the value of the type argument + */ +static int +config_user(int type, int value) +{ + switch(type) { + case SENSORS_HW_INIT: + button_press_duration_exceeded = process_alloc_event(); + + /* Software controlled */ + GPIO_SOFTWARE_CONTROL(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); + + /* Set pin to input */ + GPIO_SET_INPUT(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); + + /* Enable edge detection */ + GPIO_DETECT_EDGE(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); + + /* Both Edges */ + GPIO_TRIGGER_BOTH_EDGES(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); + + ioc_set_over(BUTTON_USER_PORT, BUTTON_USER_PIN, IOC_OVERRIDE_PUE); + + gpio_register_callback(btn_callback, BUTTON_USER_PORT, BUTTON_USER_PIN); + break; + case SENSORS_ACTIVE: + if(value) { + GPIO_ENABLE_INTERRUPT(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); + nvic_interrupt_enable(BUTTON_USER_VECTOR); + } else { + GPIO_DISABLE_INTERRUPT(BUTTON_USER_PORT_BASE, BUTTON_USER_PIN_MASK); + nvic_interrupt_disable(BUTTON_USER_VECTOR); + } + return value; + case BUTTON_SENSOR_CONFIG_TYPE_INTERVAL: + press_duration = (clock_time_t)value; + break; + default: + break; + } + + return 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(button_sensor, BUTTON_SENSOR, value, config_user, NULL); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/openmote-cc2538/dev/button-sensor.h b/platform/openmote-cc2538/dev/button-sensor.h new file mode 100644 index 000000000..9a08634ae --- /dev/null +++ b/platform/openmote-cc2538/dev/button-sensor.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-cc2538 + * @{ + * + * \defgroup openmote-button-sensor OpenMote-CC2538 user button driver + * + * The user button will generate a sensors_changed event on press as + * well as on release. + * + * @{ + * + * \file + * Header for the OpenMote-CC2538 button driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef BUTTON_SENSOR_H_ +#define BUTTON_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define BUTTON_SENSOR "Button" + +extern const struct sensors_sensor button_sensor; +/*---------------------------------------------------------------------------*/ +extern process_event_t button_press_duration_exceeded; +/*---------------------------------------------------------------------------*/ +#define BUTTON_SENSOR_CONFIG_TYPE_INTERVAL 0x0100 + +#define BUTTON_SENSOR_VALUE_TYPE_LEVEL 0 +#define BUTTON_SENSOR_VALUE_TYPE_PRESS_DURATION 1 + +#define BUTTON_SENSOR_PRESSED_LEVEL 0 +#define BUTTON_SENSOR_RELEASED_LEVEL 8 +/*---------------------------------------------------------------------------*/ +#endif /* BUTTON_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/openmote-cc2538/dev/leds-arch.c b/platform/openmote-cc2538/dev/leds-arch.c new file mode 100644 index 000000000..28454dacf --- /dev/null +++ b/platform/openmote-cc2538/dev/leds-arch.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-cc2538 + * @{ + * + * \defgroup openmote-leds OpenMote-CC2538 LED driver + * @{ + * + * \file + * LED driver implementation for the OpenMote-CC2538 platform + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "reg.h" +#include "dev/leds.h" +#include "dev/gpio.h" +/*---------------------------------------------------------------------------*/ +#define LEDS_GPIO_PIN_MASK LEDS_ALL +/*---------------------------------------------------------------------------*/ +void +leds_arch_init(void) +{ + GPIO_SET_OUTPUT(GPIO_C_BASE, LEDS_GPIO_PIN_MASK); +} +/*---------------------------------------------------------------------------*/ +unsigned char +leds_arch_get(void) +{ + return GPIO_READ_PIN(GPIO_C_BASE, LEDS_GPIO_PIN_MASK); +} +/*---------------------------------------------------------------------------*/ +void +leds_arch_set(unsigned char leds) +{ + GPIO_WRITE_PIN(GPIO_C_BASE, LEDS_GPIO_PIN_MASK, leds); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/openmote-cc2538/dev/max44009.c b/platform/openmote-cc2538/dev/max44009.c new file mode 100644 index 000000000..d7f4e90d9 --- /dev/null +++ b/platform/openmote-cc2538/dev/max44009.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2014, OpenMote Technologies, S.L. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-max44009-sensor + * @{ + * + * \file + * Driver for the MAX44009 light sensor + * + * \author + * Pere Tuset + */ +/*---------------------------------------------------------------------------*/ +#include "dev/i2c.h" +#include "dev/max44009.h" +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define DEBUG 1 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +/** + * \name MAX44009 address and device identifier + * @{ + */ +#define MAX44009_ADDRESS (0x4A) +#define MAX44009_NOT_FOUND (0x00) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name MAX44009 register addresses + * @{ + */ +#define MAX44009_INT_STATUS_ADDR (0x00) /* R */ +#define MAX44009_INT_ENABLE_ADDR (0x01) /* R/W */ +#define MAX44009_CONFIG_ADDR (0x02) /* R/W */ +#define MAX44009_LUX_HIGH_ADDR (0x03) /* R */ +#define MAX44009_LUX_LOW_ADDR (0x04) /* R */ +#define MAX44009_THR_HIGH_ADDR (0x05) /* R/W */ +#define MAX44009_THR_LOW_ADDR (0x06) /* R/W */ +#define MAX44009_THR_TIMER_ADDR (0x07) /* R/W */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name MAX44009 register values + * @{ + */ +#define MAX44009_INT_STATUS_OFF (0x00) +#define MAX44009_INT_STATUS_ON (0x01) +#define MAX44009_INT_DISABLED (0x00) +#define MAX44009_INT_ENABLED (0x01) + +#define MAX44009_CONFIG_DEFAULT (0 << 7) +#define MAX44009_CONFIG_CONTINUOUS (1 << 7) +#define MAX44009_CONFIG_AUTO (0 << 6) +#define MAX44009_CONFIG_MANUAL (1 << 6) +#define MAX44009_CONFIG_CDR_NORMAL (0 << 5) +#define MAX44009_CONFIG_CDR_DIVIDED (1 << 5) +#define MAX44009_CONFIG_INTEGRATION_800ms (0 << 0) +#define MAX44009_CONFIG_INTEGRATION_400ms (1 << 0) +#define MAX44009_CONFIG_INTEGRATION_200ms (2 << 0) +#define MAX44009_CONFIG_INTEGRATION_100ms (3 << 0) +#define MAX44009_CONFIG_INTEGRATION_50ms (4 << 0) +#define MAX44009_CONFIG_INTEGRATION_25ms (5 << 0) +#define MAX44009_CONFIG_INTEGRATION_12ms (6 << 0) +#define MAX44009_CONFIG_INTEGRATION_6ms (7 << 0) + +#define MAX44009_DEFAULT_CONFIGURATION (MAX44009_CONFIG_DEFAULT | \ + MAX44009_CONFIG_AUTO | \ + MAX44009_CONFIG_CDR_NORMAL | \ + MAX44009_CONFIG_INTEGRATION_100ms) + +#define MAX44009_USER_CONFIGURATION (MAX44009_CONFIG_DEFAULT | \ + MAX44009_CONFIG_AUTO | \ + MAX44009_CONFIG_CDR_NORMAL | \ + MAX44009_CONFIG_INTEGRATION_800ms) + +/** @} */ +/*---------------------------------------------------------------------------*/ +static uint8_t enabled; +/*---------------------------------------------------------------------------*/ +static void +max44009_init(void) +{ + uint8_t max44009_address[5] = { MAX44009_INT_ENABLE_ADDR, MAX44009_CONFIG_ADDR, \ + MAX44009_THR_HIGH_ADDR, MAX44009_THR_LOW_ADDR, \ + MAX44009_THR_TIMER_ADDR }; + uint8_t max44009_value[5]; + uint8_t max44009_data[2]; + uint8_t i; + + max44009_value[0] = (MAX44009_INT_STATUS_OFF); + max44009_value[1] = (MAX44009_USER_CONFIGURATION); + max44009_value[2] = (0xFF); + max44009_value[3] = (0x00); + max44009_value[4] = (0xFF); + + for(i = 0; i < sizeof(max44009_address) / sizeof(max44009_address[0]); i++) { + max44009_data[0] = max44009_address[i]; + max44009_data[1] = max44009_value[i]; + i2c_burst_send(MAX44009_ADDRESS, max44009_data, 2); + } +} +/*---------------------------------------------------------------------------*/ +static void +max44009_reset(void) +{ + uint8_t max44009_address[5] = { MAX44009_INT_ENABLE_ADDR, MAX44009_CONFIG_ADDR, \ + MAX44009_THR_HIGH_ADDR, MAX44009_THR_LOW_ADDR, \ + MAX44009_THR_TIMER_ADDR }; + uint8_t max44009_value[5] = { 0x00, 0x03, 0xFF, 0x00, 0xFF }; + uint8_t max44009_data[2]; + uint8_t i; + + for(i = 0; i < sizeof(max44009_address) / sizeof(max44009_address[0]); i++) { + max44009_data[0] = max44009_address[i]; + max44009_data[1] = max44009_value[i]; + i2c_burst_send(MAX44009_ADDRESS, max44009_data, 2); + } +} +/*---------------------------------------------------------------------------*/ +static uint8_t +max44009_is_present(void) +{ + uint8_t status; + uint8_t is_present; + + i2c_single_send(MAX44009_ADDRESS, MAX44009_CONFIG_ADDR); + status = i2c_single_receive(MAX44009_ADDRESS, &is_present); + if(status != I2C_MASTER_ERR_NONE) { + return 0; + } + + return is_present != MAX44009_NOT_FOUND; +} +/*---------------------------------------------------------------------------*/ +static uint16_t +max44009_read_light(void) +{ + uint8_t exponent, mantissa; + uint8_t max44009_data[2]; + uint32_t result; + + i2c_single_send(MAX44009_ADDRESS, MAX44009_LUX_HIGH_ADDR); + i2c_single_receive(MAX44009_ADDRESS, &max44009_data[0]); + i2c_single_send(MAX44009_ADDRESS, MAX44009_LUX_LOW_ADDR); + i2c_single_receive(MAX44009_ADDRESS, &max44009_data[1]); + + exponent = ((max44009_data[0] >> 4) & 0x0E); + mantissa = ((max44009_data[0] & 0x0F) << 4) | (max44009_data[1] & 0x0F); + + result = ((uint16_t)exponent << 8) | ((uint16_t)mantissa << 0); + + return result; +} +/*---------------------------------------------------------------------------*/ +static uint16_t +max44009_convert_light(uint16_t lux) +{ + uint8_t exponent, mantissa; + uint32_t result; + + exponent = (lux >> 8) & 0xFF; + exponent = (exponent == 0x0F ? exponent & 0x0E : exponent); + mantissa = (lux >> 0) & 0xFF; + + result = 45 * (2 ^ exponent * mantissa) / 10; + + return (uint16_t)result; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + uint16_t value; + + if(!enabled) { + PRINTF("MAX44009: sensor not started\n"); + return MAX44009_ERROR; + } + + if(type == MAX44009_READ_RAW_LIGHT) { + return max44009_read_light(); + } else if(type == MAX44009_READ_LIGHT) { + value = max44009_read_light(); + return max44009_convert_light(value); + } else { + PRINTF("MAX44009: invalid value requested\n"); + return MAX44009_ERROR; + } +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + if(type == MAX44009_ACTIVATE) { + if(!max44009_is_present()) { + return MAX44009_ERROR; + } else { + max44009_init(); + enabled = 1; + return MAX44009_SUCCESS; + } + } + + if((type == MAX44009_RESET) && enabled) { + max44009_reset(); + return MAX44009_SUCCESS; + } else { + PRINTF("MAX44009: is not enabled\n"); + return MAX44009_ERROR; + } + + return MAX44009_ERROR; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(max44009, MAX44009_SENSOR, value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/openmote-cc2538/dev/max44009.h b/platform/openmote-cc2538/dev/max44009.h new file mode 100644 index 000000000..32ba101e8 --- /dev/null +++ b/platform/openmote-cc2538/dev/max44009.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2014, OpenMote Technologies, S.L. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-sensors + * @{ + * + * \defgroup openmote-max44009-sensor MAX4009 light sensor + * @{ + * + * \file + * Header file for the MAX44009 light sensor driver + * + * \author + * Pere Tuset + */ +/*---------------------------------------------------------------------------*/ +#ifndef MAX44009_H_ +#define MAX44009_H_ +/*---------------------------------------------------------------------------*/ +#define MAX44009_ERROR (-1) +#define MAX44009_SUCCESS (0) +#define MAX44009_ACTIVATE (SENSORS_ACTIVE) +#define MAX44009_READ_RAW_LIGHT (2) +#define MAX44009_READ_LIGHT (3) +#define MAX44009_RESET (4) +#define MAX44009_NONE (5) +/*---------------------------------------------------------------------------*/ +#define MAX44009_SENSOR "MAX44009 Sensor" +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor max44009; +/*---------------------------------------------------------------------------*/ +#endif /* MAX44009_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/openmote-cc2538/dev/openmote-sensors.c b/platform/openmote-cc2538/dev/openmote-sensors.c new file mode 100644 index 000000000..3b55e4cbb --- /dev/null +++ b/platform/openmote-cc2538/dev/openmote-sensors.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-sensors + * @{ + * + * Generic module controlling sensors on the OpenMote-CC2538 platform + * @{ + * + * \file + * Implementation of a generic module controlling OpenMote-CC2538 sensors + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/cc2538-sensors.h" +#include "dev/button-sensor.h" + +#include +/*---------------------------------------------------------------------------*/ +/** + * \brief Exports a global symbol to be used by the sensor API + */ +SENSORS(&button_sensor, &cc2538_temp_sensor); +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/openmote-cc2538/dev/openmote-sensors.h b/platform/openmote-cc2538/dev/openmote-sensors.h new file mode 100644 index 000000000..a765dbd3d --- /dev/null +++ b/platform/openmote-cc2538/dev/openmote-sensors.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-cc2538 + * @{ + * + * \defgroup openmote-sensors OpenMote-CC2538 sensors + * + * Generic module controlling sensors on the OpenMote-CC2538 platform + * @{ + * + * \file + * Implementation of a generic module controlling OpenMote-CC2538 sensors + */ +/*---------------------------------------------------------------------------*/ +#ifndef OPENMOTE_SENSORS_H_ +#define OPENMOTE_SENSORS_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +#include "dev/cc2538-sensors.h" +#include "dev/button-sensor.h" +/*---------------------------------------------------------------------------*/ +#endif /* OPENMOTE_SENSORS_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/openmote-cc2538/dev/sht21.c b/platform/openmote-cc2538/dev/sht21.c new file mode 100644 index 000000000..4fd577e01 --- /dev/null +++ b/platform/openmote-cc2538/dev/sht21.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2014, OpenMote Technologies, S.L. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-sht21-sensor + * @{ + * + * \file + * Driver for the SHT21 temperature and relative humidity sensor + * + * \author + * Pere Tuset + */ +/*---------------------------------------------------------------------------*/ +#include "dev/i2c.h" +#include "dev/sht21.h" +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +/** + * \name SHT21 address + */ +#define SHT21_ADDRESS (0x40) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name SHT21 register addresses and values + * @{ + */ +#define SHT21_USER_REG_READ (0xE7) +#define SHT21_USER_REG_WRITE (0xE6) +#define SHT21_USER_REG_RESERVED_BITS (0x38) + +#define SHT21_TEMPERATURE_HM_CMD (0xE3) +#define SHT21_HUMIDITY_HM_CMD (0xE5) +#define SHT21_TEMPERATURE_NHM_CMD (0xF3) +#define SHT21_HUMIDITY_NHM_CMD (0xF5) +#define SHT21_RESET_CMD (0xFE) + +#define SHT21_STATUS_MASK (0xFC) + +#define SHT21_RESOLUTION_12b_14b ((0 << 7) | (0 << 0)) +#define SHT21_RESOLUTION_8b_12b ((0 << 7) | (1 << 0)) +#define SHT21_RESOLUTION_10b_13b ((1 << 7) | (0 << 0)) +#define SHT21_RESOLUTION_11b_11b ((1 << 7) | (1 << 0)) +#define SHT21_BATTERY_ABOVE_2V25 (0 << 6) +#define SHT21_BATTERY_BELOW_2V25 (1 << 6) +#define SHT21_ONCHIP_HEATER_ENABLE (1 << 2) +#define SHT21_ONCHIP_HEATER_DISABLE (0 << 2) +#define SHT21_OTP_RELOAD_ENABLE (0 << 1) +#define SHT21_OTP_RELOAD_DISABLE (1 << 1) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name SHT21 configuration values + * @{ + */ +#define SHT21_DEFAULT_CONFIG (SHT21_RESOLUTION_12b_14b | \ + SHT21_ONCHIP_HEATER_DISABLE | \ + SHT21_BATTERY_ABOVE_2V25 | \ + SHT21_OTP_RELOAD_DISABLE) + +#define SHT21_USER_CONFIG (SHT21_RESOLUTION_12b_14b | \ + SHT21_ONCHIP_HEATER_DISABLE | \ + SHT21_BATTERY_ABOVE_2V25 | \ + SHT21_OTP_RELOAD_DISABLE) +/** @} */ +/*---------------------------------------------------------------------------*/ +static uint8_t enabled; +/*---------------------------------------------------------------------------*/ +static void +sht21_init(void) +{ + uint8_t config[2]; + + /* Setup the configuration vector, the first position holds address */ + /* and the second position holds the actual configuration */ + config[0] = SHT21_USER_REG_WRITE; + config[1] = 0; + + /* Read the current configuration according to the datasheet (pag. 9, fig. 18) */ + i2c_single_send(SHT21_ADDRESS, SHT21_USER_REG_READ); + i2c_single_receive(SHT21_ADDRESS, &config[1]); + + /* Clean all the configuration bits except those reserved */ + config[1] &= SHT21_USER_REG_RESERVED_BITS; + + /* Set the configuration bits without changing those reserved */ + config[1] |= SHT21_USER_CONFIG; + + i2c_burst_send(SHT21_ADDRESS, config, sizeof(config)); +} +/*---------------------------------------------------------------------------*/ +static void +sht21_reset(void) +{ + /* Send a soft-reset command according to the datasheet (pag. 9, fig. 17) */ + i2c_single_send(SHT21_ADDRESS, SHT21_RESET_CMD); +} +/*---------------------------------------------------------------------------*/ +static uint8_t +sht21_is_present(void) +{ + uint8_t status; + uint8_t is_present; + + /* Read the current configuration according to the datasheet (pag. 9, fig. 18) */ + i2c_single_send(SHT21_ADDRESS, SHT21_USER_REG_READ); + status = i2c_single_receive(SHT21_ADDRESS, &is_present); + if(status != I2C_MASTER_ERR_NONE) { + return 0; + } + + /* Clear the reserved bits according to the datasheet (pag. 9, tab. 8) */ + is_present &= ~SHT21_USER_REG_RESERVED_BITS; + + return (is_present == SHT21_USER_CONFIG) || (is_present == SHT21_DEFAULT_CONFIG); +} +/*---------------------------------------------------------------------------*/ +static uint32_t +sht21_read_temperature(void) +{ + uint8_t sht21_temperature[2]; + uint16_t temperature; + + /* Read the current temperature according to the datasheet (pag. 8, fig. 15) */ + i2c_single_send(SHT21_ADDRESS, SHT21_TEMPERATURE_HM_CMD); + i2c_burst_receive(SHT21_ADDRESS, sht21_temperature, sizeof(sht21_temperature)); + + temperature = (sht21_temperature[0] << 8) | ((sht21_temperature[1] & SHT21_STATUS_MASK)); + + return temperature; +} +/*---------------------------------------------------------------------------*/ +static int16_t +sht21_convert_temperature(uint32_t temperature) +{ + int16_t result; + + temperature *= 17572; + temperature = temperature >> 16; + result = (int16_t)temperature - 4685; + + return result; +} +/*---------------------------------------------------------------------------*/ +static uint32_t +sht21_read_humidity(void) +{ + uint8_t sht21_humidity[2]; + uint16_t humidity; + + /* Read the current humidity according to the datasheet (pag. 8, fig. 15) */ + i2c_single_send(SHT21_ADDRESS, SHT21_HUMIDITY_HM_CMD); + i2c_burst_receive(SHT21_ADDRESS, sht21_humidity, sizeof(sht21_humidity)); + + humidity = (sht21_humidity[0] << 8) | ((sht21_humidity[1] & SHT21_STATUS_MASK)); + + return humidity; +} +/*---------------------------------------------------------------------------*/ +static int16_t +sht21_convert_humidity(uint32_t humidity) +{ + int16_t result; + + humidity *= 12500; + humidity = humidity >> 16; + result = (int16_t)humidity - 600; + result = (result > 10000) ? 10000 : result; + + return result; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + uint32_t value; + + if(!enabled) { + PRINTF("SHT21: sensor not started\n"); + return SHT21_ERROR; + } + + if(type == SHT21_READ_RAW_TEMP) { + return sht21_read_temperature(); + } else if(type == SHT21_READ_RAW_RHUM) { + return sht21_read_humidity(); + } else if(type == SHT21_READ_TEMP) { + value = sht21_read_temperature(); + return sht21_convert_temperature(value); + } else if(type == SHT21_READ_RHUM) { + value = sht21_read_humidity(); + return sht21_convert_humidity(value); + } else { + PRINTF("SHT21: invalid value requested\n"); + return SHT21_ERROR; + } +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + if(type == SHT21_ACTIVATE) { + if(!sht21_is_present()) { + PRINTF("SHT21: is not present\n"); + return SHT21_ERROR; + } else { + sht21_init(); + enabled = 1; + return SHT21_SUCCESS; + } + } + + if(type == SHT21_RESET && enabled) { + sht21_reset(); + return SHT21_SUCCESS; + } else { + PRINTF("SHT21: is not enabled\n"); + return SHT21_ERROR; + } + + return SHT21_ERROR; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(sht21, SHT21_SENSOR, value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/openmote-cc2538/dev/sht21.h b/platform/openmote-cc2538/dev/sht21.h new file mode 100644 index 000000000..3304d915e --- /dev/null +++ b/platform/openmote-cc2538/dev/sht21.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2014, OpenMote Technologies, S.L. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-sensors + * @{ + * + * \defgroup openmote-sht21-sensor SHT21 sensor + * @{ + * + * \file + * Header file for the SHT21 temperature and humidity sensor driver + * + * \author + * Pere Tuset + */ +/*---------------------------------------------------------------------------*/ +#ifndef SHT21_H_ +#define SHT21_H_ +/*---------------------------------------------------------------------------*/ +#define SHT21_ERROR (-1) +#define SHT21_SUCCESS (0) +#define SHT21_ACTIVATE (SENSORS_ACTIVE) +#define SHT21_READ_RAW_TEMP (2) +#define SHT21_READ_RAW_RHUM (3) +#define SHT21_READ_TEMP (4) +#define SHT21_READ_RHUM (5) +#define SHT21_RESET (6) +#define SHT21_NONE (7) +/*---------------------------------------------------------------------------*/ +#define SHT21_SENSOR "SHT21 Sensor" +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor sht21; +/*---------------------------------------------------------------------------*/ +#endif /* SHT21_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/openmote-cc2538/dev/tps62730.c b/platform/openmote-cc2538/dev/tps62730.c new file mode 100644 index 000000000..f90c0e097 --- /dev/null +++ b/platform/openmote-cc2538/dev/tps62730.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2014, OpenMote Technologies, S.L. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-tps62730 + * @{ + * + * Driver for the TPS62730 voltage regulator, to enable power from + * the battery voltage (bypass, Vout=Vin, Iq < 1uA) or through the + * buck regulator (on, Vout=2.1V, Iq = 30uA) + * @{ + * + * \file + * Driver for the TPS62730 voltage regulator + * + * \author + * Pere Tuset + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "dev/gpio.h" +#include "dev/tps62730.h" +/*---------------------------------------------------------------------------*/ +#define BSP_TPS62730_BASE (GPIO_B_BASE) +#define BSP_TPS62730_ON (1 << 1) +#define BSP_TPS62730_STATUS (1 << 0) +/*---------------------------------------------------------------------------*/ +static void +gpio_set(int port, int bit) +{ + REG((port | GPIO_DATA) + (bit << 2)) = bit; +} +/*---------------------------------------------------------------------------*/ +static void +gpio_reset(int port, int bit) +{ + REG((port | GPIO_DATA) + (bit << 2)) = 0; +} +/*---------------------------------------------------------------------------*/ +void +tps62730_init(void) +{ + GPIO_SET_OUTPUT(BSP_TPS62730_BASE, BSP_TPS62730_ON); + GPIO_SET_INPUT(BSP_TPS62730_BASE, BSP_TPS62730_STATUS); + + tps62730_bypass(); +} +/*---------------------------------------------------------------------------*/ +void +tps62730_on(void) +{ + gpio_set(BSP_TPS62730_BASE, BSP_TPS62730_ON); +} +/*---------------------------------------------------------------------------*/ +void +tps62730_bypass(void) +{ + gpio_reset(BSP_TPS62730_BASE, BSP_TPS62730_ON); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/openmote-cc2538/dev/tps62730.h b/platform/openmote-cc2538/dev/tps62730.h new file mode 100644 index 000000000..00518c9c7 --- /dev/null +++ b/platform/openmote-cc2538/dev/tps62730.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, OpenMote Technologies, S.L. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup openmote-cc2538 + * @{ + * + * \defgroup openmote-tps62730 TPS62730 voltage regulator + * + * Driver for the TPS62730 voltage regulator, to enable power from + * the battery voltage (bypass, Vout=Vin, Iq < 1uA) or through the + * buck regulator (on, Vout=2.1V, Iq = 30uA) + * @{ + * + * \file + * Driver for the TPS62730 voltage regulator + * + * \author + * Pere Tuset + */ +/*---------------------------------------------------------------------------*/ +#ifndef TPS62730_H_ +#define TPS62730_H_ +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize the TPS62730 voltage regulator in bypass mode + */ +void tps62730_init(void); +/*---------------------------------------------------------------------------*/ +/** + * \brief Set TPS62730 to on, Vout = 2.2V, Iq = 30 uA + */ +void tps62730_on(void); +/*---------------------------------------------------------------------------*/ +/** + * \brief Set TPS62730 to bypass, Vout = Vin, Iq < 1 uA + */ +void tps62730_bypass(void); +/*---------------------------------------------------------------------------*/ +#endif /* TPS62730_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/osd-merkur/Makefile.osd-merkur b/platform/osd-merkur-128/Makefile.osd-merkur-128 similarity index 70% rename from platform/osd-merkur/Makefile.osd-merkur rename to platform/osd-merkur-128/Makefile.osd-merkur-128 index 1527cdc6c..8817f3855 100644 --- a/platform/osd-merkur/Makefile.osd-merkur +++ b/platform/osd-merkur-128/Makefile.osd-merkur-128 @@ -1,10 +1,11 @@ -CONTIKI_TARGET_DIRS = . dev dev/LED_Strip_Suli apps net loader dev/arduino +CONTIKI_TARGET_DIRS = . dev apps net loader dev/arduino CONTIKI_CORE=contiki-main CONTIKI_TARGET_MAIN = ${CONTIKI_CORE}.o CONTIKI_TARGET_SOURCEFILES += contiki-main.c params.c node-id.c #Needed for slip -CONTIKI_TARGET_SOURCEFILES += temperature-sensor.c adc.c led.c sensors.c slip_uart0.c slip.c leds-arch.c +CONTIKI_TARGET_SOURCEFILES += led.c sensors.c slip_uart0.c slip.c leds-arch.c +CONTIKI_TARGET_SOURCEFILES += temperature-sensor.c adc.c #Needed for Button CONTIKI_TARGET_SOURCEFILES += button-sensor.c # i2c Master @@ -19,7 +20,6 @@ CONTIKI_TARGET_SOURCEFILES += battery-sensor.c batmon.c CONTIKI_TARGET_SOURCEFILES += pir-sensor.c #Needed for OPTRIAC CONTIKI_TARGET_SOURCEFILES += optriac-sensor.c -CONTIKIAVR=$(CONTIKI)/cpu/avr #Needed for SERVO CONTIKI_TARGET_SOURCEFILES += servo.c servo-sensor.c #Needed for Timer4 Servo @@ -28,11 +28,13 @@ CONTIKI_TARGET_SOURCEFILES += servo.c servo-sensor.c CONTIKI_TARGET_SOURCEFILES += relay.c relay-sensor.c # Arduino CONTIKI_TARGET_SOURCEFILES += wiring_digital.c -CONTIKI_TARGET_SOURCEFILES += LED_Strip_Suli.c CONTIKI_TARGET_SOURCEFILES += new.cpp twi.c Wire.cpp WMath.cpp CONTIKI_TARGET_SOURCEFILES += Print.cpp Stream.cpp WString.cpp +# guh Source Files +# Smart Grid Ready Interface +CONTIKI_TARGET_SOURCEFILES += sg-ready.c -SULI_DIR=$(CONTIKI)/platform/$(TARGET)/dev/LED_Strip_Suli +CONTIKIAVR=$(CONTIKI)/cpu/avr CONTIKIBOARD=. BOOTLOADER_START = 0x1F000 @@ -40,19 +42,29 @@ CONTIKI_PLAT_DEFS = -DF_CPU=16000000UL -DAUTO_CRC_PADDING=2 -DPLAT_TIMER=5 MCU=atmega128rfa1 -AVRDUDE_PROGRAMMER=jtag2 +#AVRDUDE_PROGRAMMER=jtag2 +AVRDUDE_PROGRAMMER=arduino -# For usb devices, you may either use PORT=usb, or (e.g. if you have more than one -# programmer connected) you can use the following trick to find out the serial number: +# For usb devices, you may either use PORT=usb, or (e.g. if you have +# more than one programmer connected) you can use the following trick to +# find out the serial number: # # The example is for an JTAGICE mkII used to program an ATmega128: # avrdude -v -P usb:xxxx -c jtag2 -p atmega128 -AVRDUDE_PORT=usb:00B000000D79 - +# AVRDUDE_PORT=usb:00B000000D79 +# For serial devices with bootloader we also use the AVRDUDE_PORT setting: +AVRDUDE_PORT=/dev/ttyUSB0 +# Only needed for serial devices, use empty setting for other +# programmers +AVRDUDE_BAUD_OPTION=-b 57600 # Additional avrdude options -# Verify off -AVRDUDE_OPTIONS=-V +# First some flash options: +# Verify off is -V +# Erase is -e +# No-Erase (needed by some stk500 variants) is -D +AVRDUDE_FLASH_OPTIONS=-e +AVRDUDE_OPTIONS=$(AVRDUDE_BAUD_OPTION) $(AVRDUDE_FLASH_OPTIONS) AVRDUDE_MCU=m128rfa1 #debug diff --git a/platform/osd-merkur-128/contiki-conf.h b/platform/osd-merkur-128/contiki-conf.h new file mode 100644 index 000000000..043dff995 --- /dev/null +++ b/platform/osd-merkur-128/contiki-conf.h @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2006, Technical University of Munich + * 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 + * Configuration for Atmel ATmega128rfa1 + * \author + * David Kopf + */ + +#ifndef CONTIKI_CONF_H_ +#define CONTIKI_CONF_H_ + +/* Platform name, type, and MCU clock rate */ +#define PLATFORM_NAME "RFA1" +#define PLATFORM_TYPE ATMEGA128RFA1 +#ifndef F_CPU +#define F_CPU 16000000UL +#endif + +#include + +#define IEEE802154_CONF_PANID 0xABCD // default panid + +/* The AVR tick interrupt usually is done with an 8 bit counter around 128 Hz. + * 125 Hz needs slightly more overhead during the interrupt, as does a 32 bit + * clock_time_t. + */ + /* Clock ticks per second */ +#define CLOCK_CONF_SECOND 128 + +typedef uint32_t clock_time_t; +#define CLOCK_LT(a,b) ((int32_t)((a)-(b)) < 0) + +/* These routines are not part of the contiki core but can be enabled in cpu/avr/clock.c */ +void clock_delay_msec(uint16_t howlong); +void clock_adjust_ticks(clock_time_t howmany); + +/* COM port to be used for SLIP connection. This is usually UART0. */ +#define SLIP_PORT RS232_PORT_0 + +/* Pre-allocated memory for loadable modules heap space (in bytes)*/ +/* Default is 4096. Currently used only when elfloader is present. Not tested on Raven */ +//#define MMEM_CONF_SIZE 256 + +/* Starting address for code received via the codeprop facility. Not tested. */ +typedef unsigned long off_t; +//#define EEPROMFS_ADDR_CODEPROP 0x8000 + +/* Logging adds 200 bytes to program size. RS232 output slows down webserver. */ +//#define LOG_CONF_ENABLED 1 + +/* RADIOSTATS is used in rf230bb, clock.c and the webserver cgi to report radio usage */ +/* It has less overhead than ENERGEST */ +//#define RADIOSTATS 1 + +/* More extensive stats, via main loop printfs or webserver status pages */ +//#define ENERGEST_CONF_ON 1 + +/* Packet statistics */ +typedef unsigned short uip_stats_t; +//#define UIP_STATISTICS 1 + +/* Available watchdog timeouts depend on mcu. Default is WDTO_2S. -1 Disables the watchdog. */ +/* AVR Studio simulator tends to reboot due to clocking the WD 8 times too fast */ +//#define WATCHDOG_CONF_TIMEOUT -1 + +/* Debugflow macro, useful for tracing path through mac and radio interrupts */ +//#define DEBUGFLOWSIZE 128 + + +/* Define MAX_*X_POWER to reduce tx power and ignore weak rx packets for testing a miniature multihop network. + * Leave undefined for full power and sensitivity. + * tx=0 (3dbm, default) to 15 (-17.2dbm) + * RF230_CONF_AUTOACK sets the extended mode using the energy-detect register with rx=0 (-91dBm) to 84 (-7dBm) + * else the rssi register is used having range 0 (91dBm) to 28 (-10dBm) + * For simplicity RF230_MIN_RX_POWER is based on the energy-detect value and divided by 3 when autoack is not set. + * On the RF230 a reduced rx power threshold will not prevent autoack if enabled and requested. + * These numbers applied to both Raven and Jackdaw give a maximum communication distance of about 15 cm + * and a 10 meter range to a full-sensitivity RF230 sniffer. +#define RF230_MAX_TX_POWER 15 +#define RF230_MIN_RX_POWER 30 + */ + /* The rf231, atmega128rfa1 and atmega256rfr2 can use an rssi + * threshold for triggering rx_busy that saves 0.5ma in rx mode + * 1 - 15 maps into -90 to -48 dBm; the register is written with + * RF230_MIN_RX_POWER/6 + 1. Undefine for -100dBm sensitivity + */ +//#define RF230_MIN_RX_POWER 0 + +/* Network setup */ +/* TX routine passes the cca/ack result in the return parameter */ +#define RDC_CONF_HARDWARE_ACK 1 +/* TX routine does automatic cca and optional backoffs */ +#define RDC_CONF_HARDWARE_CSMA 1 +/* Allow MCU sleeping between channel checks */ +#define RDC_CONF_MCU_SLEEP 1 + +#if NETSTACK_CONF_WITH_IPV6 +#define LINKADDR_CONF_SIZE 8 +#define UIP_CONF_ICMP6 1 +#define UIP_CONF_UDP 1 +#define UIP_CONF_TCP 1 +#define NETSTACK_CONF_NETWORK sicslowpan_driver +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 +#else +/* ip4 should build but is largely untested */ +#define LINKADDR_CONF_SIZE 2 +#define NETSTACK_CONF_NETWORK rime_driver +#endif + +#define UIP_CONF_LL_802154 1 +#define UIP_CONF_LLH_LEN 0 + +/* 10 bytes per stateful address context - see sicslowpan.c */ +/* Default is 1 context with prefix aaaa::/64 */ +/* These must agree with all the other nodes or there will be a failure to communicate! */ +#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 1 +#define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=0xaa;addr_contexts[0].prefix[1]=0xaa;} +#define SICSLOWPAN_CONF_ADDR_CONTEXT_1 {addr_contexts[1].prefix[0]=0xbb;addr_contexts[1].prefix[1]=0xbb;} +#define SICSLOWPAN_CONF_ADDR_CONTEXT_2 {addr_contexts[2].prefix[0]=0x20;addr_contexts[2].prefix[1]=0x01;addr_contexts[2].prefix[2]=0x49;addr_contexts[2].prefix[3]=0x78,addr_contexts[2].prefix[4]=0x1d;addr_contexts[2].prefix[5]=0xb1;} + +/* Take the default TCP maximum segment size for efficiency and simpler wireshark captures */ +/* Use this to prevent 6LowPAN fragmentation (whether or not fragmentation is enabled) */ +//#define UIP_CONF_TCP_MSS 48 + +#define UIP_CONF_IP_FORWARD 0 +#define UIP_CONF_FWCACHE_SIZE 0 + +#define UIP_CONF_IPV6_CHECKS 1 +#define UIP_CONF_IPV6_QUEUE_PKT 1 +#define UIP_CONF_IPV6_REASSEMBLY 0 + +#define UIP_CONF_UDP_CHECKSUMS 1 +#define UIP_CONF_TCP_SPLIT 1 +#define UIP_CONF_DHCP_LIGHT 1 + + +//#if 1 /* No radio cycling */ +#if 0 /* radio cycling */ + +#define NETSTACK_CONF_MAC nullmac_driver +#define NETSTACK_CONF_RDC sicslowmac_driver +#define NETSTACK_CONF_FRAMER framer_802154 +#define NETSTACK_CONF_RADIO rf230_driver +/* AUTOACK receive mode gives better rssi measurements, even if ACK is never requested */ +#define RF230_CONF_AUTOACK 1 +/* Request 802.15.4 ACK on all packets sent (else autoretry). This is primarily for testing. */ +#define SICSLOWPAN_CONF_ACK_ALL 0 +/* 1 + Number of auto retry attempts 0-15 (0 implies don't use extended TX_ARET_ON mode) */ +#define RF230_CONF_FRAME_RETRIES 2 +/* Number of csma retry attempts 0-5 in extended tx mode (7 does immediate tx with no csma) */ +#define RF230_CONF_CSMA_RETRIES 5 +/* Default is one RAM buffer for received packets. More than one may benefit multiple TCP connections or ports */ +#define RF230_CONF_RX_BUFFERS 3 +#define SICSLOWPAN_CONF_FRAG 1 +/* Most browsers reissue GETs after 3 seconds which stops fragment reassembly so a longer MAXAGE does no good */ +#define SICSLOWPAN_CONF_MAXAGE 3 +/* How long to wait before terminating an idle TCP connection. Smaller to allow faster sleep. Default is 120 seconds */ +/* If wait is too short the connection can be reset as a result of multiple fragment reassembly timeouts */ +#define UIP_CONF_WAIT_TIMEOUT 20 +/* 211 bytes per queue buffer */ +#define QUEUEBUF_CONF_NUM 8 +/* 54 bytes per queue ref buffer */ +#define QUEUEBUF_CONF_REF_NUM 2 +/* Allocate remaining RAM as desired */ +/* 30 bytes per TCP connection */ +/* 6LoWPAN does not do well with concurrent TCP streams, as new browser GETs collide with packets coming */ +/* from previous GETs, causing decreased throughput, retransmissions, and timeouts. Increase to study this. */ +/* ACKs to other ports become interleaved with computation-intensive GETs, so ACKs are particularly missed. */ +/* Increasing the number of packet receive buffers in RAM helps to keep ACKs from being lost */ +#define UIP_CONF_MAX_CONNECTIONS 4 +/* 2 bytes per TCP listening port */ +#define UIP_CONF_MAX_LISTENPORTS 4 +/* 25 bytes per UDP connection */ +#define UIP_CONF_UDP_CONNS 10 +/* See uip-ds6.h */ +#define NBR_TABLE_CONF_MAX_NEIGHBORS 20 +#define UIP_CONF_DS6_DEFRT_NBU 2 +#define UIP_CONF_DS6_PREFIX_NBU 3 +#define UIP_CONF_MAX_ROUTES 20 +#define UIP_CONF_DS6_ADDR_NBU 3 +#define UIP_CONF_DS6_MADDR_NBU 0 +#define UIP_CONF_DS6_AADDR_NBU 0 + + +#elif 1 /* Contiki-mac radio cycling */ +//#define NETSTACK_CONF_MAC nullmac_driver +/* csma needed for burst mode at present. Webserver won't work without it */ +#define NETSTACK_CONF_MAC csma_driver +#define NETSTACK_CONF_RDC contikimac_driver +/* Default is two CCA separated by 500 usec */ +#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8 +/* So without the header this needed for RPL mesh to form */ +#define CONTIKIMAC_FRAMER_CONF_SHORTEST_PACKET_SIZE 43-18 //multicast RPL DIS length +/* Not tested much yet */ +#define CONTIKIMAC_CONF_WITH_PHASE_OPTIMIZATION 0 +#define CONTIKIMAC_CONF_COMPOWER 1 +#define RIMESTATS_CONF_ENABLED 0 + +#if NETSTACK_CONF_WITH_IPV6 +#define NETSTACK_CONF_FRAMER framer_802154 +#else /* NETSTACK_CONF_WITH_IPV6 */ +#define NETSTACK_CONF_FRAMER contikimac_framer +#endif /* NETSTACK_CONF_WITH_IPV6 */ + +#define NETSTACK_CONF_RADIO rf230_driver +/* The radio needs to interrupt during an rtimer interrupt */ +#define RTIMER_CONF_NESTED_INTERRUPTS 1 +#define RF230_CONF_AUTOACK 1 +/* A 0 here means non-extended mode; 1 means extended mode with no retry, >1 for retrys */ +/* Contikimac strobes on its own, but hardware retries are faster */ +#define RF230_CONF_FRAME_RETRIES 1 +/* Long csma backoffs will compromise radio cycling; set to 0 for 1 csma */ +#define RF230_CONF_CSMA_RETRIES 0 +#define SICSLOWPAN_CONF_FRAG 1 +#define SICSLOWPAN_CONF_MAXAGE 3 +/* 211 bytes per queue buffer. Contikimac burst mode needs 15 for a 1280 byte MTU */ +#define QUEUEBUF_CONF_NUM 15 +/* 54 bytes per queue ref buffer */ +#define QUEUEBUF_CONF_REF_NUM 2 +/* Allocate remaining RAM. Not much left due to queuebuf increase */ +#define UIP_CONF_MAX_CONNECTIONS 2 +#define UIP_CONF_MAX_LISTENPORTS 4 +#define UIP_CONF_UDP_CONNS 5 +#define NBR_TABLE_CONF_MAX_NEIGHBORS 20 +#define UIP_CONF_DS6_DEFRT_NBU 2 +#define UIP_CONF_DS6_PREFIX_NBU 3 +#define UIP_CONF_MAX_ROUTES 4 +#define UIP_CONF_DS6_ADDR_NBU 3 +#define UIP_CONF_DS6_MADDR_NBU 0 +#define UIP_CONF_DS6_AADDR_NBU 0 + +#else +#error Network configuration not specified! +#endif /* Network setup */ + +/* ************************************************************************** */ +//#pragma mark RPL Settings +/* ************************************************************************** */ +#if UIP_CONF_IPV6_RPL + +#define UIP_CONF_ROUTER 1 +#define UIP_CONF_ND6_SEND_RA 0 +#define UIP_CONF_ND6_REACHABLE_TIME 600000 +#define UIP_CONF_ND6_RETRANS_TIMER 10000 + +/* For slow slip connections, to prevent buffer overruns */ +//#define UIP_CONF_RECEIVE_WINDOW 300 +#undef UIP_CONF_FWCACHE_SIZE +#define UIP_CONF_FWCACHE_SIZE 30 +#define UIP_CONF_BROADCAST 1 +#define UIP_ARCH_IPCHKSUM 1 +#define UIP_CONF_PINGADDRCONF 0 +#define UIP_CONF_LOGGING 0 + +#endif /* RPL */ + +#define CCIF +#define CLIF +#ifndef CC_CONF_INLINE +#define CC_CONF_INLINE inline +#endif + +/* include the project config */ +/* PROJECT_CONF_H might be defined in the project Makefile */ +#ifdef PROJECT_CONF_H +#include PROJECT_CONF_H +#endif + +#endif /* CONTIKI_CONF_H_ */ diff --git a/platform/osd-merkur-128/contiki-main.c b/platform/osd-merkur-128/contiki-main.c new file mode 100644 index 000000000..142d6edd7 --- /dev/null +++ b/platform/osd-merkur-128/contiki-main.c @@ -0,0 +1,593 @@ +/* + * Copyright (c) 2006, Technical University of Munich + * 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. + * + */ +#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args) + +#define ANNOUNCE_BOOT 1 //adds about 600 bytes to program size +#if ANNOUNCE_BOOT +#define PRINTA(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTA(...) +#endif + +#define DEBUG 0 +#if DEBUG +#define PRINTD(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTD(...) +#endif + +#include +#include +#include +#include +#include +#include + +#include "loader/symbols-def.h" +#include "loader/symtab.h" + +#include "params.h" +#include "radio/rf230bb/rf230bb.h" +#include "net/mac/frame802154.h" +#include "net/mac/framer-802154.h" +#include "net/ipv6/sicslowpan.h" + +#include "contiki.h" +#include "contiki-net.h" +#include "contiki-lib.h" + +#include "dev/rs232.h" +#include "dev/serial-line.h" +#include "dev/slip.h" + +#if AVR_WEBSERVER +#include "httpd-fs.h" +#include "httpd-cgi.h" +#endif + +#ifdef COFFEE_FILES +#include "cfs/cfs.h" +#include "cfs/cfs-coffee.h" +#endif + +#if UIP_CONF_ROUTER&&0 +#include "net/routing/rimeroute.h" +#include "net/rime/rime-udp.h" +#endif + +#include "net/rime/rime.h" + +/* Track interrupt flow through mac, rdc and radio driver */ +//#define DEBUGFLOWSIZE 32 +#if DEBUGFLOWSIZE +uint8_t debugflowsize,debugflow[DEBUGFLOWSIZE]; +#define DEBUGFLOW(c) if (debugflowsize<(DEBUGFLOWSIZE-1)) debugflow[debugflowsize++]=c +#else +#define DEBUGFLOW(c) +#endif + +/* Get periodic prints from idle loop, from clock seconds or rtimer interrupts */ +/* Use of rtimer will conflict with other rtimer interrupts such as contikimac radio cycling */ +/* STAMPS will print ENERGEST outputs if that is enabled. */ +#define PERIODICPRINTS 1 +#if PERIODICPRINTS +//#define PINGS 64 +#define ROUTES 600 +#define STAMPS 60 +#define STACKMONITOR 1024 +uint32_t clocktime; +#define TESTRTIMER 0 +#if TESTRTIMER +uint8_t rtimerflag=1; +struct rtimer rt; +void rtimercycle(void) {rtimerflag=1;} +#endif +#endif + +//uint16_t ledtimer; + +/*-------------------------------------------------------------------------*/ +/*----------------------Configuration of the .elf file---------------------*/ +#if 1 +/* The proper way to set the signature is */ +#include +#else +/* Older avr-gcc's may not define the needed SIGNATURE bytes. Do it manually if you get an error */ +typedef struct {const unsigned char B2;const unsigned char B1;const unsigned char B0;} __signature_t; +#define SIGNATURE __signature_t __signature __attribute__((section (".signature"))) +SIGNATURE = { + .B2 = 0x01,//SIGNATURE_2, //ATMEGA128rfa1 + .B1 = 0xA7,//SIGNATURE_1, //128KB flash + .B0 = 0x1E,//SIGNATURE_0, //Atmel +}; +#endif + +#if 1 +/* JTAG+SPI enabled, External osc 1kck4ms1 , Boot 4096 words @ $1F000, TXC1K+4,1msec delay, Brownout 1.9 volts */ +FUSES ={.low = 0xF6, .high = 0x98, .extended = 0xfd,}; +#define BOOTLOADER_START = 0x1F000 +#else +/* JTAG+SPI, Boot 4096 words @ $F000, Internal oscillator, startup 6 CK +0 ms, Brownout 1.8 volts */ +FUSES ={.low = 0xC2, .high = 0x99, .extended = 0xfe,}; +#endif + +#include "lib/sensors.h" +#include "dev/button-sensor.h" +#include "dev/battery-sensor.h" +#include "dev/pir-sensor.h" +SENSORS(&button_sensor, &pir_sensor); + +uint8_t +rng_get_uint8(void) { +#if 1 + /* Upper two RSSI reg bits (RND_VALUE) are random in rf231 */ + uint8_t j; + j = (PHY_RSSI&0xc0) + ((PHY_RSSI>>2)&0x30) + ((PHY_RSSI>>4)&0x0c) + ((PHY_RSSI>>6)&0x03); +#else +/* Get a pseudo random number using the ADC */ + uint8_t i,j; + ADCSRA=1<>4); +} +/*-------------------------Low level initialization------------------------*/ +/*------Done in a subroutine to keep main routine stack usage small--------*/ +void initialize(void) +{ + watchdog_init(); + watchdog_start(); + + /* Generic or slip connection on uart0 */ + rs232_init(RS232_PORT_0, USART_BAUD_38400,USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8); + + /* Second rs232 port for debugging or slip alternative */ +// rs232_init(RS232_PORT_1, USART_BAUD_57600,USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8); + + /* Redirect stdout */ + rs232_redirect_stdout(RS232_PORT_0); + + clock_init(); + + if(MCUSR & (1< +//#define delay_us( us ) ( _delay_loop_2(1+(us*F_CPU)/4000000UL) ) +// delay_us(50000); + } + clock_init(); +} +#endif + + PRINTA("\n*******Booting %s*******\n",CONTIKI_VERSION_STRING); + +/* rtimers needed for radio cycling */ + rtimer_init(); + + /* Initialize process subsystem */ + process_init(); + + /* etimers must be started before ctimer_init */ + process_start(&etimer_process, NULL); + ctimer_init(); + + /* Start radio and radio receive process */ + NETSTACK_RADIO.init(); + +/* Get a random seed for the 802.15.4 packet sequence number. + * Some layers will ignore duplicates found in a history (e.g. Contikimac) + * causing the initial packets to be ignored after a short-cycle restart. + */ + random_init(rng_get_uint8()); + + /* Set addresses BEFORE starting tcpip process */ + + linkaddr_t addr; + + if (params_get_eui64(addr.u8)) { + PRINTA("Random EUI64 address generated\n"); + } + +#if NETSTACK_CONF_WITH_IPV6 + memcpy(&uip_lladdr.addr, &addr.u8, sizeof(linkaddr_t)); +#elif WITH_NODE_ID + node_id=get_panaddr_from_eeprom(); + addr.u8[1]=node_id&0xff; + addr.u8[0]=(node_id&0xff00)>>8; + PRINTA("Node ID from eeprom: %X\n",node_id); +#endif + linkaddr_set_node_addr(&addr); + + PRINTA("Panid:%x\n", params_get_panid()); +// framer_802154_set_panid(params_get_panid()); + rf230_set_pan_addr(params_get_panid(),params_get_panaddr(),(uint8_t *)&addr.u8); + rf230_set_channel(params_get_channel()); + rf230_set_txpower(params_get_txpower()); + +#if NETSTACK_CONF_WITH_IPV6 + PRINTA("EUI-64 MAC: %x-%x-%x-%x-%x-%x-%x-%x\n",addr.u8[0],addr.u8[1],addr.u8[2],addr.u8[3],addr.u8[4],addr.u8[5],addr.u8[6],addr.u8[7]); +#else + PRINTA("MAC address "); + uint8_t i; + for (i=sizeof(linkaddr_t); i>0; i--){ + PRINTA("%x:",addr.u8[i-1]); + } + PRINTA("\n"); +#endif + + /* Initialize stack protocols */ + queuebuf_init(); + NETSTACK_RDC.init(); + NETSTACK_MAC.init(); + NETSTACK_NETWORK.init(); + +#if ANNOUNCE_BOOT + PRINTA("%s %s, channel %u , check rate %u Hz tx power %u\n",NETSTACK_MAC.name, NETSTACK_RDC.name, rf230_get_channel(), + CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1:NETSTACK_RDC.channel_check_interval()), + rf230_get_txpower()); +#if UIP_CONF_IPV6_RPL + PRINTA("RPL Enabled\n"); +#endif +#if UIP_CONF_ROUTER + PRINTA("Routing Enabled\n"); +#endif + +#endif /* ANNOUNCE_BOOT */ + +#if NETSTACK_CONF_WITH_IPV6 || NETSTACK_CONF_WITH_IPV4 + process_start(&tcpip_process, NULL); +#endif + + process_start(&sensors_process, NULL); + + /* Autostart other processes */ + autostart_start(autostart_processes); + + /*---If using coffee file system create initial web content if necessary---*/ +#if COFFEE_FILES + int fa = cfs_open( "/index.html", CFS_READ); + if (fa<0) { //Make some default web content + PRINTA("No index.html file found, creating upload.html!\n"); + PRINTA("Formatting FLASH file system for coffee..."); + cfs_coffee_format(); + PRINTA("Done!\n"); + fa = cfs_open( "/index.html", CFS_WRITE); + int r = cfs_write(fa, &"It works!", 9); + if (r<0) PRINTA("Can''t create /index.html!\n"); + cfs_close(fa); +// fa = cfs_open("upload.html"), CFW_WRITE); +//
+ } +#endif /* COFFEE_FILES */ + +/* Add addresses for testing */ +#if 0 +{ + uip_ip6addr_t ipaddr; + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); +// uip_ds6_prefix_add(&ipaddr,64,0); +} +#endif + +/*--------------------------Announce the configuration---------------------*/ +#if ANNOUNCE_BOOT +#if AVR_WEBSERVER +{ uint8_t i; + char buf[80]; + unsigned int size; + + for (i=0;i>10); +#elif COFFEE_FILES==3 + PRINTA(".%s online with static %u byte program memory file system\n",buf,size); +#elif COFFEE_FILES==4 + PRINTA(".%s online with dynamic %u KB program memory file system\n",buf,size>>10); +#endif /* COFFEE_FILES */ +} +#else + PRINTA("Online\n"); +#endif +#endif /* ANNOUNCE_BOOT */ + +} + +#if ROUTES && NETSTACK_CONF_WITH_IPV6 +static void +ipaddr_add(const uip_ipaddr_t *addr) +{ + uint16_t a; + int8_t i, f; + for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0) PRINTF("::"); + } else { + if(f > 0) { + f = -1; + } else if(i > 0) { + PRINTF(":"); + } + PRINTF("%x",a); + } + } +} +#endif + +/*-------------------------------------------------------------------------*/ +/*------------------------- Main Scheduler loop----------------------------*/ +/*-------------------------------------------------------------------------*/ +int +main(void) +{ +#if NETSTACK_CONF_WITH_IPV6 + uip_ds6_nbr_t *nbr; +#endif /* NETSTACK_CONF_WITH_IPV6 */ + initialize(); + + while(1) { + process_run(); + watchdog_periodic(); + +#if 0 + /* Turn off LED after a while */ + if (ledtimer) { + if (--ledtimer==0) { + } + } +#endif + +#if 0 +/* Various entry points for debugging in the AVR Studio simulator. + * Set as next statement and step into the routine. + */ + NETSTACK_RADIO.send(packetbuf_hdrptr(), 42); + process_poll(&rf230_process); + packetbuf_clear(); + len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE); + packetbuf_set_datalen(42); + NETSTACK_RDC.input(); +#endif + +#if 0 +/* Clock.c can trigger a periodic PLL calibration in the RF230BB driver. + * This can show when that happens. + */ + extern uint8_t rf230_calibrated; + if (rf230_calibrated) { + PRINTD("\nRF230 calibrated!\n"); + rf230_calibrated=0; + } +#endif + +/* Set DEBUGFLOWSIZE in contiki-conf.h to track path through MAC, RDC, and RADIO */ +#if DEBUGFLOWSIZE + if (debugflowsize) { + debugflow[debugflowsize]=0; + PRINTF("%s",debugflow); + debugflowsize=0; + } +#endif + +#if PERIODICPRINTS +#if TESTRTIMER +/* Timeout can be increased up to 8 seconds maximum. + * A one second cycle is convenient for triggering the various debug printouts. + * The triggers are staggered to avoid printing everything at once. + */ + if (rtimerflag) { + rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL); + rtimerflag=0; +#else + if (clocktime!=clock_seconds()) { + clocktime=clock_seconds(); +#endif + +#if STAMPS +if ((clocktime%STAMPS)==0) { +#if ENERGEST_CONF_ON +#include "lib/print-stats.h" + print_stats(); +#elif RADIOSTATS +extern volatile unsigned long radioontime; + PRINTF("%u(%u)s\n",clocktime,radioontime); +#else + PRINTF("%us\n",clocktime); +#endif + +} +#endif +#if TESTRTIMER + clocktime+=1; +#endif + +#if PINGS && NETSTACK_CONF_WITH_IPV6 +extern void raven_ping6(void); +if ((clocktime%PINGS)==1) { + PRINTF("**Ping\n"); + raven_ping6(); +} +#endif + +#if ROUTES && NETSTACK_CONF_WITH_IPV6 +if ((clocktime%ROUTES)==2) { + +extern uip_ds6_netif_t uip_ds6_if; + + uint8_t i,j=0; + PRINTF("\nAddresses [%u max]\n",UIP_DS6_ADDR_NB); + for (i=0;iipaddr); + PRINTF("\n"); + j=0; + } + + if (j) PRINTF(" "); + PRINTF("\nRoutes [%u max]\n",UIP_DS6_ROUTE_NB); + { + uip_ds6_route_t *r; + j = 1; + for(r = uip_ds6_route_head(); + r != NULL; + r = uip_ds6_route_next(r)) { + ipaddr_add(&r->ipaddr); + PRINTF("/%u (via ", r->length); + ipaddr_add(uip_ds6_route_nexthop(r)); + PRINTF(") %lus\n", r->state.lifetime); + j = 0; + } + } + if (j) PRINTF(" "); + PRINTF("\n---------\n"); + +} +#endif + +#if STACKMONITOR +if ((clocktime%STACKMONITOR)==3) { + extern uint16_t __bss_end; + uint16_t p=(uint16_t)&__bss_end; + do { + if (*(uint16_t *)p != 0x4242) { + PRINTF("Never-used stack > %d bytes\n",p-(uint16_t)&__bss_end); + break; + } + p+=10; + } while (p +*/ + + + // WARNING : Blink function is disabled on the core leds.c file + +#include "contiki.h" +#include "dev/leds.h" +#include "leds-arch.h" + +/*---------------------------------------------------------------------------*/ +void +leds_arch_init(void) +{ +DDRE |= (1< + +#define NUM_DIGITAL_PINS 15 +#define NUM_ANALOG_INPUTS 6 +#define analogInputToDigitalPin(p) ((p < NUM_ANALOG_INPUTS) ? (p) + NUM_DIGITAL_PINS : -1) +#define digitalPinHasPWM(p) ((p) == 2 ||(p) == 3 ||(p) == 4 ||(p) == 14 ) + +// Dev board specific defines: RF RX and TX LEDs: +#define RXLED_DDR DDRB +#define RXLED_PORT PORTB +#define RXLED_POS PB6 + +#define TXLED_DDR DDRB +#define TXLED_PORT PORTB +#define TXLED_POS PB7 + +const static uint8_t SS = 10; +const static uint8_t MOSI = 11; +const static uint8_t MISO = 13; +const static uint8_t SCK = 12; + +const static uint8_t SDA = 9; +const static uint8_t SCL = 8; +const static uint8_t LED = 4; +const static uint8_t LED1 = 4; +const static uint8_t LED2 = 5; + +const static uint8_t A0 = 7; +const static uint8_t A1 = 6; +const static uint8_t A2 = 5; +const static uint8_t A3 = 4; +const static uint8_t A4 = 0; +const static uint8_t A5 = 1; + +// A majority of the pins are NOT PCINTs, SO BE WARNED (i.e. you cannot use them as receive pins) +// Only pins available for RECEIVE (TRANSMIT can be on any pin): +// Pins: 10, 11, 12, 13, 14 + +#define digitalPinToPCICR(p) ( (((p) >= 10) && ((p) <= 14)) || ? (&PCICR) : ((uint8_t *)0) ) + +#define digitalPinToPCICRbit(p) ( 0 ) + +#define digitalPinToPCMSK(p) ( (((p) >= 10) && ((p) <= 14)) ? (&PCMSK0) : ((uint8_t *)0) ) + +#define digitalPinToPCMSKbit(p) ( ((p) == 10) ? 6 : \ + ( ((p) == 11) ? 5 : \ + ( ((p) == 12) ? 1 : \ + ( ((p) == 13) ? 3 : \ + ( ((p) == 14) ? 7 : \ + 0 ) ) ) ) ) + +#ifdef ARDUINO_MAIN + +const uint16_t PROGMEM port_to_mode_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t)&DDRB, + NOT_A_PORT, + (uint16_t)&DDRD, + (uint16_t)&DDRE, + (uint16_t)&DDRF, + (uint16_t)&DDRG, + NOT_A_PORT, + NOT_A_PORT, + NOT_A_PORT, + NOT_A_PORT, + NOT_A_PORT, +}; + +const uint16_t PROGMEM port_to_output_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t)&PORTB, + NOT_A_PORT, + (uint16_t)&PORTD, + (uint16_t)&PORTE, + (uint16_t)&PORTF, + (uint16_t)&PORTG, + NOT_A_PORT, + NOT_A_PORT, + NOT_A_PORT, + NOT_A_PORT, + NOT_A_PORT, +}; + +const uint16_t PROGMEM port_to_input_PGM[] = { + NOT_A_PIN, + NOT_A_PIN, + NOT_A_PIN, + (uint16_t)&PINC, + (uint16_t)&PIND, + (uint16_t)&PINE, + (uint16_t)&PINF, + (uint16_t)&PING, + NOT_A_PIN, + NOT_A_PIN, + NOT_A_PIN, + NOT_A_PIN, + NOT_A_PIN, +}; + +const uint8_t PROGMEM digital_pin_to_port_PGM[] = { + // PORTLIST + // ------------------------------------------- + PE , // PE 1 ** 0 ** D0 / USART0_TX + PE , // PE 0 ** 1 ** D1 / USART0_RX + PE , // PE 3 ** 2 ** D2 / PWM + PE , // PE 4 ** 3 ** D3 / PWM + PE , // PE 5 ** 4 ** D4 / PWM / LED1 / LED + PE , // PE 6 ** 5 ** D5 / LED2 + PD , // PD 3 ** 6 ** D6 / USART1_TX + PD , // PD 2 ** 7 ** D7 / USART1_RX + PD , // PD 0 ** 8 ** D8 / I2C_SCL + PD , // PD 1 ** 9 ** D9 / I2C_SDA + PB , // PB 0 ** 10 ** D10 / SPI_SSN + PB , // PB 2 ** 11 ** D11 / SPI_MOSI + PB , // PB 1 ** 12 ** D12 / SPI_SCK + PB , // PB 3 ** 13 ** D13 / SPI_MISO + PB , // PB 4 ** 14 ** D14 / PWM + PF , // PF 7 ** 15 ** A0 / D15 + PF , // PF 6 ** 16 ** A1 / D16 + PF , // PF 5 ** 17 ** A2 / D17 + PF , // PF 4 ** 18 ** A3 / D18 + PF , // PF 0 ** 19 ** A4 / D19 + PF , // PF 1 ** 20 ** A5 / D20 +// PB , // PB 6 ** 34 ** D34 / LED1 / LED / PWM +// PB , // PB 7 ** 35 ** D35 / LED2 / PWM +// PE , // PE 2 ** 2 ** D2 +// PE , // PE 7 ** 7 ** D7 +// PB , // PB 5 ** 8 ** D8 / PWM +// PG , // PG 0 ** 16 ** D16 +// PG , // PG 1 ** 17 ** D17 +// PG , // PG 2 ** 18 ** D18 +// PG , // PG 5 ** 19 ** D19 / PWM +// PD , // PD 4 ** 22 ** D22 +// PD , // PD 5 ** 23 ** D23 +// PD , // PD 6 ** 24 ** D24 +// PD , // PD 7 ** 25 ** D25 +// PF , // PF 2 ** 28 ** A2 / D28 +// PF , // PF 3 ** 29 ** A3 / D29 +}; + +const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { + // PIN IN PORT + // ------------------------------------------- + _BV( 1 ) , // PE 1 ** 0 ** USART0_TX + _BV( 0 ) , // PE 0 ** 1 ** USART0_RX + _BV( 3 ) , // PE 3 ** 2 ** D3 / PWM + _BV( 4 ) , // PE 4 ** 3 ** D4 / PWM + _BV( 5 ) , // PE 5 ** 4 ** D5 / PWM + _BV( 6 ) , // PE 6 ** 5 ** D6 + _BV( 3 ) , // PD 3 ** 6 ** D21 / USART1_TX + _BV( 2 ) , // PD 2 ** 7 ** D20 / USART1_RX + _BV( 0 ) , // PD 0 ** 8 ** D15 / I2C_SCL + _BV( 1 ) , // PD 1 ** 9 ** D14 / I2C_SDA + _BV( 0 ) , // PB 0 ** 10 ** D10 / SPI_SSN + _BV( 2 ) , // PB 2 ** 11 ** D11 / SPI_MOSI + _BV( 1 ) , // PB 1 ** 12 ** D13 / SPI_SCK + _BV( 3 ) , // PB 3 ** 13 ** D12 / SPI_MISO + _BV( 4 ) , // PB 4 ** 14 ** D9 / PWM + _BV( 7 ) , // PF 7 ** 15 ** A0 / D33 + _BV( 6 ) , // PF 6 ** 16 ** A1 / D32 + _BV( 5 ) , // PF 5 ** 17 ** A2 / D31 + _BV( 4 ) , // PF 4 ** 18 ** A3 / D30 + _BV( 0 ) , // PF 0 ** 19 ** A4 / D26 + _BV( 1 ) , // PF 1 ** 20 ** A5 / D27 +// _BV( 2 ) , // PE 2 ** 2 ** D2 +// _BV( 7 ) , // PE 7 ** 7 ** D7 +// _BV( 5 ) , // PB 5 ** 8 ** D8 / PWM +// _BV( 0 ) , // PG 0 ** 16 ** D16 +// _BV( 1 ) , // PG 1 ** 17 ** D17 +// _BV( 2 ) , // PG 2 ** 18 ** D18 +// _BV( 5 ) , // PG 5 ** 19 ** D19 / PWM +// _BV( 4 ) , // PD 4 ** 22 ** D22 +// _BV( 5 ) , // PD 5 ** 23 ** D23 +// _BV( 6 ) , // PD 6 ** 24 ** D24 +// _BV( 7 ) , // PD 7 ** 25 ** D25 +// _BV( 2 ) , // PF 2 ** 28 ** A2 / D28 +// _BV( 3 ) , // PF 3 ** 29 ** A3 / D29 +// _BV( 6 ) , // PB 6 ** 34 ** D34 / LED1 / LED / PWM +// _BV( 7 ) , // PB 7 ** 35 ** D35 / LED2 / PWM +}; + +#endif + +#endif diff --git a/platform/osd-merkur-128/node-id.c b/platform/osd-merkur-128/node-id.c new file mode 100644 index 000000000..8698b1855 --- /dev/null +++ b/platform/osd-merkur-128/node-id.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * $Id: node-id.c,v 1.1 2007/03/23 09:59:08 nifi Exp $ + */ + +/** + * \file + * Utility to store a node id in the external flash + * \author + * Adam Dunkels + */ + +#include "node-id.h" +#include "contiki-conf.h" +#include "dev/xmem.h" + +unsigned short node_id = 0; + +/*---------------------------------------------------------------------------*/ +void +node_id_restore(void) +{ +/* todo */ +/* + unsigned char buf[4]; + xmem_pread(buf, 4, NODE_ID_XMEM_OFFSET); + if(buf[0] == 0xad && + buf[1] == 0xde) { + node_id = (buf[2] << 8) | buf[3]; + } else { + node_id = 0; + } +*/ + node_id = 0; +} +/*---------------------------------------------------------------------------*/ +void +node_id_burn(unsigned short id) +{ +/* todo */ +/* + unsigned char buf[4]; + buf[0] = 0xad; + buf[1] = 0xde; + buf[2] = id >> 8; + buf[3] = id & 0xff; + xmem_erase(XMEM_ERASE_UNIT_SIZE, NODE_ID_XMEM_OFFSET); + xmem_pwrite(buf, 4, NODE_ID_XMEM_OFFSET); +*/ +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/osd-merkur-128/node-id.h b/platform/osd-merkur-128/node-id.h new file mode 100644 index 000000000..592379fc9 --- /dev/null +++ b/platform/osd-merkur-128/node-id.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * Author: Adam Dunkels + * + * $Id: node-id.h,v 1.1 2007/03/23 09:59:08 nifi Exp $ + */ + +#ifndef __NODE_ID_H__ +#define __NODE_ID_H__ + +void node_id_restore(void); +void node_id_burn(unsigned short node_id); + +extern unsigned short node_id; + +#endif /* __NODE_ID_H__ */ diff --git a/platform/osd-merkur-128/params.c b/platform/osd-merkur-128/params.c new file mode 100644 index 000000000..4b0252387 --- /dev/null +++ b/platform/osd-merkur-128/params.c @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2011, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args) + +#define DEBUG 1 +#if DEBUG +#define PRINTD(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTD(...) +#endif + +#include "contiki.h" +#include +#include +#include +#include + +#if AVR_WEBSERVER +//#include "httpd-fs.h" +//#include "httpd-cgi.h" +#endif + +#include "contiki-net.h" +#include "params.h" + +#if WITH_NODE_ID +uint16_t node_id; +#endif + +#if CONTIKI_CONF_RANDOM_MAC +extern uint8_t rng_get_uint8(void); +static void +generate_new_eui64(uint8_t eui64[8]) { + eui64[0] = 0x02; + eui64[1] = rng_get_uint8(); + eui64[2] = rng_get_uint8(); + eui64[3] = 0xFF; + eui64[4] = 0xFE; + eui64[5] = rng_get_uint8(); + eui64[6] = rng_get_uint8(); + eui64[7] = rng_get_uint8(); +} +#endif + +#if AVR_WEBSERVER +/* Webserver builds can set these in httpd-fsdata.c via makefsdata.h */ +extern uint8_t default_mac_address[8]; +extern uint8_t default_server_name[16]; +extern uint8_t default_domain_name[30]; +#else +const uint8_t default_mac_address[8] PROGMEM = PARAMS_EUI64ADDR; +const uint8_t default_server_name[] PROGMEM = PARAMS_SERVERNAME; +const uint8_t default_domain_name[] PROGMEM = PARAMS_DOMAINNAME; +#endif + +#if PARAMETER_STORAGE==0 +/* 0 Hard coded, minmal program and eeprom usage. */ + +extern uint8_t bootloader_get_mac(uint8_t); + +uint8_t +params_get_eui64(uint8_t *eui64) { +#if CONTIKI_CONF_RANDOM_MAC + PRINTD("Generating random EUI64 MAC\n"); + generate_new_eui64(eui64); + return 1; +#else + uint8_t i; +#if BOOTLOADER_GET_MAC + for (i=0;i 26)) x[1]=x[0]; +/* Do exclusive or test on the two values read */ + if((uint8_t)x[0]!=(uint8_t)~x[1]) {//~x[1] can promote comparison to 16 bit +/* Verification fails, rewrite everything */ + uint8_t i,buffer[32]; + PRINTD("EEPROM is corrupt, rewriting with defaults.\n"); +#if CONTIKI_CONF_RANDOM_MAC + PRINTD("Generating random EUI64 MAC\n"); + generate_new_eui64(&buffer); + randomeui64=1; +#else + for (i=0;iSet EEPROM RF channel to %d\n",x); + } + } + return x; +} +uint8_t +params_get_eui64(uint8_t *eui64) { + size_t size = sizeof(linkaddr_t); + if(settings_get(SETTINGS_KEY_EUI64, 0, (unsigned char*)eui64, &size) == SETTINGS_STATUS_OK) { + PRINTD("<-Get EUI64 MAC\n"); + return 0; + } +#if CONTIKI_CONF_RANDOM_MAC + PRINTD("Generating random EUI64 MAC\n"); + generate_new_eui64(eui64); +#else + {uint8_t i;for (i=0;i<8;i++) eui64[i] = pgm_read_byte_near(default_mac_address+i);} //test this +#endif + if (settings_add(SETTINGS_KEY_EUI64,(unsigned char*)eui64,8) == SETTINGS_STATUS_OK) { + PRINTD("->Set EEPROM MAC address\n"); + } +#if CONTIKI_CONF_RANDOM_MAC + return 1; +#else + return 0; +#endif +} +uint16_t +params_get_panid(void) { + uint16_t x; + size_t size = 2; + if (settings_get(SETTINGS_KEY_PAN_ID, 0,(unsigned char*)&x, &size) == SETTINGS_STATUS_OK) { + PRINTD("<-Get PAN ID of %04x\n",x); + } else { + x=IEEE802154_PANID; + if (settings_add_uint16(SETTINGS_KEY_PAN_ID,x)==SETTINGS_STATUS_OK) { + PRINTD("->Set EEPROM PAN ID to %04x\n",x); + } + } + return x; +} +uint16_t +params_get_panaddr(void) { + uint16_t x; + size_t size = 2; + if (settings_get(SETTINGS_KEY_PAN_ADDR, 0,(unsigned char*)&x, &size) == SETTINGS_STATUS_OK) { + PRINTD("<-Get PAN address of %04x\n",x); + } else { + x=PARAMS_PANADDR; + if (settings_add_uint16(SETTINGS_KEY_PAN_ADDR,x)==SETTINGS_STATUS_OK) { + PRINTD("->Set EEPROM PAN address to %04x\n",x); + } + } + return x; +} +uint8_t +params_get_txpower(void) { + uint8_t x; + size_t size = 1; + if (settings_get(SETTINGS_KEY_TXPOWER, 0,(unsigned char*)&x, &size) == SETTINGS_STATUS_OK) { + PRINTD("<-Get tx power of %d (0=max)\n",x); + } else { + x=PARAMS_TXPOWER; + if (settings_add_uint8(SETTINGS_KEY_TXPOWER,x)==SETTINGS_STATUS_OK) { + PRINTD("->Set EEPROM tx power of %d (0=max)\n",x); + } + } + return x; +} +#endif /* CONTIKI_CONF_SETTINGS_MANAGER */ diff --git a/platform/osd-merkur/params.h b/platform/osd-merkur-128/params.h similarity index 91% rename from platform/osd-merkur/params.h rename to platform/osd-merkur-128/params.h index ce368de97..f338e75e1 100644 --- a/platform/osd-merkur/params.h +++ b/platform/osd-merkur-128/params.h @@ -17,16 +17,15 @@ // end default settings -#define CONTIKI_CONF_RANDOM_MAC 0 //adds 78 bytes +#define CONTIKI_CONF_RANDOM_MAC 0 //adds 78 bytes #define CONTIKI_CONF_SETTINGS_MANAGER 0 //adds 1696 bytes -#define BOOTLOADER_GET_MAC 0x0001ff80 // get mac from bootloader, need bootloader bonsai, PARAMETER_STORAGE 0 +#define BOOTLOADER_GET_MAC 0x0001ff80 // get mac from bootloader #if CONTIKI_CONF_SETTINGS_MANAGER //#define PARAMETER_STORAGE 2 #define PARAMETER_STORAGE 2 #else -//#define PARAMETER_STORAGE 1 -#define PARAMETER_STORAGE 0 // get mac form boolaoder, need bootlaoder bonsai, PARAMETER_STORAGE 0 +#define PARAMETER_STORAGE 0 // 0:get mac from booloader (see above) #endif /* Include settings.h, then dummy out the write routines */ @@ -75,7 +74,7 @@ extern uint8_t eemem_domain_name[30]; #if UIP_CONF_LL_802154 //#define PARAMS_EUI64ADDR {0x02, 0xNN, 0xNN, 0xNN, 0xNN, 0xNN, 0xNN, 0xNN} //#define PARAMS_EUI64ADDR {0x00, 0x21, 0x2e, 0xff, 0xff, 0x00, 0x1E, 0xFB} -#define PARAMS_EUI64ADDR {0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x01} +#define PARAMS_EUI64ADDR {0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x11} #else //#define PARAMS_EUI64ADDR {0x02, 0xNN, 0xNN, 0xff, 0xfe, 0xNN, 0xNN, 0xNN} #define PARAMS_EUI64ADDR {0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x03} diff --git a/platform/osd-merkur-128/slip_uart0.c b/platform/osd-merkur-128/slip_uart0.c new file mode 100644 index 000000000..edff55385 --- /dev/null +++ b/platform/osd-merkur-128/slip_uart0.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2010, University of Colombo School of Computing + * 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 + * Machine dependent AVR SLIP routines for UART0. + * \author + * Kasun Hewage + */ + +#include +#include "contiki.h" +#include "dev/rs232.h" +#include "slip.h" + +/*---------------------------------------------------------------------------*/ +static int +slip_putchar(char c, FILE *stream) +{ +#define SLIP_END 0300 + static char debug_frame = 0; + + if (!debug_frame) { /* Start of debug output */ + slip_arch_writeb(SLIP_END); + slip_arch_writeb('\r'); /* Type debug line == '\r' */ + debug_frame = 1; + } + + slip_arch_writeb((unsigned char)c); + + /* + * Line buffered output, a newline marks the end of debug output and + * implicitly flushes debug output. + */ + if (c == '\n') { + slip_arch_writeb(SLIP_END); + debug_frame = 0; + } + + return c; +} +/*---------------------------------------------------------------------------*/ +static FILE slip_stdout = FDEV_SETUP_STREAM(slip_putchar, NULL, + _FDEV_SETUP_WRITE); +/*---------------------------------------------------------------------------*/ +void +slip_arch_init(unsigned long ubr) +{ + rs232_set_input(SLIP_PORT, slip_input_byte); + stdout = &slip_stdout; +} +/*---------------------------------------------------------------------------*/ +/* + XXX: + Currently, the following function is in cpu/avr/dev/rs232.c file. this + should be moved to here from there hence this is a platform specific slip + related function. +void +slip_arch_writeb(unsigned char c) +{ + rs232_send(RS232_PORT_0, c); +} +*/ diff --git a/platform/osd-merkur-256/Makefile.osd-merkur-256 b/platform/osd-merkur-256/Makefile.osd-merkur-256 new file mode 100644 index 000000000..0a60d2044 --- /dev/null +++ b/platform/osd-merkur-256/Makefile.osd-merkur-256 @@ -0,0 +1,91 @@ +CONTIKI_TARGET_DIRS = . dev apps net loader dev/arduino + +CONTIKI_CORE=contiki-main +CONTIKI_TARGET_MAIN = ${CONTIKI_CORE}.o +CONTIKI_TARGET_SOURCEFILES += contiki-main.c params.c node-id.c +#Needed for slip +CONTIKI_TARGET_SOURCEFILES += led.c sensors.c slip_uart0.c slip.c leds-arch.c +CONTIKI_TARGET_SOURCEFILES += temperature-sensor.c adc.c +#Needed for Button +CONTIKI_TARGET_SOURCEFILES += button-sensor.c +# i2c Master +#CONTIKI_TARGET_SOURCEFILES += i2c.c +#Needed for DHT11 humidity sensor +CONTIKI_TARGET_SOURCEFILES += dht11.c +#Needed for DS18S20 temperature sensor +CONTIKI_TARGET_SOURCEFILES += ds1820.c +#Needed for Battery test +CONTIKI_TARGET_SOURCEFILES += battery-sensor.c batmon.c +#Needed for PIR +CONTIKI_TARGET_SOURCEFILES += pir-sensor.c +#Needed for OPTRIAC +CONTIKI_TARGET_SOURCEFILES += optriac-sensor.c +#Needed for SERVO +CONTIKI_TARGET_SOURCEFILES += servo.c servo-sensor.c +#Needed for Timer4 Servo +#CONTIKI_TARGET_SOURCEFILES += t4-servo.c t4-servo-sensor.c +#Needed for Relay 1 to 4 +CONTIKI_TARGET_SOURCEFILES += relay.c relay-sensor.c +# Arduino +CONTIKI_TARGET_SOURCEFILES += wiring_digital.c +CONTIKI_TARGET_SOURCEFILES += new.cpp twi.c Wire.cpp WMath.cpp +CONTIKI_TARGET_SOURCEFILES += Print.cpp Stream.cpp WString.cpp +# guh Source Files +# Smart Grid Ready Interface +CONTIKI_TARGET_SOURCEFILES += sg-ready.c + +CONTIKIAVR=$(CONTIKI)/cpu/avr + +CONTIKIBOARD=. +BOOTLOADER_START = 0x3E000 +CONTIKI_PLAT_DEFS = -DF_CPU=16000000UL -DAUTO_CRC_PADDING=2 -DPLAT_TIMER=5 + +MCU=atmega256rfr2 + +#AVRDUDE_PROGRAMMER=jtag2 +AVRDUDE_PROGRAMMER=stk500v2 + +# For usb devices, you may either use PORT=usb, or (e.g. if you have +# more than one programmer connected) you can use the following trick to +# find out the serial number: +# +# The example is for an JTAGICE mkII used to program an atmega256: +# avrdude -v -P usb:xxxx -c jtag2 -p atmega256 +# AVRDUDE_PORT=usb:00B000000D79 +# For serial devices with bootloader we also use the AVRDUDE_PORT setting: +AVRDUDE_PORT=/dev/ttyUSB0 +# Only needed for serial devices, use empty setting for other +# programmers +AVRDUDE_BAUD_OPTION=-b 57600 + +# Additional avrdude options +# First some flash options: +# Verify off is -V +# Erase is -e +# No-Erase (needed by our stk500 variant) is -D +# Note that it really doesn't turn off erase: It doesn't issue an +# explicit erase command (which is not implemented) but the bootloader +# *always* does an implicit erase when programming. +AVRDUDE_FLASH_OPTIONS=-D +AVRDUDE_OPTIONS=$(AVRDUDE_BAUD_OPTION) $(AVRDUDE_FLASH_OPTIONS) +AVRDUDE_MCU=m256rfr2 + +#debug +# CFLAGS += -save-temps +# Bootloader bonsai +# LDFLAGS += -save-temps +# For newer bootloaders we have a jump table at the end of the bootloader +# section: guhRF Bootloader MAC Address +BOOTLOADER_GET_MAC=0x0003ff80 + +LDFLAGS += -Wl,--defsym,bootloader_get_mac=$(BOOTLOADER_GET_MAC) + + +include $(CONTIKIAVR)/Makefile.avr +include $(CONTIKIAVR)/radio/Makefile.radio + +MODULES += core/net/mac core/net core/net/mac/sicslowmac \ + core/net/mac/contikimac core/net/llsec \ +# core/net/ipv6 core/net/ipv4 core/net/ip \ +# core/net/rime \ +# core/net/rpl \ diff --git a/platform/osd-merkur-256/contiki-conf.h b/platform/osd-merkur-256/contiki-conf.h new file mode 100644 index 000000000..fb8cf3178 --- /dev/null +++ b/platform/osd-merkur-256/contiki-conf.h @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2006, Technical University of Munich + * 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 + * Configuration for Atmel ATMEGA256RFR2 + * \author + * David Kopf + * Bernhard Trinnes + */ + +#ifndef CONTIKI_CONF_H_ +#define CONTIKI_CONF_H_ + +/* Platform name, type, and MCU clock rate */ +#define PLATFORM_NAME "RFR2" +#define PLATFORM_TYPE ATMEGA256RFR2 +#ifndef F_CPU +#define F_CPU 16000000UL +#endif + +#include + +#define IEEE802154_CONF_PANID 0xABCD // default panid + +/* The AVR tick interrupt usually is done with an 8 bit counter around 128 Hz. + * 125 Hz needs slightly more overhead during the interrupt, as does a 32 bit + * clock_time_t. + */ + /* Clock ticks per second */ +#define CLOCK_CONF_SECOND 128 + +typedef uint32_t clock_time_t; +#define CLOCK_LT(a,b) ((int32_t)((a)-(b)) < 0) + +/* These routines are not part of the contiki core but can be enabled in cpu/avr/clock.c */ +void clock_delay_msec(uint16_t howlong); +void clock_adjust_ticks(clock_time_t howmany); + +/* COM port to be used for SLIP connection. This is usually UART0. */ +#define SLIP_PORT RS232_PORT_0 + +/* Pre-allocated memory for loadable modules heap space (in bytes)*/ +/* Default is 4096. Currently used only when elfloader is present. Not tested on Raven */ +//#define MMEM_CONF_SIZE 256 + +/* Starting address for code received via the codeprop facility. Not tested. */ +typedef unsigned long off_t; +//#define EEPROMFS_ADDR_CODEPROP 0x8000 + +/* Logging adds 200 bytes to program size. RS232 output slows down webserver. */ +//#define LOG_CONF_ENABLED 1 + +/* RADIOSTATS is used in rf230bb, clock.c and the webserver cgi to report radio usage */ +/* It has less overhead than ENERGEST */ +//#define RADIOSTATS 1 + +/* More extensive stats, via main loop printfs or webserver status pages */ +//#define ENERGEST_CONF_ON 1 + +/* Packet statistics */ +typedef unsigned short uip_stats_t; +//#define UIP_STATISTICS 1 + +/* Available watchdog timeouts depend on mcu. Default is WDTO_2S. -1 Disables the watchdog. */ +/* AVR Studio simulator tends to reboot due to clocking the WD 8 times too fast */ +//#define WATCHDOG_CONF_TIMEOUT -1 + +/* Debugflow macro, useful for tracing path through mac and radio interrupts */ +//#define DEBUGFLOWSIZE 128 + + +/* Define MAX_*X_POWER to reduce tx power and ignore weak rx packets for testing a miniature multihop network. + * Leave undefined for full power and sensitivity. + * tx=0 (3dbm, default) to 15 (-17.2dbm) + * RF230_CONF_AUTOACK sets the extended mode using the energy-detect register with rx=0 (-91dBm) to 84 (-7dBm) + * else the rssi register is used having range 0 (91dBm) to 28 (-10dBm) + * For simplicity RF230_MIN_RX_POWER is based on the energy-detect value and divided by 3 when autoack is not set. + * On the RF230 a reduced rx power threshold will not prevent autoack if enabled and requested. + * These numbers applied to both Raven and Jackdaw give a maximum communication distance of about 15 cm + * and a 10 meter range to a full-sensitivity RF230 sniffer. +#define RF230_MAX_TX_POWER 15 +#define RF230_MIN_RX_POWER 30 + */ + /* The rf231, atmega128rfa1 and atmega256rfr2 can use an rssi + * threshold for triggering rx_busy that saves 0.5ma in rx mode + * 1 - 15 maps into -90 to -48 dBm; the register is written with + * RF230_MIN_RX_POWER/6 + 1. Undefine for -100dBm sensitivity + */ +//#define RF230_MIN_RX_POWER 0 + +/* Network setup */ +/* TX routine passes the cca/ack result in the return parameter */ +#define RDC_CONF_HARDWARE_ACK 1 +/* TX routine does automatic cca and optional backoffs */ +#define RDC_CONF_HARDWARE_CSMA 1 +/* Allow MCU sleeping between channel checks */ +#define RDC_CONF_MCU_SLEEP 1 + +#if NETSTACK_CONF_WITH_IPV6 +#define LINKADDR_CONF_SIZE 8 +#define UIP_CONF_ICMP6 1 +#define UIP_CONF_UDP 1 +#define UIP_CONF_TCP 1 +#define NETSTACK_CONF_NETWORK sicslowpan_driver +#define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 +#else +/* ip4 should build but is largely untested */ +#define LINKADDR_CONF_SIZE 2 +#define NETSTACK_CONF_NETWORK rime_driver +#endif + +#define UIP_CONF_LL_802154 1 +#define UIP_CONF_LLH_LEN 0 + +/* 10 bytes per stateful address context - see sicslowpan.c */ +/* Default is 1 context with prefix aaaa::/64 */ +/* These must agree with all the other nodes or there will be a failure to communicate! */ +#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 1 +#define SICSLOWPAN_CONF_ADDR_CONTEXT_0 {addr_contexts[0].prefix[0]=0xaa;addr_contexts[0].prefix[1]=0xaa;} +#define SICSLOWPAN_CONF_ADDR_CONTEXT_1 {addr_contexts[1].prefix[0]=0xbb;addr_contexts[1].prefix[1]=0xbb;} +#define SICSLOWPAN_CONF_ADDR_CONTEXT_2 {addr_contexts[2].prefix[0]=0x20;addr_contexts[2].prefix[1]=0x01;addr_contexts[2].prefix[2]=0x49;addr_contexts[2].prefix[3]=0x78,addr_contexts[2].prefix[4]=0x1d;addr_contexts[2].prefix[5]=0xb1;} + +/* Take the default TCP maximum segment size for efficiency and simpler wireshark captures */ +/* Use this to prevent 6LowPAN fragmentation (whether or not fragmentation is enabled) */ +//#define UIP_CONF_TCP_MSS 48 + +#define UIP_CONF_IP_FORWARD 0 +#define UIP_CONF_FWCACHE_SIZE 0 + +#define UIP_CONF_IPV6_CHECKS 1 +#define UIP_CONF_IPV6_QUEUE_PKT 1 +#define UIP_CONF_IPV6_REASSEMBLY 0 + +#define UIP_CONF_UDP_CHECKSUMS 1 +#define UIP_CONF_TCP_SPLIT 1 +#define UIP_CONF_DHCP_LIGHT 1 + + +//#if 1 /* No radio cycling */ +#if 0 /* radio cycling */ + +#define NETSTACK_CONF_MAC nullmac_driver +#define NETSTACK_CONF_RDC sicslowmac_driver +#define NETSTACK_CONF_FRAMER framer_802154 +#define NETSTACK_CONF_RADIO rf230_driver +/* AUTOACK receive mode gives better rssi measurements, even if ACK is never requested */ +#define RF230_CONF_AUTOACK 1 +/* Request 802.15.4 ACK on all packets sent (else autoretry). This is primarily for testing. */ +#define SICSLOWPAN_CONF_ACK_ALL 0 +/* 1 + Number of auto retry attempts 0-15 (0 implies don't use extended TX_ARET_ON mode) */ +#define RF230_CONF_FRAME_RETRIES 2 +/* Number of csma retry attempts 0-5 in extended tx mode (7 does immediate tx with no csma) */ +#define RF230_CONF_CSMA_RETRIES 5 +/* Default is one RAM buffer for received packets. More than one may benefit multiple TCP connections or ports */ +#define RF230_CONF_RX_BUFFERS 3 +#define SICSLOWPAN_CONF_FRAG 1 +/* Most browsers reissue GETs after 3 seconds which stops fragment reassembly so a longer MAXAGE does no good */ +#define SICSLOWPAN_CONF_MAXAGE 3 +/* How long to wait before terminating an idle TCP connection. Smaller to allow faster sleep. Default is 120 seconds */ +/* If wait is too short the connection can be reset as a result of multiple fragment reassembly timeouts */ +#define UIP_CONF_WAIT_TIMEOUT 20 +/* 211 bytes per queue buffer */ +#define QUEUEBUF_CONF_NUM 8 +/* 54 bytes per queue ref buffer */ +#define QUEUEBUF_CONF_REF_NUM 2 +/* Allocate remaining RAM as desired */ +/* 30 bytes per TCP connection */ +/* 6LoWPAN does not do well with concurrent TCP streams, as new browser GETs collide with packets coming */ +/* from previous GETs, causing decreased throughput, retransmissions, and timeouts. Increase to study this. */ +/* ACKs to other ports become interleaved with computation-intensive GETs, so ACKs are particularly missed. */ +/* Increasing the number of packet receive buffers in RAM helps to keep ACKs from being lost */ +#define UIP_CONF_MAX_CONNECTIONS 4 +/* 2 bytes per TCP listening port */ +#define UIP_CONF_MAX_LISTENPORTS 4 +/* 25 bytes per UDP connection */ +#define UIP_CONF_UDP_CONNS 10 +/* See uip-ds6.h */ +#define NBR_TABLE_CONF_MAX_NEIGHBORS 20 +#define UIP_CONF_DS6_DEFRT_NBU 2 +#define UIP_CONF_DS6_PREFIX_NBU 3 +#define UIP_CONF_MAX_ROUTES 20 +#define UIP_CONF_DS6_ADDR_NBU 3 +#define UIP_CONF_DS6_MADDR_NBU 0 +#define UIP_CONF_DS6_AADDR_NBU 0 + + +#elif 1 /* Contiki-mac radio cycling */ +//#define NETSTACK_CONF_MAC nullmac_driver +/* csma needed for burst mode at present. Webserver won't work without it */ +#define NETSTACK_CONF_MAC csma_driver +#define NETSTACK_CONF_RDC contikimac_driver +/* Default is two CCA separated by 500 usec */ +#define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8 +/* So without the header this needed for RPL mesh to form */ +#define CONTIKIMAC_FRAMER_CONF_SHORTEST_PACKET_SIZE 43-18 //multicast RPL DIS length +/* Not tested much yet */ +#define CONTIKIMAC_CONF_WITH_PHASE_OPTIMIZATION 0 +#define CONTIKIMAC_CONF_COMPOWER 1 +#define RIMESTATS_CONF_ENABLED 0 + +#if NETSTACK_CONF_WITH_IPV6 +#define NETSTACK_CONF_FRAMER framer_802154 +#else /* NETSTACK_CONF_WITH_IPV6 */ +#define NETSTACK_CONF_FRAMER contikimac_framer +#endif /* NETSTACK_CONF_WITH_IPV6 */ + +#define NETSTACK_CONF_RADIO rf230_driver +/* The radio needs to interrupt during an rtimer interrupt */ +#define RTIMER_CONF_NESTED_INTERRUPTS 1 +#define RF230_CONF_AUTOACK 1 +/* A 0 here means non-extended mode; 1 means extended mode with no retry, >1 for retrys */ +/* Contikimac strobes on its own, but hardware retries are faster */ +#define RF230_CONF_FRAME_RETRIES 1 +/* Long csma backoffs will compromise radio cycling; set to 0 for 1 csma */ +#define RF230_CONF_CSMA_RETRIES 0 +#define SICSLOWPAN_CONF_FRAG 1 +#define SICSLOWPAN_CONF_MAXAGE 3 +/* 211 bytes per queue buffer. Contikimac burst mode needs 15 for a 1280 byte MTU */ +#define QUEUEBUF_CONF_NUM 15 +/* 54 bytes per queue ref buffer */ +#define QUEUEBUF_CONF_REF_NUM 2 +/* Allocate remaining RAM. Not much left due to queuebuf increase */ +#define UIP_CONF_MAX_CONNECTIONS 2 +#define UIP_CONF_MAX_LISTENPORTS 4 +#define UIP_CONF_UDP_CONNS 5 +#define NBR_TABLE_CONF_MAX_NEIGHBORS 20 +#define UIP_CONF_DS6_DEFRT_NBU 2 +#define UIP_CONF_DS6_PREFIX_NBU 3 +#define UIP_CONF_MAX_ROUTES 4 +#define UIP_CONF_DS6_ADDR_NBU 3 +#define UIP_CONF_DS6_MADDR_NBU 0 +#define UIP_CONF_DS6_AADDR_NBU 0 + +#else +#error Network configuration not specified! +#endif /* Network setup */ + +/* ************************************************************************** */ +//#pragma mark RPL Settings +/* ************************************************************************** */ +#if UIP_CONF_IPV6_RPL + +#define UIP_CONF_ROUTER 1 +#define UIP_CONF_ND6_SEND_RA 0 +#define UIP_CONF_ND6_REACHABLE_TIME 600000 +#define UIP_CONF_ND6_RETRANS_TIMER 10000 + +/* For slow slip connections, to prevent buffer overruns */ +//#define UIP_CONF_RECEIVE_WINDOW 300 +#undef UIP_CONF_FWCACHE_SIZE +#define UIP_CONF_FWCACHE_SIZE 30 +#define UIP_CONF_BROADCAST 1 +#define UIP_ARCH_IPCHKSUM 1 +#define UIP_CONF_PINGADDRCONF 0 +#define UIP_CONF_LOGGING 0 + +#endif /* RPL */ + +#define CCIF +#define CLIF +#ifndef CC_CONF_INLINE +#define CC_CONF_INLINE inline +#endif + +/* include the project config */ +/* PROJECT_CONF_H might be defined in the project Makefile */ +#ifdef PROJECT_CONF_H +#include PROJECT_CONF_H +#endif + +#endif /* CONTIKI_CONF_H_ */ diff --git a/platform/osd-merkur-256/contiki-main.c b/platform/osd-merkur-256/contiki-main.c new file mode 100644 index 000000000..420871524 --- /dev/null +++ b/platform/osd-merkur-256/contiki-main.c @@ -0,0 +1,593 @@ +/* + * Copyright (c) 2006, Technical University of Munich + * 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. + * + */ +#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args) + +#define ANNOUNCE_BOOT 1 //adds about 600 bytes to program size +#if ANNOUNCE_BOOT +#define PRINTA(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTA(...) +#endif + +#define DEBUG 0 +#if DEBUG +#define PRINTD(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTD(...) +#endif + +#include +#include +#include +#include +#include +#include + +#include "loader/symbols-def.h" +#include "loader/symtab.h" + +#include "params.h" +#include "radio/rf230bb/rf230bb.h" +#include "net/mac/frame802154.h" +#include "net/mac/framer-802154.h" +#include "net/ipv6/sicslowpan.h" + +#include "contiki.h" +#include "contiki-net.h" +#include "contiki-lib.h" + +#include "dev/rs232.h" +#include "dev/serial-line.h" +#include "dev/slip.h" + +#if AVR_WEBSERVER +#include "httpd-fs.h" +#include "httpd-cgi.h" +#endif + +#ifdef COFFEE_FILES +#include "cfs/cfs.h" +#include "cfs/cfs-coffee.h" +#endif + +#if UIP_CONF_ROUTER&&0 +#include "net/routing/rimeroute.h" +#include "net/rime/rime-udp.h" +#endif + +#include "net/rime/rime.h" + +/* Track interrupt flow through mac, rdc and radio driver */ +//#define DEBUGFLOWSIZE 32 +#if DEBUGFLOWSIZE +uint8_t debugflowsize,debugflow[DEBUGFLOWSIZE]; +#define DEBUGFLOW(c) if (debugflowsize<(DEBUGFLOWSIZE-1)) debugflow[debugflowsize++]=c +#else +#define DEBUGFLOW(c) +#endif + +/* Get periodic prints from idle loop, from clock seconds or rtimer interrupts */ +/* Use of rtimer will conflict with other rtimer interrupts such as contikimac radio cycling */ +/* STAMPS will print ENERGEST outputs if that is enabled. */ +#define PERIODICPRINTS 1 +#if PERIODICPRINTS +//#define PINGS 64 +#define ROUTES 600 +#define STAMPS 60 +#define STACKMONITOR 1024 +uint32_t clocktime; +#define TESTRTIMER 0 +#if TESTRTIMER +uint8_t rtimerflag=1; +struct rtimer rt; +void rtimercycle(void) {rtimerflag=1;} +#endif +#endif + +//uint16_t ledtimer; + +/*-------------------------------------------------------------------------*/ +/*----------------------Configuration of the .elf file---------------------*/ +#if 1 +/* The proper way to set the signature is */ +#include +#else +/* Older avr-gcc's may not define the needed SIGNATURE bytes. Do it manually if you get an error */ +typedef struct {const unsigned char B2;const unsigned char B1;const unsigned char B0;} __signature_t; +#define SIGNATURE __signature_t __signature __attribute__((section (".signature"))) +SIGNATURE = { + .B2 = 0x02,//SIGNATURE_2, //ATMEGA256rfr2 + .B1 = 0xA8,//SIGNATURE_1, //256KB flash + .B0 = 0x1E,//SIGNATURE_0, //Atmel +}; +#endif + +#if 1 +/* JTAG+SPI enabled, External osc 1kck4ms1 , Boot 4096 words @ $1F000, TXC1K+4,1msec delay, Brownout 1.9 volts */ +FUSES ={.low = 0xF6, .high = 0x98, .extended = 0xfe,}; +#define BOOTLOADER_START = 0x3E000 +#else +/* JTAG+SPI, Boot 4096 words @ $F000, Internal oscillator, startup 6 CK +0 ms, Brownout 1.8 volts */ +FUSES ={.low = 0xC2, .high = 0x99, .extended = 0xfe,}; +#endif + +#include "lib/sensors.h" +#include "dev/button-sensor.h" +#include "dev/battery-sensor.h" +#include "dev/pir-sensor.h" +SENSORS(&button_sensor, &pir_sensor); + +uint8_t +rng_get_uint8(void) { +#if 1 + /* Upper two RSSI reg bits (RND_VALUE) are random in rf231 */ + uint8_t j; + j = (PHY_RSSI&0xc0) + ((PHY_RSSI>>2)&0x30) + ((PHY_RSSI>>4)&0x0c) + ((PHY_RSSI>>6)&0x03); +#else +/* Get a pseudo random number using the ADC */ + uint8_t i,j; + ADCSRA=1<>4); +} +/*-------------------------Low level initialization------------------------*/ +/*------Done in a subroutine to keep main routine stack usage small--------*/ +void initialize(void) +{ + watchdog_init(); + watchdog_start(); + + /* Generic or slip connection on uart0 */ + rs232_init(RS232_PORT_0, USART_BAUD_38400,USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8); + + /* Second rs232 port for debugging or slip alternative */ +// rs232_init(RS232_PORT_1, USART_BAUD_57600,USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8); + + /* Redirect stdout */ + rs232_redirect_stdout(RS232_PORT_0); + + clock_init(); + + if(MCUSR & (1< +//#define delay_us( us ) ( _delay_loop_2(1+(us*F_CPU)/4000000UL) ) +// delay_us(50000); + } + clock_init(); +} +#endif + + PRINTA("\n*******Booting %s*******\n",CONTIKI_VERSION_STRING); + +/* rtimers needed for radio cycling */ + rtimer_init(); + + /* Initialize process subsystem */ + process_init(); + + /* etimers must be started before ctimer_init */ + process_start(&etimer_process, NULL); + ctimer_init(); + + /* Start radio and radio receive process */ + NETSTACK_RADIO.init(); + +/* Get a random seed for the 802.15.4 packet sequence number. + * Some layers will ignore duplicates found in a history (e.g. Contikimac) + * causing the initial packets to be ignored after a short-cycle restart. + */ + random_init(rng_get_uint8()); + + /* Set addresses BEFORE starting tcpip process */ + + linkaddr_t addr; + + if (params_get_eui64(addr.u8)) { + PRINTA("Random EUI64 address generated\n"); + } + +#if NETSTACK_CONF_WITH_IPV6 + memcpy(&uip_lladdr.addr, &addr.u8, sizeof(linkaddr_t)); +#elif WITH_NODE_ID + node_id=get_panaddr_from_eeprom(); + addr.u8[1]=node_id&0xff; + addr.u8[0]=(node_id&0xff00)>>8; + PRINTA("Node ID from eeprom: %X\n",node_id); +#endif + linkaddr_set_node_addr(&addr); + + PRINTA("Panid:%x\n", params_get_panid()); +// framer_802154_set_panid(params_get_panid()); + rf230_set_pan_addr(params_get_panid(),params_get_panaddr(),(uint8_t *)&addr.u8); + rf230_set_channel(params_get_channel()); + rf230_set_txpower(params_get_txpower()); + +#if NETSTACK_CONF_WITH_IPV6 + PRINTA("EUI-64 MAC: %x-%x-%x-%x-%x-%x-%x-%x\n",addr.u8[0],addr.u8[1],addr.u8[2],addr.u8[3],addr.u8[4],addr.u8[5],addr.u8[6],addr.u8[7]); +#else + PRINTA("MAC address "); + uint8_t i; + for (i=sizeof(linkaddr_t); i>0; i--){ + PRINTA("%x:",addr.u8[i-1]); + } + PRINTA("\n"); +#endif + + /* Initialize stack protocols */ + queuebuf_init(); + NETSTACK_RDC.init(); + NETSTACK_MAC.init(); + NETSTACK_NETWORK.init(); + +#if ANNOUNCE_BOOT + PRINTA("%s %s, channel %u , check rate %u Hz tx power %u\n",NETSTACK_MAC.name, NETSTACK_RDC.name, rf230_get_channel(), + CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1:NETSTACK_RDC.channel_check_interval()), + rf230_get_txpower()); +#if UIP_CONF_IPV6_RPL + PRINTA("RPL Enabled\n"); +#endif +#if UIP_CONF_ROUTER + PRINTA("Routing Enabled\n"); +#endif + +#endif /* ANNOUNCE_BOOT */ + +#if NETSTACK_CONF_WITH_IPV6 || NETSTACK_CONF_WITH_IPV4 + process_start(&tcpip_process, NULL); +#endif + + process_start(&sensors_process, NULL); + + /* Autostart other processes */ + autostart_start(autostart_processes); + + /*---If using coffee file system create initial web content if necessary---*/ +#if COFFEE_FILES + int fa = cfs_open( "/index.html", CFS_READ); + if (fa<0) { //Make some default web content + PRINTA("No index.html file found, creating upload.html!\n"); + PRINTA("Formatting FLASH file system for coffee..."); + cfs_coffee_format(); + PRINTA("Done!\n"); + fa = cfs_open( "/index.html", CFS_WRITE); + int r = cfs_write(fa, &"It works!", 9); + if (r<0) PRINTA("Can''t create /index.html!\n"); + cfs_close(fa); +// fa = cfs_open("upload.html"), CFW_WRITE); +//
+ } +#endif /* COFFEE_FILES */ + +/* Add addresses for testing */ +#if 0 +{ + uip_ip6addr_t ipaddr; + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); +// uip_ds6_prefix_add(&ipaddr,64,0); +} +#endif + +/*--------------------------Announce the configuration---------------------*/ +#if ANNOUNCE_BOOT +#if AVR_WEBSERVER +{ uint8_t i; + char buf[80]; + unsigned int size; + + for (i=0;i>10); +#elif COFFEE_FILES==3 + PRINTA(".%s online with static %u byte program memory file system\n",buf,size); +#elif COFFEE_FILES==4 + PRINTA(".%s online with dynamic %u KB program memory file system\n",buf,size>>10); +#endif /* COFFEE_FILES */ +} +#else + PRINTA("Online\n"); +#endif +#endif /* ANNOUNCE_BOOT */ + +} + +#if ROUTES && NETSTACK_CONF_WITH_IPV6 +static void +ipaddr_add(const uip_ipaddr_t *addr) +{ + uint16_t a; + int8_t i, f; + for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) { + a = (addr->u8[i] << 8) + addr->u8[i + 1]; + if(a == 0 && f >= 0) { + if(f++ == 0) PRINTF("::"); + } else { + if(f > 0) { + f = -1; + } else if(i > 0) { + PRINTF(":"); + } + PRINTF("%x",a); + } + } +} +#endif + +/*-------------------------------------------------------------------------*/ +/*------------------------- Main Scheduler loop----------------------------*/ +/*-------------------------------------------------------------------------*/ +int +main(void) +{ +#if NETSTACK_CONF_WITH_IPV6 + uip_ds6_nbr_t *nbr; +#endif /* NETSTACK_CONF_WITH_IPV6 */ + initialize(); + + while(1) { + process_run(); + watchdog_periodic(); + +#if 0 + /* Turn off LED after a while */ + if (ledtimer) { + if (--ledtimer==0) { + } + } +#endif + +#if 0 +/* Various entry points for debugging in the AVR Studio simulator. + * Set as next statement and step into the routine. + */ + NETSTACK_RADIO.send(packetbuf_hdrptr(), 42); + process_poll(&rf230_process); + packetbuf_clear(); + len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE); + packetbuf_set_datalen(42); + NETSTACK_RDC.input(); +#endif + +#if 0 +/* Clock.c can trigger a periodic PLL calibration in the RF230BB driver. + * This can show when that happens. + */ + extern uint8_t rf230_calibrated; + if (rf230_calibrated) { + PRINTD("\nRF230 calibrated!\n"); + rf230_calibrated=0; + } +#endif + +/* Set DEBUGFLOWSIZE in contiki-conf.h to track path through MAC, RDC, and RADIO */ +#if DEBUGFLOWSIZE + if (debugflowsize) { + debugflow[debugflowsize]=0; + PRINTF("%s",debugflow); + debugflowsize=0; + } +#endif + +#if PERIODICPRINTS +#if TESTRTIMER +/* Timeout can be increased up to 8 seconds maximum. + * A one second cycle is convenient for triggering the various debug printouts. + * The triggers are staggered to avoid printing everything at once. + */ + if (rtimerflag) { + rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL); + rtimerflag=0; +#else + if (clocktime!=clock_seconds()) { + clocktime=clock_seconds(); +#endif + +#if STAMPS +if ((clocktime%STAMPS)==0) { +#if ENERGEST_CONF_ON +#include "lib/print-stats.h" + print_stats(); +#elif RADIOSTATS +extern volatile unsigned long radioontime; + PRINTF("%u(%u)s\n",clocktime,radioontime); +#else + PRINTF("%us\n",clocktime); +#endif + +} +#endif +#if TESTRTIMER + clocktime+=1; +#endif + +#if PINGS && NETSTACK_CONF_WITH_IPV6 +extern void raven_ping6(void); +if ((clocktime%PINGS)==1) { + PRINTF("**Ping\n"); + raven_ping6(); +} +#endif + +#if ROUTES && NETSTACK_CONF_WITH_IPV6 +if ((clocktime%ROUTES)==2) { + +extern uip_ds6_netif_t uip_ds6_if; + + uint8_t i,j=0; + PRINTF("\nAddresses [%u max]\n",UIP_DS6_ADDR_NB); + for (i=0;iipaddr); + PRINTF("\n"); + j=0; + } + + if (j) PRINTF(" "); + PRINTF("\nRoutes [%u max]\n",UIP_DS6_ROUTE_NB); + { + uip_ds6_route_t *r; + j = 1; + for(r = uip_ds6_route_head(); + r != NULL; + r = uip_ds6_route_next(r)) { + ipaddr_add(&r->ipaddr); + PRINTF("/%u (via ", r->length); + ipaddr_add(uip_ds6_route_nexthop(r)); + PRINTF(") %lus\n", r->state.lifetime); + j = 0; + } + } + if (j) PRINTF(" "); + PRINTF("\n---------\n"); + +} +#endif + +#if STACKMONITOR +if ((clocktime%STACKMONITOR)==3) { + extern uint16_t __bss_end; + uint16_t p=(uint16_t)&__bss_end; + do { + if (*(uint16_t *)p != 0x4242) { + PRINTF("Never-used stack > %d bytes\n",p-(uint16_t)&__bss_end); + break; + } + p+=10; + } while (p +*/ + + + // WARNING : Blink function is disabled on the core leds.c file + +#include "contiki.h" +#include "dev/leds.h" +#include "leds-arch.h" + +/*---------------------------------------------------------------------------*/ +void +leds_arch_init(void) +{ +DDRE |= (1< + +#define NUM_DIGITAL_PINS 15 +#define NUM_ANALOG_INPUTS 6 +#define analogInputToDigitalPin(p) ((p < NUM_ANALOG_INPUTS) ? (p) + NUM_DIGITAL_PINS : -1) +#define digitalPinHasPWM(p) ((p) == 2 ||(p) == 3 ||(p) == 4 ||(p) == 14 ) + +// Dev board specific defines: RF RX and TX LEDs: +#define RXLED_DDR DDRB +#define RXLED_PORT PORTB +#define RXLED_POS PB6 + +#define TXLED_DDR DDRB +#define TXLED_PORT PORTB +#define TXLED_POS PB7 + +const static uint8_t SS = 10; +const static uint8_t MOSI = 11; +const static uint8_t MISO = 13; +const static uint8_t SCK = 12; + +const static uint8_t SDA = 9; +const static uint8_t SCL = 8; +const static uint8_t LED = 4; +const static uint8_t LED1 = 4; +const static uint8_t LED2 = 5; + +const static uint8_t A0 = 7; +const static uint8_t A1 = 6; +const static uint8_t A2 = 5; +const static uint8_t A3 = 4; +const static uint8_t A4 = 0; +const static uint8_t A5 = 1; + +// A majority of the pins are NOT PCINTs, SO BE WARNED (i.e. you cannot use them as receive pins) +// Only pins available for RECEIVE (TRANSMIT can be on any pin): +// Pins: 10, 11, 12, 13, 14 + +#define digitalPinToPCICR(p) ( (((p) >= 10) && ((p) <= 14)) || ? (&PCICR) : ((uint8_t *)0) ) + +#define digitalPinToPCICRbit(p) ( 0 ) + +#define digitalPinToPCMSK(p) ( (((p) >= 10) && ((p) <= 14)) ? (&PCMSK0) : ((uint8_t *)0) ) + +#define digitalPinToPCMSKbit(p) ( ((p) == 10) ? 6 : \ + ( ((p) == 11) ? 5 : \ + ( ((p) == 12) ? 1 : \ + ( ((p) == 13) ? 3 : \ + ( ((p) == 14) ? 7 : \ + 0 ) ) ) ) ) + +#ifdef ARDUINO_MAIN + +const uint16_t PROGMEM port_to_mode_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t)&DDRB, + NOT_A_PORT, + (uint16_t)&DDRD, + (uint16_t)&DDRE, + (uint16_t)&DDRF, + (uint16_t)&DDRG, + NOT_A_PORT, + NOT_A_PORT, + NOT_A_PORT, + NOT_A_PORT, + NOT_A_PORT, +}; + +const uint16_t PROGMEM port_to_output_PGM[] = { + NOT_A_PORT, + NOT_A_PORT, + (uint16_t)&PORTB, + NOT_A_PORT, + (uint16_t)&PORTD, + (uint16_t)&PORTE, + (uint16_t)&PORTF, + (uint16_t)&PORTG, + NOT_A_PORT, + NOT_A_PORT, + NOT_A_PORT, + NOT_A_PORT, + NOT_A_PORT, +}; + +const uint16_t PROGMEM port_to_input_PGM[] = { + NOT_A_PIN, + NOT_A_PIN, + NOT_A_PIN, + (uint16_t)&PINC, + (uint16_t)&PIND, + (uint16_t)&PINE, + (uint16_t)&PINF, + (uint16_t)&PING, + NOT_A_PIN, + NOT_A_PIN, + NOT_A_PIN, + NOT_A_PIN, + NOT_A_PIN, +}; + +const uint8_t PROGMEM digital_pin_to_port_PGM[] = { + // PORTLIST + // ------------------------------------------- + PE , // PE 1 ** 0 ** D0 / USART0_TX + PE , // PE 0 ** 1 ** D1 / USART0_RX + PE , // PE 3 ** 2 ** D2 / PWM + PE , // PE 4 ** 3 ** D3 / PWM + PE , // PE 5 ** 4 ** D4 / PWM / LED1 / LED + PE , // PE 6 ** 5 ** D5 / LED2 + PD , // PD 3 ** 6 ** D6 / USART1_TX + PD , // PD 2 ** 7 ** D7 / USART1_RX + PD , // PD 0 ** 8 ** D8 / I2C_SCL + PD , // PD 1 ** 9 ** D9 / I2C_SDA + PB , // PB 0 ** 10 ** D10 / SPI_SSN + PB , // PB 2 ** 11 ** D11 / SPI_MOSI + PB , // PB 1 ** 12 ** D12 / SPI_SCK + PB , // PB 3 ** 13 ** D13 / SPI_MISO + PB , // PB 4 ** 14 ** D14 / PWM + PF , // PF 7 ** 15 ** A0 / D15 + PF , // PF 6 ** 16 ** A1 / D16 + PF , // PF 5 ** 17 ** A2 / D17 + PF , // PF 4 ** 18 ** A3 / D18 + PF , // PF 0 ** 19 ** A4 / D19 + PF , // PF 1 ** 20 ** A5 / D20 +// PB , // PB 6 ** 34 ** D34 / LED1 / LED / PWM +// PB , // PB 7 ** 35 ** D35 / LED2 / PWM +// PE , // PE 2 ** 2 ** D2 +// PE , // PE 7 ** 7 ** D7 +// PB , // PB 5 ** 8 ** D8 / PWM +// PG , // PG 0 ** 16 ** D16 +// PG , // PG 1 ** 17 ** D17 +// PG , // PG 2 ** 18 ** D18 +// PG , // PG 5 ** 19 ** D19 / PWM +// PD , // PD 4 ** 22 ** D22 +// PD , // PD 5 ** 23 ** D23 +// PD , // PD 6 ** 24 ** D24 +// PD , // PD 7 ** 25 ** D25 +// PF , // PF 2 ** 28 ** A2 / D28 +// PF , // PF 3 ** 29 ** A3 / D29 +}; + +const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[] = { + // PIN IN PORT + // ------------------------------------------- + _BV( 1 ) , // PE 1 ** 0 ** USART0_TX + _BV( 0 ) , // PE 0 ** 1 ** USART0_RX + _BV( 3 ) , // PE 3 ** 2 ** D3 / PWM + _BV( 4 ) , // PE 4 ** 3 ** D4 / PWM + _BV( 5 ) , // PE 5 ** 4 ** D5 / PWM + _BV( 6 ) , // PE 6 ** 5 ** D6 + _BV( 3 ) , // PD 3 ** 6 ** D21 / USART1_TX + _BV( 2 ) , // PD 2 ** 7 ** D20 / USART1_RX + _BV( 0 ) , // PD 0 ** 8 ** D15 / I2C_SCL + _BV( 1 ) , // PD 1 ** 9 ** D14 / I2C_SDA + _BV( 0 ) , // PB 0 ** 10 ** D10 / SPI_SSN + _BV( 2 ) , // PB 2 ** 11 ** D11 / SPI_MOSI + _BV( 1 ) , // PB 1 ** 12 ** D13 / SPI_SCK + _BV( 3 ) , // PB 3 ** 13 ** D12 / SPI_MISO + _BV( 4 ) , // PB 4 ** 14 ** D9 / PWM + _BV( 7 ) , // PF 7 ** 15 ** A0 / D33 + _BV( 6 ) , // PF 6 ** 16 ** A1 / D32 + _BV( 5 ) , // PF 5 ** 17 ** A2 / D31 + _BV( 4 ) , // PF 4 ** 18 ** A3 / D30 + _BV( 0 ) , // PF 0 ** 19 ** A4 / D26 + _BV( 1 ) , // PF 1 ** 20 ** A5 / D27 +// _BV( 2 ) , // PE 2 ** 2 ** D2 +// _BV( 7 ) , // PE 7 ** 7 ** D7 +// _BV( 5 ) , // PB 5 ** 8 ** D8 / PWM +// _BV( 0 ) , // PG 0 ** 16 ** D16 +// _BV( 1 ) , // PG 1 ** 17 ** D17 +// _BV( 2 ) , // PG 2 ** 18 ** D18 +// _BV( 5 ) , // PG 5 ** 19 ** D19 / PWM +// _BV( 4 ) , // PD 4 ** 22 ** D22 +// _BV( 5 ) , // PD 5 ** 23 ** D23 +// _BV( 6 ) , // PD 6 ** 24 ** D24 +// _BV( 7 ) , // PD 7 ** 25 ** D25 +// _BV( 2 ) , // PF 2 ** 28 ** A2 / D28 +// _BV( 3 ) , // PF 3 ** 29 ** A3 / D29 +// _BV( 6 ) , // PB 6 ** 34 ** D34 / LED1 / LED / PWM +// _BV( 7 ) , // PB 7 ** 35 ** D35 / LED2 / PWM +}; + +#endif + +#endif diff --git a/platform/osd-merkur-256/node-id.c b/platform/osd-merkur-256/node-id.c new file mode 100644 index 000000000..8698b1855 --- /dev/null +++ b/platform/osd-merkur-256/node-id.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * $Id: node-id.c,v 1.1 2007/03/23 09:59:08 nifi Exp $ + */ + +/** + * \file + * Utility to store a node id in the external flash + * \author + * Adam Dunkels + */ + +#include "node-id.h" +#include "contiki-conf.h" +#include "dev/xmem.h" + +unsigned short node_id = 0; + +/*---------------------------------------------------------------------------*/ +void +node_id_restore(void) +{ +/* todo */ +/* + unsigned char buf[4]; + xmem_pread(buf, 4, NODE_ID_XMEM_OFFSET); + if(buf[0] == 0xad && + buf[1] == 0xde) { + node_id = (buf[2] << 8) | buf[3]; + } else { + node_id = 0; + } +*/ + node_id = 0; +} +/*---------------------------------------------------------------------------*/ +void +node_id_burn(unsigned short id) +{ +/* todo */ +/* + unsigned char buf[4]; + buf[0] = 0xad; + buf[1] = 0xde; + buf[2] = id >> 8; + buf[3] = id & 0xff; + xmem_erase(XMEM_ERASE_UNIT_SIZE, NODE_ID_XMEM_OFFSET); + xmem_pwrite(buf, 4, NODE_ID_XMEM_OFFSET); +*/ +} +/*---------------------------------------------------------------------------*/ diff --git a/platform/osd-merkur-256/node-id.h b/platform/osd-merkur-256/node-id.h new file mode 100644 index 000000000..592379fc9 --- /dev/null +++ b/platform/osd-merkur-256/node-id.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + * Author: Adam Dunkels + * + * $Id: node-id.h,v 1.1 2007/03/23 09:59:08 nifi Exp $ + */ + +#ifndef __NODE_ID_H__ +#define __NODE_ID_H__ + +void node_id_restore(void); +void node_id_burn(unsigned short node_id); + +extern unsigned short node_id; + +#endif /* __NODE_ID_H__ */ diff --git a/platform/osd-merkur-256/params.c b/platform/osd-merkur-256/params.c new file mode 100644 index 000000000..4b0252387 --- /dev/null +++ b/platform/osd-merkur-256/params.c @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2011, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +#define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args) + +#define DEBUG 1 +#if DEBUG +#define PRINTD(FORMAT,args...) printf_P(PSTR(FORMAT),##args) +#else +#define PRINTD(...) +#endif + +#include "contiki.h" +#include +#include +#include +#include + +#if AVR_WEBSERVER +//#include "httpd-fs.h" +//#include "httpd-cgi.h" +#endif + +#include "contiki-net.h" +#include "params.h" + +#if WITH_NODE_ID +uint16_t node_id; +#endif + +#if CONTIKI_CONF_RANDOM_MAC +extern uint8_t rng_get_uint8(void); +static void +generate_new_eui64(uint8_t eui64[8]) { + eui64[0] = 0x02; + eui64[1] = rng_get_uint8(); + eui64[2] = rng_get_uint8(); + eui64[3] = 0xFF; + eui64[4] = 0xFE; + eui64[5] = rng_get_uint8(); + eui64[6] = rng_get_uint8(); + eui64[7] = rng_get_uint8(); +} +#endif + +#if AVR_WEBSERVER +/* Webserver builds can set these in httpd-fsdata.c via makefsdata.h */ +extern uint8_t default_mac_address[8]; +extern uint8_t default_server_name[16]; +extern uint8_t default_domain_name[30]; +#else +const uint8_t default_mac_address[8] PROGMEM = PARAMS_EUI64ADDR; +const uint8_t default_server_name[] PROGMEM = PARAMS_SERVERNAME; +const uint8_t default_domain_name[] PROGMEM = PARAMS_DOMAINNAME; +#endif + +#if PARAMETER_STORAGE==0 +/* 0 Hard coded, minmal program and eeprom usage. */ + +extern uint8_t bootloader_get_mac(uint8_t); + +uint8_t +params_get_eui64(uint8_t *eui64) { +#if CONTIKI_CONF_RANDOM_MAC + PRINTD("Generating random EUI64 MAC\n"); + generate_new_eui64(eui64); + return 1; +#else + uint8_t i; +#if BOOTLOADER_GET_MAC + for (i=0;i 26)) x[1]=x[0]; +/* Do exclusive or test on the two values read */ + if((uint8_t)x[0]!=(uint8_t)~x[1]) {//~x[1] can promote comparison to 16 bit +/* Verification fails, rewrite everything */ + uint8_t i,buffer[32]; + PRINTD("EEPROM is corrupt, rewriting with defaults.\n"); +#if CONTIKI_CONF_RANDOM_MAC + PRINTD("Generating random EUI64 MAC\n"); + generate_new_eui64(&buffer); + randomeui64=1; +#else + for (i=0;iSet EEPROM RF channel to %d\n",x); + } + } + return x; +} +uint8_t +params_get_eui64(uint8_t *eui64) { + size_t size = sizeof(linkaddr_t); + if(settings_get(SETTINGS_KEY_EUI64, 0, (unsigned char*)eui64, &size) == SETTINGS_STATUS_OK) { + PRINTD("<-Get EUI64 MAC\n"); + return 0; + } +#if CONTIKI_CONF_RANDOM_MAC + PRINTD("Generating random EUI64 MAC\n"); + generate_new_eui64(eui64); +#else + {uint8_t i;for (i=0;i<8;i++) eui64[i] = pgm_read_byte_near(default_mac_address+i);} //test this +#endif + if (settings_add(SETTINGS_KEY_EUI64,(unsigned char*)eui64,8) == SETTINGS_STATUS_OK) { + PRINTD("->Set EEPROM MAC address\n"); + } +#if CONTIKI_CONF_RANDOM_MAC + return 1; +#else + return 0; +#endif +} +uint16_t +params_get_panid(void) { + uint16_t x; + size_t size = 2; + if (settings_get(SETTINGS_KEY_PAN_ID, 0,(unsigned char*)&x, &size) == SETTINGS_STATUS_OK) { + PRINTD("<-Get PAN ID of %04x\n",x); + } else { + x=IEEE802154_PANID; + if (settings_add_uint16(SETTINGS_KEY_PAN_ID,x)==SETTINGS_STATUS_OK) { + PRINTD("->Set EEPROM PAN ID to %04x\n",x); + } + } + return x; +} +uint16_t +params_get_panaddr(void) { + uint16_t x; + size_t size = 2; + if (settings_get(SETTINGS_KEY_PAN_ADDR, 0,(unsigned char*)&x, &size) == SETTINGS_STATUS_OK) { + PRINTD("<-Get PAN address of %04x\n",x); + } else { + x=PARAMS_PANADDR; + if (settings_add_uint16(SETTINGS_KEY_PAN_ADDR,x)==SETTINGS_STATUS_OK) { + PRINTD("->Set EEPROM PAN address to %04x\n",x); + } + } + return x; +} +uint8_t +params_get_txpower(void) { + uint8_t x; + size_t size = 1; + if (settings_get(SETTINGS_KEY_TXPOWER, 0,(unsigned char*)&x, &size) == SETTINGS_STATUS_OK) { + PRINTD("<-Get tx power of %d (0=max)\n",x); + } else { + x=PARAMS_TXPOWER; + if (settings_add_uint8(SETTINGS_KEY_TXPOWER,x)==SETTINGS_STATUS_OK) { + PRINTD("->Set EEPROM tx power of %d (0=max)\n",x); + } + } + return x; +} +#endif /* CONTIKI_CONF_SETTINGS_MANAGER */ diff --git a/platform/osd-merkur-256/params.h b/platform/osd-merkur-256/params.h new file mode 100644 index 000000000..7b074c198 --- /dev/null +++ b/platform/osd-merkur-256/params.h @@ -0,0 +1,104 @@ +#ifndef PARAMS_H_ +#define PARAMS_H_ +/* PARAMETER_STORAGE = + * 0 Hard coded, minmal program and eeprom usage. + * 1 Stored in fixed eeprom locations, rewritten from flash if corrupt. + * This allows parameter changes using a hardware programmer or custom application code. + * Corruption test is based on channel verify so get the channel before anything else! + * 2 Obtained from eeprom using the general settings manager and read from program flash if not present. + * Useful for for testing builds without wearing out flash memory. + * 3 Obtained from eeprom using the settings manager and rewritten from flash if not present. + * This ensures all parameters are present in upper eeprom flash. + * + * Note the parameters in this file can be changed without forcing a complete rebuild. + */ +// default settings +#define CHANNEL_802_15_4 25 // default frequency (11-26) + +// end default settings + +#define CONTIKI_CONF_RANDOM_MAC 0 //adds 78 bytes +#define CONTIKI_CONF_SETTINGS_MANAGER 0 //adds 1696 bytes +#define BOOTLOADER_GET_MAC 0x0003ff80 // get mac from bootloader + +#if CONTIKI_CONF_SETTINGS_MANAGER +//#define PARAMETER_STORAGE 2 +#define PARAMETER_STORAGE 2 +#else +#define PARAMETER_STORAGE 0 // 0:get mac from booloader (see above) +#endif + +/* Include settings.h, then dummy out the write routines */ +#include "settings.h" +#if PARAMETER_STORAGE==2 +#define settings_add(...) 0 +#define settings_add_uint8(...) 0 +#define settings_add_uint16(...) 0 +#endif + +#if AVR_WEBSERVER +/* Webserver builds can set some defaults in httpd-fsdata.c via makefsdata.h */ +extern uint8_t eemem_mac_address[8]; +extern uint8_t eemem_server_name[16]; +extern uint8_t eemem_domain_name[30]; +#endif +#ifdef SERVER_NAME +#define PARAMS_SERVERNAME SERVER_NAME +#else +#define PARAMS_SERVERNAME "ATMEGA256rfr2" +#endif +#ifdef DOMAIN_NAME +#define PARAMS_DOMAINNAME DOMAIN_NAME +#else +#define PARAMS_DOMAINNAME "localhost" +#endif +#ifdef NODE_ID +#define PARAMS_NODEID NODE_ID +#else +#define PARAMS_NODEID 0 +#endif +#ifdef IEEE802154_PANADDR +#define PARAMS_PANADDR IEEE802154_PANADDR +#else +#define PARAMS_PANADDR 0 +#endif +#ifdef RF230_MAX_TX_POWER +#define PARAMS_TXPOWER RF230_MAX_TX_POWER +#else +#define PARAMS_TXPOWER 0 +#endif +#ifdef EUI64_ADDRESS +#define PARAMS_EUI64ADDR EUI64_ADDRESS +#else +/* This form of of EUI64 mac allows full 6LoWPAN header compression from mac address */ +#if UIP_CONF_LL_802154 +//#define PARAMS_EUI64ADDR {0x02, 0xNN, 0xNN, 0xNN, 0xNN, 0xNN, 0xNN, 0xNN} +//#define PARAMS_EUI64ADDR {0x00, 0x21, 0x2e, 0xff, 0xff, 0x00, 0x1E, 0xFB} +#define PARAMS_EUI64ADDR {0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x11} +#else +//#define PARAMS_EUI64ADDR {0x02, 0xNN, 0xNN, 0xff, 0xfe, 0xNN, 0xNN, 0xNN} +#define PARAMS_EUI64ADDR {0x00, 0x00, 0x00, 0xff, 0xfe, 0x00, 0x00, 0x03} +#endif +/* This form of of EUI64 mac allows 16 bit 6LoWPAN header compression on multihops */ +//#define PARAMS_EUI64ADDR {0x02, 0x00, 0x00, 0xff, 0xfe, 0x00, 0xNN, 0xNN} +#endif + +uint8_t params_get_eui64(uint8_t *eui64); +#if PARAMETER_STORAGE==0 +/* Hard coded program flash parameters */ +#define params_get_servername(...) +#define params_get_nodeid(...) PARAMS_NODEID +#define params_get_channel(...) CHANNEL_802_15_4 +#define params_get_panid(...) IEEE802154_PANID +#define params_get_panaddr(...) PARAMS_PANADDR +#define params_get_txpower(...) PARAMS_TXPOWER +#else +/* Parameters stored in eeprom */ +uint16_t params_get_nodeid(void); +uint8_t params_get_channel(void); +uint16_t params_get_panid(void); +uint16_t params_get_panaddr(void); +uint8_t params_get_txpower(void); +#endif + +#endif /* PARAMS_H_ */ diff --git a/platform/osd-merkur-256/slip_uart0.c b/platform/osd-merkur-256/slip_uart0.c new file mode 100644 index 000000000..edff55385 --- /dev/null +++ b/platform/osd-merkur-256/slip_uart0.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2010, University of Colombo School of Computing + * 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 + * Machine dependent AVR SLIP routines for UART0. + * \author + * Kasun Hewage + */ + +#include +#include "contiki.h" +#include "dev/rs232.h" +#include "slip.h" + +/*---------------------------------------------------------------------------*/ +static int +slip_putchar(char c, FILE *stream) +{ +#define SLIP_END 0300 + static char debug_frame = 0; + + if (!debug_frame) { /* Start of debug output */ + slip_arch_writeb(SLIP_END); + slip_arch_writeb('\r'); /* Type debug line == '\r' */ + debug_frame = 1; + } + + slip_arch_writeb((unsigned char)c); + + /* + * Line buffered output, a newline marks the end of debug output and + * implicitly flushes debug output. + */ + if (c == '\n') { + slip_arch_writeb(SLIP_END); + debug_frame = 0; + } + + return c; +} +/*---------------------------------------------------------------------------*/ +static FILE slip_stdout = FDEV_SETUP_STREAM(slip_putchar, NULL, + _FDEV_SETUP_WRITE); +/*---------------------------------------------------------------------------*/ +void +slip_arch_init(unsigned long ubr) +{ + rs232_set_input(SLIP_PORT, slip_input_byte); + stdout = &slip_stdout; +} +/*---------------------------------------------------------------------------*/ +/* + XXX: + Currently, the following function is in cpu/avr/dev/rs232.c file. this + should be moved to here from there hence this is a platform specific slip + related function. +void +slip_arch_writeb(unsigned char c) +{ + rs232_send(RS232_PORT_0, c); +} +*/ diff --git a/platform/osd-merkur/dev/LED_Strip_Suli b/platform/osd-merkur/dev/LED_Strip_Suli deleted file mode 160000 index 56b7ce6c3..000000000 --- a/platform/osd-merkur/dev/LED_Strip_Suli +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 56b7ce6c3227aeac131b59e39829c4991e7caefd diff --git a/platform/osd-merkur/dev/old/Printable.h b/platform/osd-merkur/dev/old/Printable.h deleted file mode 100644 index d03c9af62..000000000 --- a/platform/osd-merkur/dev/old/Printable.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - Printable.h - Interface class that allows printing of complex types - Copyright (c) 2011 Adrian McEwen. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef Printable_h -#define Printable_h - -#include - -class Print; - -/** The Printable class provides a way for new classes to allow themselves to be printed. - By deriving from Printable and implementing the printTo method, it will then be possible - for users to print out instances of this class by passing them into the usual - Print::print and Print::println methods. -*/ - -class Printable -{ - public: - virtual size_t printTo(Print& p) const = 0; -}; - -#endif - diff --git a/platform/osd-merkur/dev/old/Stream.cpp b/platform/osd-merkur/dev/old/Stream.cpp deleted file mode 100644 index aafb7fcf9..000000000 --- a/platform/osd-merkur/dev/old/Stream.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - Stream.cpp - adds parsing methods to Stream class - Copyright (c) 2008 David A. Mellis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Created July 2011 - parsing functions based on TextFinder library by Michael Margolis - */ - -#include "Arduino.h" -#include "Stream.h" - -#define PARSE_TIMEOUT 1000 // default number of milli-seconds to wait -#define NO_SKIP_CHAR 1 // a magic char not found in a valid ASCII numeric field - -// private method to read stream with timeout -int Stream::timedRead() -{ - int c; - _startMillis = millis(); - do { - c = read(); - if (c >= 0) return c; - } while(millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout -} - -// private method to peek stream with timeout -int Stream::timedPeek() -{ - int c; - _startMillis = millis(); - do { - c = peek(); - if (c >= 0) return c; - } while(millis() - _startMillis < _timeout); - return -1; // -1 indicates timeout -} - -// returns peek of the next digit in the stream or -1 if timeout -// discards non-numeric characters -int Stream::peekNextDigit() -{ - int c; - while (1) { - c = timedPeek(); - if (c < 0) return c; // timeout - if (c == '-') return c; - if (c >= '0' && c <= '9') return c; - read(); // discard non-numeric - } -} - -// Public Methods -////////////////////////////////////////////////////////////// - -void Stream::setTimeout(unsigned long timeout) // sets the maximum number of milliseconds to wait -{ - _timeout = timeout; -} - - // find returns true if the target string is found -bool Stream::find(char *target) -{ - return findUntil(target, NULL); -} - -// reads data from the stream until the target string of given length is found -// returns true if target string is found, false if timed out -bool Stream::find(char *target, size_t length) -{ - return findUntil(target, length, NULL, 0); -} - -// as find but search ends if the terminator string is found -bool Stream::findUntil(char *target, char *terminator) -{ - return findUntil(target, strlen(target), terminator, strlen(terminator)); -} - -// reads data from the stream until the target string of the given length is found -// search terminated if the terminator string is found -// returns true if target string is found, false if terminated or timed out -bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen) -{ - size_t index = 0; // maximum target string length is 64k bytes! - size_t termIndex = 0; - int c; - - if( *target == 0) - return true; // return true if target is a null string - while( (c = timedRead()) > 0){ - - if(c != target[index]) - index = 0; // reset index if any char does not match - - if( c == target[index]){ - //////Serial.print("found "); Serial.write(c); Serial.print("index now"); Serial.println(index+1); - if(++index >= targetLen){ // return true if all chars in the target match - return true; - } - } - - if(termLen > 0 && c == terminator[termIndex]){ - if(++termIndex >= termLen) - return false; // return false if terminate string found before target string - } - else - termIndex = 0; - } - return false; -} - - -// returns the first valid (long) integer value from the current position. -// initial characters that are not digits (or the minus sign) are skipped -// function is terminated by the first character that is not a digit. -long Stream::parseInt() -{ - return parseInt(NO_SKIP_CHAR); // terminate on first non-digit character (or timeout) -} - -// as above but a given skipChar is ignored -// this allows format characters (typically commas) in values to be ignored -long Stream::parseInt(char skipChar) -{ - boolean isNegative = false; - long value = 0; - int c; - - c = peekNextDigit(); - // ignore non numeric leading characters - if(c < 0) - return 0; // zero returned if timeout - - do{ - if(c == skipChar) - ; // ignore this charactor - else if(c == '-') - isNegative = true; - else if(c >= '0' && c <= '9') // is c a digit? - value = value * 10 + c - '0'; - read(); // consume the character we got with peek - c = timedPeek(); - } - while( (c >= '0' && c <= '9') || c == skipChar ); - - if(isNegative) - value = -value; - return value; -} - - -// as parseInt but returns a floating point value -float Stream::parseFloat() -{ - return parseFloat(NO_SKIP_CHAR); -} - -// as above but the given skipChar is ignored -// this allows format characters (typically commas) in values to be ignored -float Stream::parseFloat(char skipChar){ - boolean isNegative = false; - boolean isFraction = false; - long value = 0; - char c; - float fraction = 1.0; - - c = peekNextDigit(); - // ignore non numeric leading characters - if(c < 0) - return 0; // zero returned if timeout - - do{ - if(c == skipChar) - ; // ignore - else if(c == '-') - isNegative = true; - else if (c == '.') - isFraction = true; - else if(c >= '0' && c <= '9') { // is c a digit? - value = value * 10 + c - '0'; - if(isFraction) - fraction *= 0.1; - } - read(); // consume the character we got with peek - c = timedPeek(); - } - while( (c >= '0' && c <= '9') || c == '.' || c == skipChar ); - - if(isNegative) - value = -value; - if(isFraction) - return value * fraction; - else - return value; -} - -// read characters from stream into buffer -// terminates if length characters have been read, or timeout (see setTimeout) -// returns the number of characters placed in the buffer -// the buffer is NOT null terminated. -// -size_t Stream::readBytes(char *buffer, size_t length) -{ - size_t count = 0; - while (count < length) { - int c = timedRead(); - if (c < 0) break; - *buffer++ = (char)c; - count++; - } - return count; -} - - -// as readBytes with terminator character -// terminates if length characters have been read, timeout, or if the terminator character detected -// returns the number of characters placed in the buffer (0 means no valid data found) - -size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length) -{ - if (length < 1) return 0; - size_t index = 0; - while (index < length) { - int c = timedRead(); - if (c < 0 || c == terminator) break; - *buffer++ = (char)c; - index++; - } - return index; // return number of characters, not including null terminator -} - -String Stream::readString() -{ - String ret; - int c = timedRead(); - while (c >= 0) - { - ret += (char)c; - c = timedRead(); - } - return ret; -} - -String Stream::readStringUntil(char terminator) -{ - String ret; - int c = timedRead(); - while (c >= 0 && c != terminator) - { - ret += (char)c; - c = timedRead(); - } - return ret; -} - diff --git a/platform/osd-merkur/dev/old/Stream.h b/platform/osd-merkur/dev/old/Stream.h deleted file mode 100644 index 58bbf752f..000000000 --- a/platform/osd-merkur/dev/old/Stream.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - Stream.h - base class for character-based streams. - Copyright (c) 2010 David A. Mellis. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - parsing functions based on TextFinder library by Michael Margolis -*/ - -#ifndef Stream_h -#define Stream_h - -#include -#include "Print.h" - -// compatability macros for testing -/* -#define getInt() parseInt() -#define getInt(skipChar) parseInt(skipchar) -#define getFloat() parseFloat() -#define getFloat(skipChar) parseFloat(skipChar) -#define getString( pre_string, post_string, buffer, length) -readBytesBetween( pre_string, terminator, buffer, length) -*/ - -class Stream : public Print -{ - private: - unsigned long _timeout; // number of milliseconds to wait for the next char before aborting timed read - unsigned long _startMillis; // used for timeout measurement - int timedRead(); // private method to read stream with timeout - int timedPeek(); // private method to peek stream with timeout - int peekNextDigit(); // returns the next numeric digit in the stream or -1 if timeout - - public: - virtual int available() = 0; - virtual int read() = 0; - virtual int peek() = 0; - virtual void flush() = 0; - - Stream() {_timeout=1000;} - -// parsing methods - - void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second - - bool find(char *target); // reads data from the stream until the target string is found - // returns true if target string is found, false if timed out (see setTimeout) - - bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found - // returns true if target string is found, false if timed out - - bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found - - bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found - - - long parseInt(); // returns the first valid (long) integer value from the current position. - // initial characters that are not digits (or the minus sign) are skipped - // integer is terminated by the first character that is not a digit. - - float parseFloat(); // float version of parseInt - - size_t readBytes( char *buffer, size_t length); // read chars from stream into buffer - // terminates if length characters have been read or timeout (see setTimeout) - // returns the number of characters placed in the buffer (0 means no valid data found) - - size_t readBytesUntil( char terminator, char *buffer, size_t length); // as readBytes with terminator character - // terminates if length characters have been read, timeout, or if the terminator character detected - // returns the number of characters placed in the buffer (0 means no valid data found) - - // Arduino String functions to be added here - String readString(); - String readStringUntil(char terminator); - - protected: - long parseInt(char skipChar); // as above but the given skipChar is ignored - // as above but the given skipChar is ignored - // this allows format characters (typically commas) in values to be ignored - - float parseFloat(char skipChar); // as above but the given skipChar is ignored -}; - -#endif diff --git a/platform/osd-merkur/dev/old/WString.cpp b/platform/osd-merkur/dev/old/WString.cpp deleted file mode 100644 index c6839fc0d..000000000 --- a/platform/osd-merkur/dev/old/WString.cpp +++ /dev/null @@ -1,645 +0,0 @@ -/* - WString.cpp - String library for Wiring & Arduino - ...mostly rewritten by Paul Stoffregen... - Copyright (c) 2009-10 Hernando Barragan. All rights reserved. - Copyright 2011, Paul Stoffregen, paul@pjrc.com - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include "WString.h" - - -/*********************************************/ -/* Constructors */ -/*********************************************/ - -String::String(const char *cstr) -{ - init(); - if (cstr) copy(cstr, strlen(cstr)); -} - -String::String(const String &value) -{ - init(); - *this = value; -} - -#ifdef __GXX_EXPERIMENTAL_CXX0X__ -String::String(String &&rval) -{ - init(); - move(rval); -} -String::String(StringSumHelper &&rval) -{ - init(); - move(rval); -} -#endif - -String::String(char c) -{ - init(); - char buf[2]; - buf[0] = c; - buf[1] = 0; - *this = buf; -} - -String::String(unsigned char value, unsigned char base) -{ - init(); - char buf[9]; - utoa(value, buf, base); - *this = buf; -} - -String::String(int value, unsigned char base) -{ - init(); - char buf[18]; - itoa(value, buf, base); - *this = buf; -} - -String::String(unsigned int value, unsigned char base) -{ - init(); - char buf[17]; - utoa(value, buf, base); - *this = buf; -} - -String::String(long value, unsigned char base) -{ - init(); - char buf[34]; - ltoa(value, buf, base); - *this = buf; -} - -String::String(unsigned long value, unsigned char base) -{ - init(); - char buf[33]; - ultoa(value, buf, base); - *this = buf; -} - -String::~String() -{ - free(buffer); -} - -/*********************************************/ -/* Memory Management */ -/*********************************************/ - -inline void String::init(void) -{ - buffer = NULL; - capacity = 0; - len = 0; - flags = 0; -} - -void String::invalidate(void) -{ - if (buffer) free(buffer); - buffer = NULL; - capacity = len = 0; -} - -unsigned char String::reserve(unsigned int size) -{ - if (buffer && capacity >= size) return 1; - if (changeBuffer(size)) { - if (len == 0) buffer[0] = 0; - return 1; - } - return 0; -} - -unsigned char String::changeBuffer(unsigned int maxStrLen) -{ - char *newbuffer = (char *)realloc(buffer, maxStrLen + 1); - if (newbuffer) { - buffer = newbuffer; - capacity = maxStrLen; - return 1; - } - return 0; -} - -/*********************************************/ -/* Copy and Move */ -/*********************************************/ - -String & String::copy(const char *cstr, unsigned int length) -{ - if (!reserve(length)) { - invalidate(); - return *this; - } - len = length; - strcpy(buffer, cstr); - return *this; -} - -#ifdef __GXX_EXPERIMENTAL_CXX0X__ -void String::move(String &rhs) -{ - if (buffer) { - if (capacity >= rhs.len) { - strcpy(buffer, rhs.buffer); - len = rhs.len; - rhs.len = 0; - return; - } else { - free(buffer); - } - } - buffer = rhs.buffer; - capacity = rhs.capacity; - len = rhs.len; - rhs.buffer = NULL; - rhs.capacity = 0; - rhs.len = 0; -} -#endif - -String & String::operator = (const String &rhs) -{ - if (this == &rhs) return *this; - - if (rhs.buffer) copy(rhs.buffer, rhs.len); - else invalidate(); - - return *this; -} - -#ifdef __GXX_EXPERIMENTAL_CXX0X__ -String & String::operator = (String &&rval) -{ - if (this != &rval) move(rval); - return *this; -} - -String & String::operator = (StringSumHelper &&rval) -{ - if (this != &rval) move(rval); - return *this; -} -#endif - -String & String::operator = (const char *cstr) -{ - if (cstr) copy(cstr, strlen(cstr)); - else invalidate(); - - return *this; -} - -/*********************************************/ -/* concat */ -/*********************************************/ - -unsigned char String::concat(const String &s) -{ - return concat(s.buffer, s.len); -} - -unsigned char String::concat(const char *cstr, unsigned int length) -{ - unsigned int newlen = len + length; - if (!cstr) return 0; - if (length == 0) return 1; - if (!reserve(newlen)) return 0; - strcpy(buffer + len, cstr); - len = newlen; - return 1; -} - -unsigned char String::concat(const char *cstr) -{ - if (!cstr) return 0; - return concat(cstr, strlen(cstr)); -} - -unsigned char String::concat(char c) -{ - char buf[2]; - buf[0] = c; - buf[1] = 0; - return concat(buf, 1); -} - -unsigned char String::concat(unsigned char num) -{ - char buf[4]; - itoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(int num) -{ - char buf[7]; - itoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(unsigned int num) -{ - char buf[6]; - utoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(long num) -{ - char buf[12]; - ltoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -unsigned char String::concat(unsigned long num) -{ - char buf[11]; - ultoa(num, buf, 10); - return concat(buf, strlen(buf)); -} - -/*********************************************/ -/* Concatenate */ -/*********************************************/ - -StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(rhs.buffer, rhs.len)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr) -{ - StringSumHelper &a = const_cast(lhs); - if (!cstr || !a.concat(cstr, strlen(cstr))) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, char c) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(c)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, int num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, long num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num) -{ - StringSumHelper &a = const_cast(lhs); - if (!a.concat(num)) a.invalidate(); - return a; -} - -/*********************************************/ -/* Comparison */ -/*********************************************/ - -int String::compareTo(const String &s) const -{ - if (!buffer || !s.buffer) { - if (s.buffer && s.len > 0) return 0 - *(unsigned char *)s.buffer; - if (buffer && len > 0) return *(unsigned char *)buffer; - return 0; - } - return strcmp(buffer, s.buffer); -} - -unsigned char String::equals(const String &s2) const -{ - return (len == s2.len && compareTo(s2) == 0); -} - -unsigned char String::equals(const char *cstr) const -{ - if (len == 0) return (cstr == NULL || *cstr == 0); - if (cstr == NULL) return buffer[0] == 0; - return strcmp(buffer, cstr) == 0; -} - -unsigned char String::operator<(const String &rhs) const -{ - return compareTo(rhs) < 0; -} - -unsigned char String::operator>(const String &rhs) const -{ - return compareTo(rhs) > 0; -} - -unsigned char String::operator<=(const String &rhs) const -{ - return compareTo(rhs) <= 0; -} - -unsigned char String::operator>=(const String &rhs) const -{ - return compareTo(rhs) >= 0; -} - -unsigned char String::equalsIgnoreCase( const String &s2 ) const -{ - if (this == &s2) return 1; - if (len != s2.len) return 0; - if (len == 0) return 1; - const char *p1 = buffer; - const char *p2 = s2.buffer; - while (*p1) { - if (tolower(*p1++) != tolower(*p2++)) return 0; - } - return 1; -} - -unsigned char String::startsWith( const String &s2 ) const -{ - if (len < s2.len) return 0; - return startsWith(s2, 0); -} - -unsigned char String::startsWith( const String &s2, unsigned int offset ) const -{ - if (offset > len - s2.len || !buffer || !s2.buffer) return 0; - return strncmp( &buffer[offset], s2.buffer, s2.len ) == 0; -} - -unsigned char String::endsWith( const String &s2 ) const -{ - if ( len < s2.len || !buffer || !s2.buffer) return 0; - return strcmp(&buffer[len - s2.len], s2.buffer) == 0; -} - -/*********************************************/ -/* Character Access */ -/*********************************************/ - -char String::charAt(unsigned int loc) const -{ - return operator[](loc); -} - -void String::setCharAt(unsigned int loc, char c) -{ - if (loc < len) buffer[loc] = c; -} - -char & String::operator[](unsigned int index) -{ - static char dummy_writable_char; - if (index >= len || !buffer) { - dummy_writable_char = 0; - return dummy_writable_char; - } - return buffer[index]; -} - -char String::operator[]( unsigned int index ) const -{ - if (index >= len || !buffer) return 0; - return buffer[index]; -} - -void String::getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index) const -{ - if (!bufsize || !buf) return; - if (index >= len) { - buf[0] = 0; - return; - } - unsigned int n = bufsize - 1; - if (n > len - index) n = len - index; - strncpy((char *)buf, buffer + index, n); - buf[n] = 0; -} - -/*********************************************/ -/* Search */ -/*********************************************/ - -int String::indexOf(char c) const -{ - return indexOf(c, 0); -} - -int String::indexOf( char ch, unsigned int fromIndex ) const -{ - if (fromIndex >= len) return -1; - const char* temp = strchr(buffer + fromIndex, ch); - if (temp == NULL) return -1; - return temp - buffer; -} - -int String::indexOf(const String &s2) const -{ - return indexOf(s2, 0); -} - -int String::indexOf(const String &s2, unsigned int fromIndex) const -{ - if (fromIndex >= len) return -1; - const char *found = strstr(buffer + fromIndex, s2.buffer); - if (found == NULL) return -1; - return found - buffer; -} - -int String::lastIndexOf( char theChar ) const -{ - return lastIndexOf(theChar, len - 1); -} - -int String::lastIndexOf(char ch, unsigned int fromIndex) const -{ - if (fromIndex >= len) return -1; - char tempchar = buffer[fromIndex + 1]; - buffer[fromIndex + 1] = '\0'; - char* temp = strrchr( buffer, ch ); - buffer[fromIndex + 1] = tempchar; - if (temp == NULL) return -1; - return temp - buffer; -} - -int String::lastIndexOf(const String &s2) const -{ - return lastIndexOf(s2, len - s2.len); -} - -int String::lastIndexOf(const String &s2, unsigned int fromIndex) const -{ - if (s2.len == 0 || len == 0 || s2.len > len) return -1; - if (fromIndex >= len) fromIndex = len - 1; - int found = -1; - for (char *p = buffer; p <= buffer + fromIndex; p++) { - p = strstr(p, s2.buffer); - if (!p) break; - if ((unsigned int)(p - buffer) <= fromIndex) found = p - buffer; - } - return found; -} - -String String::substring( unsigned int left ) const -{ - return substring(left, len); -} - -String String::substring(unsigned int left, unsigned int right) const -{ - if (left > right) { - unsigned int temp = right; - right = left; - left = temp; - } - String out; - if (left > len) return out; - if (right > len) right = len; - char temp = buffer[right]; // save the replaced character - buffer[right] = '\0'; - out = buffer + left; // pointer arithmetic - buffer[right] = temp; //restore character - return out; -} - -/*********************************************/ -/* Modification */ -/*********************************************/ - -void String::replace(char find, char replace) -{ - if (!buffer) return; - for (char *p = buffer; *p; p++) { - if (*p == find) *p = replace; - } -} - -void String::replace(const String& find, const String& replace) -{ - if (len == 0 || find.len == 0) return; - int diff = replace.len - find.len; - char *readFrom = buffer; - char *foundAt; - if (diff == 0) { - while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - memcpy(foundAt, replace.buffer, replace.len); - readFrom = foundAt + replace.len; - } - } else if (diff < 0) { - char *writeTo = buffer; - while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - unsigned int n = foundAt - readFrom; - memcpy(writeTo, readFrom, n); - writeTo += n; - memcpy(writeTo, replace.buffer, replace.len); - writeTo += replace.len; - readFrom = foundAt + find.len; - len += diff; - } - strcpy(writeTo, readFrom); - } else { - unsigned int size = len; // compute size needed for result - while ((foundAt = strstr(readFrom, find.buffer)) != NULL) { - readFrom = foundAt + find.len; - size += diff; - } - if (size == len) return; - if (size > capacity && !changeBuffer(size)) return; // XXX: tell user! - int index = len - 1; - while (index >= 0 && (index = lastIndexOf(find, index)) >= 0) { - readFrom = buffer + index + find.len; - memmove(readFrom + diff, readFrom, len - (readFrom - buffer)); - len += diff; - buffer[len] = 0; - memcpy(buffer + index, replace.buffer, replace.len); - index--; - } - } -} - -void String::toLowerCase(void) -{ - if (!buffer) return; - for (char *p = buffer; *p; p++) { - *p = tolower(*p); - } -} - -void String::toUpperCase(void) -{ - if (!buffer) return; - for (char *p = buffer; *p; p++) { - *p = toupper(*p); - } -} - -void String::trim(void) -{ - if (!buffer || len == 0) return; - char *begin = buffer; - while (isspace(*begin)) begin++; - char *end = buffer + len - 1; - while (isspace(*end) && end >= begin) end--; - len = end + 1 - begin; - if (begin > buffer) memcpy(buffer, begin, len); - buffer[len] = 0; -} - -/*********************************************/ -/* Parsing / Conversion */ -/*********************************************/ - -long String::toInt(void) const -{ - if (buffer) return atol(buffer); - return 0; -} - - diff --git a/platform/osd-merkur/dev/old/WString.h b/platform/osd-merkur/dev/old/WString.h deleted file mode 100644 index 947325e5f..000000000 --- a/platform/osd-merkur/dev/old/WString.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - WString.h - String library for Wiring & Arduino - ...mostly rewritten by Paul Stoffregen... - Copyright (c) 2009-10 Hernando Barragan. All right reserved. - Copyright 2011, Paul Stoffregen, paul@pjrc.com - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef String_class_h -#define String_class_h -#ifdef __cplusplus - -#include -#include -#include -#include - -// When compiling programs with this class, the following gcc parameters -// dramatically increase performance and memory (RAM) efficiency, typically -// with little or no increase in code size. -// -felide-constructors -// -std=c++0x - -class __FlashStringHelper; -#define F(string_literal) (reinterpret_cast(PSTR(string_literal))) - -// An inherited class for holding the result of a concatenation. These -// result objects are assumed to be writable by subsequent concatenations. -class StringSumHelper; - -// The string class -class String -{ - // use a function pointer to allow for "if (s)" without the - // complications of an operator bool(). for more information, see: - // http://www.artima.com/cppsource/safebool.html - typedef void (String::*StringIfHelperType)() const; - void StringIfHelper() const {} - -public: - // constructors - // creates a copy of the initial value. - // if the initial value is null or invalid, or if memory allocation - // fails, the string will be marked as invalid (i.e. "if (s)" will - // be false). - String(const char *cstr = ""); - String(const String &str); - #ifdef __GXX_EXPERIMENTAL_CXX0X__ - String(String &&rval); - String(StringSumHelper &&rval); - #endif - explicit String(char c); - explicit String(unsigned char, unsigned char base=10); - explicit String(int, unsigned char base=10); - explicit String(unsigned int, unsigned char base=10); - explicit String(long, unsigned char base=10); - explicit String(unsigned long, unsigned char base=10); - ~String(void); - - // memory management - // return true on success, false on failure (in which case, the string - // is left unchanged). reserve(0), if successful, will validate an - // invalid string (i.e., "if (s)" will be true afterwards) - unsigned char reserve(unsigned int size); - inline unsigned int length(void) const {return len;} - - // creates a copy of the assigned value. if the value is null or - // invalid, or if the memory allocation fails, the string will be - // marked as invalid ("if (s)" will be false). - String & operator = (const String &rhs); - String & operator = (const char *cstr); - #ifdef __GXX_EXPERIMENTAL_CXX0X__ - String & operator = (String &&rval); - String & operator = (StringSumHelper &&rval); - #endif - - // concatenate (works w/ built-in types) - - // returns true on success, false on failure (in which case, the string - // is left unchanged). if the argument is null or invalid, the - // concatenation is considered unsucessful. - unsigned char concat(const String &str); - unsigned char concat(const char *cstr); - unsigned char concat(char c); - unsigned char concat(unsigned char c); - unsigned char concat(int num); - unsigned char concat(unsigned int num); - unsigned char concat(long num); - unsigned char concat(unsigned long num); - - // if there's not enough memory for the concatenated value, the string - // will be left unchanged (but this isn't signalled in any way) - String & operator += (const String &rhs) {concat(rhs); return (*this);} - String & operator += (const char *cstr) {concat(cstr); return (*this);} - String & operator += (char c) {concat(c); return (*this);} - String & operator += (unsigned char num) {concat(num); return (*this);} - String & operator += (int num) {concat(num); return (*this);} - String & operator += (unsigned int num) {concat(num); return (*this);} - String & operator += (long num) {concat(num); return (*this);} - String & operator += (unsigned long num) {concat(num); return (*this);} - - friend StringSumHelper & operator + (const StringSumHelper &lhs, const String &rhs); - friend StringSumHelper & operator + (const StringSumHelper &lhs, const char *cstr); - friend StringSumHelper & operator + (const StringSumHelper &lhs, char c); - friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned char num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, int num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned int num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, long num); - friend StringSumHelper & operator + (const StringSumHelper &lhs, unsigned long num); - - // comparison (only works w/ Strings and "strings") - operator StringIfHelperType() const { return buffer ? &String::StringIfHelper : 0; } - int compareTo(const String &s) const; - unsigned char equals(const String &s) const; - unsigned char equals(const char *cstr) const; - unsigned char operator == (const String &rhs) const {return equals(rhs);} - unsigned char operator == (const char *cstr) const {return equals(cstr);} - unsigned char operator != (const String &rhs) const {return !equals(rhs);} - unsigned char operator != (const char *cstr) const {return !equals(cstr);} - unsigned char operator < (const String &rhs) const; - unsigned char operator > (const String &rhs) const; - unsigned char operator <= (const String &rhs) const; - unsigned char operator >= (const String &rhs) const; - unsigned char equalsIgnoreCase(const String &s) const; - unsigned char startsWith( const String &prefix) const; - unsigned char startsWith(const String &prefix, unsigned int offset) const; - unsigned char endsWith(const String &suffix) const; - - // character acccess - char charAt(unsigned int index) const; - void setCharAt(unsigned int index, char c); - char operator [] (unsigned int index) const; - char& operator [] (unsigned int index); - void getBytes(unsigned char *buf, unsigned int bufsize, unsigned int index=0) const; - void toCharArray(char *buf, unsigned int bufsize, unsigned int index=0) const - {getBytes((unsigned char *)buf, bufsize, index);} - - // search - int indexOf( char ch ) const; - int indexOf( char ch, unsigned int fromIndex ) const; - int indexOf( const String &str ) const; - int indexOf( const String &str, unsigned int fromIndex ) const; - int lastIndexOf( char ch ) const; - int lastIndexOf( char ch, unsigned int fromIndex ) const; - int lastIndexOf( const String &str ) const; - int lastIndexOf( const String &str, unsigned int fromIndex ) const; - String substring( unsigned int beginIndex ) const; - String substring( unsigned int beginIndex, unsigned int endIndex ) const; - - // modification - void replace(char find, char replace); - void replace(const String& find, const String& replace); - void toLowerCase(void); - void toUpperCase(void); - void trim(void); - - // parsing/conversion - long toInt(void) const; - -protected: - char *buffer; // the actual char array - unsigned int capacity; // the array length minus one (for the '\0') - unsigned int len; // the String length (not counting the '\0') - unsigned char flags; // unused, for future features -protected: - void init(void); - void invalidate(void); - unsigned char changeBuffer(unsigned int maxStrLen); - unsigned char concat(const char *cstr, unsigned int length); - - // copy and move - String & copy(const char *cstr, unsigned int length); - #ifdef __GXX_EXPERIMENTAL_CXX0X__ - void move(String &rhs); - #endif -}; - -class StringSumHelper : public String -{ -public: - StringSumHelper(const String &s) : String(s) {} - StringSumHelper(const char *p) : String(p) {} - StringSumHelper(char c) : String(c) {} - StringSumHelper(unsigned char num) : String(num) {} - StringSumHelper(int num) : String(num) {} - StringSumHelper(unsigned int num) : String(num) {} - StringSumHelper(long num) : String(num) {} - StringSumHelper(unsigned long num) : String(num) {} -}; - -#endif // __cplusplus -#endif // String_class_h diff --git a/platform/osd-merkur/dev/old/Wire.cpp b/platform/osd-merkur/dev/old/Wire.cpp deleted file mode 100644 index 4e7a17c47..000000000 --- a/platform/osd-merkur/dev/old/Wire.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/* - TwoWire.cpp - TWI/I2C library for Wiring & Arduino - Copyright (c) 2006 Nicholas Zambetti. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts -*/ - -extern "C" { - #include - #include - #include - #include "twi.h" -} - -#include "Wire.h" - -// Initialize Class Variables ////////////////////////////////////////////////// - -uint8_t TwoWire::rxBuffer[BUFFER_LENGTH]; -uint8_t TwoWire::rxBufferIndex = 0; -uint8_t TwoWire::rxBufferLength = 0; - -uint8_t TwoWire::txAddress = 0; -uint8_t TwoWire::txBuffer[BUFFER_LENGTH]; -uint8_t TwoWire::txBufferIndex = 0; -uint8_t TwoWire::txBufferLength = 0; - -uint8_t TwoWire::transmitting = 0; -void (*TwoWire::user_onRequest)(void); -void (*TwoWire::user_onReceive)(int); - -// Constructors //////////////////////////////////////////////////////////////// - -TwoWire::TwoWire() -{ -} - -// Public Methods ////////////////////////////////////////////////////////////// - -void TwoWire::begin(void) -{ - rxBufferIndex = 0; - rxBufferLength = 0; - - txBufferIndex = 0; - txBufferLength = 0; - - twi_init(); -} - -void TwoWire::begin(uint8_t address) -{ - twi_setAddress(address); - twi_attachSlaveTxEvent(onRequestService); - twi_attachSlaveRxEvent(onReceiveService); - begin(); -} - -void TwoWire::begin(int address) -{ - begin((uint8_t)address); -} - -uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop) -{ - // clamp to buffer length - if(quantity > BUFFER_LENGTH){ - quantity = BUFFER_LENGTH; - } - // perform blocking read into buffer - uint8_t read = twi_readFrom(address, rxBuffer, quantity, sendStop); - // set rx buffer iterator vars - rxBufferIndex = 0; - rxBufferLength = read; - - return read; -} - -uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) -{ - return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); -} - -uint8_t TwoWire::requestFrom(int address, int quantity) -{ - return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)true); -} - -uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop) -{ - return requestFrom((uint8_t)address, (uint8_t)quantity, (uint8_t)sendStop); -} - -void TwoWire::beginTransmission(uint8_t address) -{ - // indicate that we are transmitting - transmitting = 1; - // set address of targeted slave - txAddress = address; - // reset tx buffer iterator vars - txBufferIndex = 0; - txBufferLength = 0; -} - -void TwoWire::beginTransmission(int address) -{ - beginTransmission((uint8_t)address); -} - -// -// Originally, 'endTransmission' was an f(void) function. -// It has been modified to take one parameter indicating -// whether or not a STOP should be performed on the bus. -// Calling endTransmission(false) allows a sketch to -// perform a repeated start. -// -// WARNING: Nothing in the library keeps track of whether -// the bus tenure has been properly ended with a STOP. It -// is very possible to leave the bus in a hung state if -// no call to endTransmission(true) is made. Some I2C -// devices will behave oddly if they do not see a STOP. -// -uint8_t TwoWire::endTransmission(uint8_t sendStop) -{ - // transmit buffer (blocking) - int8_t ret = twi_writeTo(txAddress, txBuffer, txBufferLength, 1, sendStop); - // reset tx buffer iterator vars - txBufferIndex = 0; - txBufferLength = 0; - // indicate that we are done transmitting - transmitting = 0; - return ret; -} - -// This provides backwards compatibility with the original -// definition, and expected behaviour, of endTransmission -// -uint8_t TwoWire::endTransmission(void) -{ - return endTransmission(true); -} - -// must be called in: -// slave tx event callback -// or after beginTransmission(address) -size_t TwoWire::write(uint8_t data) -{ - if(transmitting){ - // in master transmitter mode - // don't bother if buffer is full - if(txBufferLength >= BUFFER_LENGTH){ - setWriteError(); - return 0; - } - // put byte in tx buffer - txBuffer[txBufferIndex] = data; - ++txBufferIndex; - // update amount in buffer - txBufferLength = txBufferIndex; - }else{ - // in slave send mode - // reply to master - twi_transmit(&data, 1); - } - return 1; -} - -// must be called in: -// slave tx event callback -// or after beginTransmission(address) -size_t TwoWire::write(const uint8_t *data, size_t quantity) -{ - if(transmitting){ - // in master transmitter mode - for(size_t i = 0; i < quantity; ++i){ - write(data[i]); - } - }else{ - // in slave send mode - // reply to master - twi_transmit(data, quantity); - } - return quantity; -} - -// must be called in: -// slave rx event callback -// or after requestFrom(address, numBytes) -int TwoWire::available(void) -{ - return rxBufferLength - rxBufferIndex; -} - -// must be called in: -// slave rx event callback -// or after requestFrom(address, numBytes) -int TwoWire::read(void) -{ - int value = -1; - - // get each successive byte on each call - if(rxBufferIndex < rxBufferLength){ - value = rxBuffer[rxBufferIndex]; - ++rxBufferIndex; - } - - return value; -} - -// must be called in: -// slave rx event callback -// or after requestFrom(address, numBytes) -int TwoWire::peek(void) -{ - int value = -1; - - if(rxBufferIndex < rxBufferLength){ - value = rxBuffer[rxBufferIndex]; - } - - return value; -} - -void TwoWire::flush(void) -{ - // XXX: to be implemented. -} - -// behind the scenes function that is called when data is received -void TwoWire::onReceiveService(uint8_t* inBytes, int numBytes) -{ - // don't bother if user hasn't registered a callback - if(!user_onReceive){ - return; - } - // don't bother if rx buffer is in use by a master requestFrom() op - // i know this drops data, but it allows for slight stupidity - // meaning, they may not have read all the master requestFrom() data yet - if(rxBufferIndex < rxBufferLength){ - return; - } - // copy twi rx buffer into local read buffer - // this enables new reads to happen in parallel - for(uint8_t i = 0; i < numBytes; ++i){ - rxBuffer[i] = inBytes[i]; - } - // set rx iterator vars - rxBufferIndex = 0; - rxBufferLength = numBytes; - // alert user program - user_onReceive(numBytes); -} - -// behind the scenes function that is called when data is requested -void TwoWire::onRequestService(void) -{ - // don't bother if user hasn't registered a callback - if(!user_onRequest){ - return; - } - // reset tx buffer iterator vars - // !!! this will kill any pending pre-master sendTo() activity - txBufferIndex = 0; - txBufferLength = 0; - // alert user program - user_onRequest(); -} - -// sets function called on slave write -void TwoWire::onReceive( void (*function)(int) ) -{ - user_onReceive = function; -} - -// sets function called on slave read -void TwoWire::onRequest( void (*function)(void) ) -{ - user_onRequest = function; -} - -// Preinstantiate Objects ////////////////////////////////////////////////////// - -TwoWire Wire = TwoWire(); - diff --git a/platform/osd-merkur/dev/old/Wire.h b/platform/osd-merkur/dev/old/Wire.h deleted file mode 100644 index a93d0f5bb..000000000 --- a/platform/osd-merkur/dev/old/Wire.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - TwoWire.h - TWI/I2C library for Arduino & Wiring - Copyright (c) 2006 Nicholas Zambetti. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts -*/ - -#ifndef TwoWire_h -#define TwoWire_h - -#include -#include "Stream.h" - -#define BUFFER_LENGTH 32 - -class TwoWire : public Stream -{ - private: - static uint8_t rxBuffer[]; - static uint8_t rxBufferIndex; - static uint8_t rxBufferLength; - - static uint8_t txAddress; - static uint8_t txBuffer[]; - static uint8_t txBufferIndex; - static uint8_t txBufferLength; - - static uint8_t transmitting; - static void (*user_onRequest)(void); - static void (*user_onReceive)(int); - static void onRequestService(void); - static void onReceiveService(uint8_t*, int); - public: - TwoWire(); - void begin(); - void begin(uint8_t); - void begin(int); - void beginTransmission(uint8_t); - void beginTransmission(int); - uint8_t endTransmission(void); - uint8_t endTransmission(uint8_t); - uint8_t requestFrom(uint8_t, uint8_t); - uint8_t requestFrom(uint8_t, uint8_t, uint8_t); - uint8_t requestFrom(int, int); - uint8_t requestFrom(int, int, int); - virtual size_t write(uint8_t); - virtual size_t write(const uint8_t *, size_t); - virtual int available(void); - virtual int read(void); - virtual int peek(void); - virtual void flush(void); - void onReceive( void (*)(int) ); - void onRequest( void (*)(void) ); - - inline size_t write(unsigned long n) { return write((uint8_t)n); } - inline size_t write(long n) { return write((uint8_t)n); } - inline size_t write(unsigned int n) { return write((uint8_t)n); } - inline size_t write(int n) { return write((uint8_t)n); } - using Print::write; -}; - -extern TwoWire Wire; - -#endif - diff --git a/platform/osd-merkur/dev/old/new.cpp b/platform/osd-merkur/dev/old/new.cpp deleted file mode 100644 index b81031e90..000000000 --- a/platform/osd-merkur/dev/old/new.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include - -void * operator new(size_t size) -{ - return malloc(size); -} - -void * operator new[](size_t size) -{ - return malloc(size); -} - -void operator delete(void * ptr) -{ - free(ptr); -} - -void operator delete[](void * ptr) -{ - free(ptr); -} - -int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);}; -void __cxa_guard_release (__guard *g) {*(char *)g = 1;}; -void __cxa_guard_abort (__guard *) {}; - -void __cxa_pure_virtual(void) {}; - diff --git a/platform/osd-merkur/dev/old/new.h b/platform/osd-merkur/dev/old/new.h deleted file mode 100644 index 991c86c75..000000000 --- a/platform/osd-merkur/dev/old/new.h +++ /dev/null @@ -1,24 +0,0 @@ -/* Header to define new/delete operators as they aren't provided by avr-gcc by default - Taken from http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=59453 - */ - -#ifndef NEW_H -#define NEW_H - -#include - -void * operator new(size_t size); -void * operator new[](size_t size); -void operator delete(void * ptr); -void operator delete[](void * ptr); - -__extension__ typedef int __guard __attribute__((mode (__DI__))); - -extern "C" int __cxa_guard_acquire(__guard *); -extern "C" void __cxa_guard_release (__guard *); -extern "C" void __cxa_guard_abort (__guard *); - -extern "C" void __cxa_pure_virtual(void); - -#endif - diff --git a/platform/osd-merkur/dev/old/twi.c b/platform/osd-merkur/dev/old/twi.c deleted file mode 100644 index 6b2db3cdc..000000000 --- a/platform/osd-merkur/dev/old/twi.c +++ /dev/null @@ -1,527 +0,0 @@ -/* - twi.c - TWI/I2C library for Wiring & Arduino - Copyright (c) 2006 Nicholas Zambetti. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - - Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts -*/ - -#include -#include -#include -#include -#include -#include -#include "Arduino.h" // for digitalWrite - -#ifndef cbi -#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit)) -#endif - -#ifndef sbi -#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit)) -#endif - -#include "pins_arduino.h" -#include "twi.h" - -static volatile uint8_t twi_state; -static volatile uint8_t twi_slarw; -static volatile uint8_t twi_sendStop; // should the transaction end with a stop -static volatile uint8_t twi_inRepStart; // in the middle of a repeated start - -static void (*twi_onSlaveTransmit)(void); -static void (*twi_onSlaveReceive)(uint8_t*, int); - -static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; -static volatile uint8_t twi_masterBufferIndex; -static volatile uint8_t twi_masterBufferLength; - -static uint8_t twi_txBuffer[TWI_BUFFER_LENGTH]; -static volatile uint8_t twi_txBufferIndex; -static volatile uint8_t twi_txBufferLength; - -static uint8_t twi_rxBuffer[TWI_BUFFER_LENGTH]; -static volatile uint8_t twi_rxBufferIndex; - -static volatile uint8_t twi_error; - -/* - * Function twi_init - * Desc readys twi pins and sets twi bitrate - * Input none - * Output none - */ -void twi_init(void) -{ - // initialize state - twi_state = TWI_READY; - twi_sendStop = true; // default value - twi_inRepStart = false; - - // activate internal pullups for twi. - digitalWrite(SDA, 1); - digitalWrite(SCL, 1); - - // initialize twi prescaler and bit rate - cbi(TWSR, TWPS0); - cbi(TWSR, TWPS1); - TWBR = ((F_CPU / TWI_FREQ) - 16) / 2; - - /* twi bit rate formula from atmega128 manual pg 204 - SCL Frequency = CPU Clock Frequency / (16 + (2 * TWBR)) - note: TWBR should be 10 or higher for master mode - It is 72 for a 16mhz Wiring board with 100kHz TWI */ - - // enable twi module, acks, and twi interrupt - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); -} - -/* - * Function twi_slaveInit - * Desc sets slave address and enables interrupt - * Input none - * Output none - */ -void twi_setAddress(uint8_t address) -{ - // set twi slave address (skip over TWGCE bit) - TWAR = address << 1; -} - -/* - * Function twi_readFrom - * Desc attempts to become twi bus master and read a - * series of bytes from a device on the bus - * Input address: 7bit i2c device address - * data: pointer to byte array - * length: number of bytes to read into array - * sendStop: Boolean indicating whether to send a stop at the end - * Output number of bytes read - */ -uint8_t twi_readFrom(uint8_t address, uint8_t* data, uint8_t length, uint8_t sendStop) -{ - uint8_t i; - - // ensure data will fit into buffer - if(TWI_BUFFER_LENGTH < length){ - return 0; - } - - // wait until twi is ready, become master receiver - while(TWI_READY != twi_state){ - continue; - } - twi_state = TWI_MRX; - twi_sendStop = sendStop; - // reset error state (0xFF.. no error occured) - twi_error = 0xFF; - - // initialize buffer iteration vars - twi_masterBufferIndex = 0; - twi_masterBufferLength = length-1; // This is not intuitive, read on... - // On receive, the previously configured ACK/NACK setting is transmitted in - // response to the received byte before the interrupt is signalled. - // Therefor we must actually set NACK when the _next_ to last byte is - // received, causing that NACK to be sent in response to receiving the last - // expected byte of data. - - // build sla+w, slave device address + w bit - twi_slarw = TW_READ; - twi_slarw |= address << 1; - - if (true == twi_inRepStart) { - // if we're in the repeated start state, then we've already sent the start, - // (@@@ we hope), and the TWI statemachine is just waiting for the address byte. - // We need to remove ourselves from the repeated start state before we enable interrupts, - // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning - // up. Also, don't enable the START interrupt. There may be one pending from the - // repeated start that we sent outselves, and that would really confuse things. - twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR - TWDR = twi_slarw; - TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START - } - else - // send start condition - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); - - // wait for read operation to complete - while(TWI_MRX == twi_state){ - continue; - } - - if (twi_masterBufferIndex < length) - length = twi_masterBufferIndex; - - // copy twi buffer to data - for(i = 0; i < length; ++i){ - data[i] = twi_masterBuffer[i]; - } - - return length; -} - -/* - * Function twi_writeTo - * Desc attempts to become twi bus master and write a - * series of bytes to a device on the bus - * Input address: 7bit i2c device address - * data: pointer to byte array - * length: number of bytes in array - * wait: boolean indicating to wait for write or not - * sendStop: boolean indicating whether or not to send a stop at the end - * Output 0 .. success - * 1 .. length to long for buffer - * 2 .. address send, NACK received - * 3 .. data send, NACK received - * 4 .. other twi error (lost bus arbitration, bus error, ..) - */ -uint8_t twi_writeTo(uint8_t address, uint8_t* data, uint8_t length, uint8_t wait, uint8_t sendStop) -{ - uint8_t i; - - // ensure data will fit into buffer - if(TWI_BUFFER_LENGTH < length){ - return 1; - } - - // wait until twi is ready, become master transmitter - while(TWI_READY != twi_state){ - continue; - } - twi_state = TWI_MTX; - twi_sendStop = sendStop; - // reset error state (0xFF.. no error occured) - twi_error = 0xFF; - - // initialize buffer iteration vars - twi_masterBufferIndex = 0; - twi_masterBufferLength = length; - - // copy data to twi buffer - for(i = 0; i < length; ++i){ - twi_masterBuffer[i] = data[i]; - } - - // build sla+w, slave device address + w bit - twi_slarw = TW_WRITE; - twi_slarw |= address << 1; - - // if we're in a repeated start, then we've already sent the START - // in the ISR. Don't do it again. - // - if (true == twi_inRepStart) { - // if we're in the repeated start state, then we've already sent the start, - // (@@@ we hope), and the TWI statemachine is just waiting for the address byte. - // We need to remove ourselves from the repeated start state before we enable interrupts, - // since the ISR is ASYNC, and we could get confused if we hit the ISR before cleaning - // up. Also, don't enable the START interrupt. There may be one pending from the - // repeated start that we sent outselves, and that would really confuse things. - twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR - TWDR = twi_slarw; - TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE); // enable INTs, but not START - } - else - // send start condition - TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | _BV(TWSTA); // enable INTs - - // wait for write operation to complete - while(wait && (TWI_MTX == twi_state)){ - continue; - } - - if (twi_error == 0xFF) - return 0; // success - else if (twi_error == TW_MT_SLA_NACK) - return 2; // error: address send, nack received - else if (twi_error == TW_MT_DATA_NACK) - return 3; // error: data send, nack received - else - return 4; // other twi error -} - -/* - * Function twi_transmit - * Desc fills slave tx buffer with data - * must be called in slave tx event callback - * Input data: pointer to byte array - * length: number of bytes in array - * Output 1 length too long for buffer - * 2 not slave transmitter - * 0 ok - */ -uint8_t twi_transmit(const uint8_t* data, uint8_t length) -{ - uint8_t i; - - // ensure data will fit into buffer - if(TWI_BUFFER_LENGTH < length){ - return 1; - } - - // ensure we are currently a slave transmitter - if(TWI_STX != twi_state){ - return 2; - } - - // set length and copy data into tx buffer - twi_txBufferLength = length; - for(i = 0; i < length; ++i){ - twi_txBuffer[i] = data[i]; - } - - return 0; -} - -/* - * Function twi_attachSlaveRxEvent - * Desc sets function called before a slave read operation - * Input function: callback function to use - * Output none - */ -void twi_attachSlaveRxEvent( void (*function)(uint8_t*, int) ) -{ - twi_onSlaveReceive = function; -} - -/* - * Function twi_attachSlaveTxEvent - * Desc sets function called before a slave write operation - * Input function: callback function to use - * Output none - */ -void twi_attachSlaveTxEvent( void (*function)(void) ) -{ - twi_onSlaveTransmit = function; -} - -/* - * Function twi_reply - * Desc sends byte or readys receive line - * Input ack: byte indicating to ack or to nack - * Output none - */ -void twi_reply(uint8_t ack) -{ - // transmit master read ready signal, with or without ack - if(ack){ - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); - }else{ - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); - } -} - -/* - * Function twi_stop - * Desc relinquishes bus master status - * Input none - * Output none - */ -void twi_stop(void) -{ - // send stop condition - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); - - // wait for stop condition to be exectued on bus - // TWINT is not set after a stop condition! - while(TWCR & _BV(TWSTO)){ - continue; - } - - // update twi state - twi_state = TWI_READY; -} - -/* - * Function twi_releaseBus - * Desc releases bus control - * Input none - * Output none - */ -void twi_releaseBus(void) -{ - // release bus - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); - - // update twi state - twi_state = TWI_READY; -} - -SIGNAL(TWI_vect) -{ - switch(TW_STATUS){ - // All Master - case TW_START: // sent start condition - case TW_REP_START: // sent repeated start condition - // copy device address and r/w bit to output register and ack - TWDR = twi_slarw; - twi_reply(1); - break; - - // Master Transmitter - case TW_MT_SLA_ACK: // slave receiver acked address - case TW_MT_DATA_ACK: // slave receiver acked data - // if there is data to send, send it, otherwise stop - if(twi_masterBufferIndex < twi_masterBufferLength){ - // copy data to output register and ack - TWDR = twi_masterBuffer[twi_masterBufferIndex++]; - twi_reply(1); - }else{ - if (twi_sendStop) - twi_stop(); - else { - twi_inRepStart = true; // we're gonna send the START - // don't enable the interrupt. We'll generate the start, but we - // avoid handling the interrupt until we're in the next transaction, - // at the point where we would normally issue the start. - TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; - twi_state = TWI_READY; - } - } - break; - case TW_MT_SLA_NACK: // address sent, nack received - twi_error = TW_MT_SLA_NACK; - twi_stop(); - break; - case TW_MT_DATA_NACK: // data sent, nack received - twi_error = TW_MT_DATA_NACK; - twi_stop(); - break; - case TW_MT_ARB_LOST: // lost bus arbitration - twi_error = TW_MT_ARB_LOST; - twi_releaseBus(); - break; - - // Master Receiver - case TW_MR_DATA_ACK: // data received, ack sent - // put byte into buffer - twi_masterBuffer[twi_masterBufferIndex++] = TWDR; - case TW_MR_SLA_ACK: // address sent, ack received - // ack if more bytes are expected, otherwise nack - if(twi_masterBufferIndex < twi_masterBufferLength){ - twi_reply(1); - }else{ - twi_reply(0); - } - break; - case TW_MR_DATA_NACK: // data received, nack sent - // put final byte into buffer - twi_masterBuffer[twi_masterBufferIndex++] = TWDR; - if (twi_sendStop) - twi_stop(); - else { - twi_inRepStart = true; // we're gonna send the START - // don't enable the interrupt. We'll generate the start, but we - // avoid handling the interrupt until we're in the next transaction, - // at the point where we would normally issue the start. - TWCR = _BV(TWINT) | _BV(TWSTA)| _BV(TWEN) ; - twi_state = TWI_READY; - } - break; - case TW_MR_SLA_NACK: // address sent, nack received - twi_stop(); - break; - // TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case - - // Slave Receiver - case TW_SR_SLA_ACK: // addressed, returned ack - case TW_SR_GCALL_ACK: // addressed generally, returned ack - case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack - case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration, returned ack - // enter slave receiver mode - twi_state = TWI_SRX; - // indicate that rx buffer can be overwritten and ack - twi_rxBufferIndex = 0; - twi_reply(1); - break; - case TW_SR_DATA_ACK: // data received, returned ack - case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack - // if there is still room in the rx buffer - if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ - // put byte in buffer and ack - twi_rxBuffer[twi_rxBufferIndex++] = TWDR; - twi_reply(1); - }else{ - // otherwise nack - twi_reply(0); - } - break; - case TW_SR_STOP: // stop or repeated start condition received - // put a null char after data if there's room - if(twi_rxBufferIndex < TWI_BUFFER_LENGTH){ - twi_rxBuffer[twi_rxBufferIndex] = '\0'; - } - // sends ack and stops interface for clock stretching - twi_stop(); - // callback to user defined callback - twi_onSlaveReceive(twi_rxBuffer, twi_rxBufferIndex); - // since we submit rx buffer to "wire" library, we can reset it - twi_rxBufferIndex = 0; - // ack future responses and leave slave receiver state - twi_releaseBus(); - break; - case TW_SR_DATA_NACK: // data received, returned nack - case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack - // nack back at master - twi_reply(0); - break; - - // Slave Transmitter - case TW_ST_SLA_ACK: // addressed, returned ack - case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack - // enter slave transmitter mode - twi_state = TWI_STX; - // ready the tx buffer index for iteration - twi_txBufferIndex = 0; - // set tx buffer length to be zero, to verify if user changes it - twi_txBufferLength = 0; - // request for txBuffer to be filled and length to be set - // note: user must call twi_transmit(bytes, length) to do this - twi_onSlaveTransmit(); - // if they didn't change buffer & length, initialize it - if(0 == twi_txBufferLength){ - twi_txBufferLength = 1; - twi_txBuffer[0] = 0x00; - } - // transmit first byte from buffer, fall - case TW_ST_DATA_ACK: // byte sent, ack returned - // copy data to output register - TWDR = twi_txBuffer[twi_txBufferIndex++]; - // if there is more to send, ack, otherwise nack - if(twi_txBufferIndex < twi_txBufferLength){ - twi_reply(1); - }else{ - twi_reply(0); - } - break; - case TW_ST_DATA_NACK: // received nack, we are done - case TW_ST_LAST_DATA: // received ack, but we are done already! - // ack future responses - twi_reply(1); - // leave slave receiver state - twi_state = TWI_READY; - break; - - // All - case TW_NO_INFO: // no state information - break; - case TW_BUS_ERROR: // bus error, illegal stop/start - twi_error = TW_BUS_ERROR; - twi_stop(); - break; - } -} - diff --git a/platform/osd-merkur/dev/old/twi.h b/platform/osd-merkur/dev/old/twi.h deleted file mode 100644 index 652659339..000000000 --- a/platform/osd-merkur/dev/old/twi.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - twi.h - TWI/I2C library for Wiring & Arduino - Copyright (c) 2006 Nicholas Zambetti. All right reserved. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef twi_h -#define twi_h - - #include - - //#define ATMEGA8 - - #ifndef TWI_FREQ - #define TWI_FREQ 100000L - #endif - - #ifndef TWI_BUFFER_LENGTH - #define TWI_BUFFER_LENGTH 32 - #endif - - #define TWI_READY 0 - #define TWI_MRX 1 - #define TWI_MTX 2 - #define TWI_SRX 3 - #define TWI_STX 4 - - void twi_init(void); - void twi_setAddress(uint8_t); - uint8_t twi_readFrom(uint8_t, uint8_t*, uint8_t, uint8_t); - uint8_t twi_writeTo(uint8_t, uint8_t*, uint8_t, uint8_t, uint8_t); - uint8_t twi_transmit(const uint8_t*, uint8_t); - void twi_attachSlaveRxEvent( void (*)(uint8_t*, int) ); - void twi_attachSlaveTxEvent( void (*)(void) ); - void twi_reply(uint8_t); - void twi_stop(void); - void twi_releaseBus(void); - -#endif - diff --git a/platform/seedeye/contiki-conf.h b/platform/seedeye/contiki-conf.h index 69c788381..d58ff686d 100644 --- a/platform/seedeye/contiki-conf.h +++ b/platform/seedeye/contiki-conf.h @@ -60,7 +60,7 @@ typedef uint16_t uip_stats_t; typedef uint32_t clock_time_t; typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_LT(a,b) ((int32_t)((a)-(b)) < 0) +#define RTIMER_CLOCK_DIFF(a,b) ((int32_t)((a)-(b))) #define RF_CHANNEL 13 diff --git a/platform/sky/cfs-coffee-arch.h b/platform/sky/cfs-coffee-arch.h index 08373c5e9..5eb183a42 100644 --- a/platform/sky/cfs-coffee-arch.h +++ b/platform/sky/cfs-coffee-arch.h @@ -59,7 +59,6 @@ #endif #define COFFEE_LOG_SIZE 1024 -#define COFFEE_IO_SEMANTICS 1 #define COFFEE_APPEND_ONLY 0 #define COFFEE_MICRO_LOGS 1 diff --git a/platform/sky/contiki-conf.h b/platform/sky/contiki-conf.h index ff4ad8578..7665d146e 100644 --- a/platform/sky/contiki-conf.h +++ b/platform/sky/contiki-conf.h @@ -150,10 +150,10 @@ /* configure number of neighbors and routes */ #ifndef NBR_TABLE_CONF_MAX_NEIGHBORS -#define NBR_TABLE_CONF_MAX_NEIGHBORS 20 +#define NBR_TABLE_CONF_MAX_NEIGHBORS 16 #endif /* NBR_TABLE_CONF_MAX_NEIGHBORS */ #ifndef UIP_CONF_MAX_ROUTES -#define UIP_CONF_MAX_ROUTES 20 +#define UIP_CONF_MAX_ROUTES 16 #endif /* UIP_CONF_MAX_ROUTES */ #define UIP_CONF_ND6_SEND_RA 0 @@ -179,9 +179,6 @@ #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 -#ifndef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS -#define SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS 5 -#endif /* SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS */ #else /* NETSTACK_CONF_WITH_IPV6 */ #define UIP_CONF_IP_FORWARD 1 #define UIP_CONF_BUFFER_SIZE 108 diff --git a/platform/sky/contiki-sky-main.c b/platform/sky/contiki-sky-main.c index ea3afd93a..7fe033900 100644 --- a/platform/sky/contiki-sky-main.c +++ b/platform/sky/contiki-sky-main.c @@ -330,7 +330,7 @@ main(int argc, char **argv) if(!UIP_CONF_IPV6_RPL) { uip_ipaddr_t ipaddr; int i; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); PRINTF("Tentative global IPv6 address "); diff --git a/platform/sky/platform-conf.h b/platform/sky/platform-conf.h index cb6ea0cba..5ba273047 100644 --- a/platform/sky/platform-conf.h +++ b/platform/sky/platform-conf.h @@ -80,7 +80,7 @@ /* Types for clocks and uip_stats */ typedef unsigned short uip_stats_t; typedef unsigned long clock_time_t; -typedef unsigned long off_t; +typedef long off_t; /* the low-level radio driver */ #define NETSTACK_CONF_RADIO cc2420_driver diff --git a/platform/srf06-cc26xx/README.md b/platform/srf06-cc26xx/README.md index 32071745c..04d66a0d4 100644 --- a/platform/srf06-cc26xx/README.md +++ b/platform/srf06-cc26xx/README.md @@ -7,6 +7,8 @@ platform supports two different boards: * SmartRF 06 Evaluation Board with a CC26xx or CC13xx Evaluation Module (relevant files and drivers are under `srf06/`) * CC2650 SensorTag 2.0 (relevant drivers under `sensortag/cc2650`) +* CC2650 LaunchPad (relevant drivers under `launchpad/cc2650`) +* CC1310 LaunchPad (relevant drivers under `launchpad/cc1310`) The CPU code, common for both platforms, can be found under `$(CONTIKI)/cpu/cc26xx-cc13xx`. The port was developed and tested with CC2650s, but the intention is for it to @@ -44,6 +46,10 @@ In terms of hardware support, the following drivers have been implemented: * OPT3001 sensor * Buzzer * External SPI flash +* LaunchPads + * LEDs + * Buttons + * External SPI flash Requirements ============ @@ -93,6 +99,8 @@ Other options for the `BOARD` make variable are: * Srf06+CC26xxEM: Set `BOARD=srf06/cc26xx` * Srf06+CC13xxEM: Set `BOARD=srf06/cc13xx` * CC2650 tag: Set `BOARD=sensortag/cc2650` +* CC2650 Launchpad: Set `BOARD=launchpad/cc2650` +* CC1310 Launchpad: Set `BOARD=launchpad/cc1310` If the `BOARD` variable is unspecified, an image for the Srf06 CC26XXEM will be built. @@ -101,6 +109,8 @@ errors. If you want to upload the compiled firmware to a node via the serial boot loader you need to manually enable the boot loader and then use `make cc26xx-demo.upload`. On the SmartRF06 board you enable the boot loader by resetting the board (EM RESET button) while holding the `select` button. (The boot loader backdoor needs to be enabled on the chip, and the chip needs to be configured correctly, for this to work. See README in the `tools/cc2538-bsl` directory for more info). The serial uploader script will automatically pick the first available serial port. If this is not the port where your node is connected, you can force the script to use a specific port by defining the `PORT` argument eg. `make cc26xx-demo.upload PORT=/dev/tty.usbserial` +The serial bootloader can also be used with the LaunchPad and the changes required to achieve this are the same as those required for the SmartRF. The only difference is that you will need to map `BL_PIN_NUMBER` to either the left or right user button (values to be used for `BL_PIN_NUMBER` in `ccfg.c` are `0x0D` and `0x0E` respectively). + Note that uploading over serial doesn't work for the Sensortag, you can use TI's SmartRF Flash Programmer in this case. For the `cc26xx-demo`, the included readme describes in detail what the example does. diff --git a/platform/srf06-cc26xx/sensortag/board-spi.c b/platform/srf06-cc26xx/common/board-spi.c similarity index 98% rename from platform/srf06-cc26xx/sensortag/board-spi.c rename to platform/srf06-cc26xx/common/board-spi.c index 960db75c8..fb9fecd63 100644 --- a/platform/srf06-cc26xx/sensortag/board-spi.c +++ b/platform/srf06-cc26xx/common/board-spi.c @@ -33,7 +33,7 @@ * @{ * * \file - * Board-specific SPI driver for the Sensortag-CC26xx + * Board-specific SPI driver common to the Sensortag and LaunchPad */ /*---------------------------------------------------------------------------*/ #include "contiki.h" @@ -120,7 +120,7 @@ board_spi_open(uint32_t bit_rate, uint32_t clk_pin) /* First, make sure the SERIAL PD is on */ ti_lib_prcm_power_domain_on(PRCM_DOMAIN_SERIAL); while((ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) - != PRCM_DOMAIN_POWER_ON)); + != PRCM_DOMAIN_POWER_ON)); /* Enable clock in active mode */ ti_lib_rom_prcm_peripheral_run_enable(PRCM_PERIPH_SSI0); diff --git a/platform/srf06-cc26xx/sensortag/board-spi.h b/platform/srf06-cc26xx/common/board-spi.h similarity index 89% rename from platform/srf06-cc26xx/sensortag/board-spi.h rename to platform/srf06-cc26xx/common/board-spi.h index 26bdff162..3699db120 100644 --- a/platform/srf06-cc26xx/sensortag/board-spi.h +++ b/platform/srf06-cc26xx/common/board-spi.h @@ -29,14 +29,22 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup sensortag-cc26xx-peripherals + * \addtogroup cc26xx-srf-tag * @{ * - * \defgroup sensortag-cc26xx-spi SensorTag 2.0 SPI functions + * \defgroup common-cc26xx-peripherals CC13xx/CC26xx peripheral driver pool + * + * Drivers for peripherals present on more than one CC13xx/CC26xx board. For + * example, the same external flash driver is used for both the part found on + * the Sensortag as well as the part on the LaunchPad. + * + * @{ + * + * \defgroup sensortag-cc26xx-spi SensorTag/LaunchPad SPI functions * @{ * * \file - * Header file for the Sensortag-CC26xx SPI Driver + * Header file for the Sensortag/LaunchPad SPI Driver */ /*---------------------------------------------------------------------------*/ #ifndef BOARD_SPI_H_ @@ -100,6 +108,7 @@ bool board_spi_write(const uint8_t *buf, size_t length); #endif /* BOARD_SPI_H_ */ /*---------------------------------------------------------------------------*/ /** + * @} * @} * @} */ diff --git a/platform/srf06-cc26xx/sensortag/ext-flash.c b/platform/srf06-cc26xx/common/ext-flash.c similarity index 96% rename from platform/srf06-cc26xx/sensortag/ext-flash.c rename to platform/srf06-cc26xx/common/ext-flash.c index c35bd4d0f..62fea2288 100644 --- a/platform/srf06-cc26xx/sensortag/ext-flash.c +++ b/platform/srf06-cc26xx/common/ext-flash.c @@ -33,13 +33,16 @@ * @{ * * \file - * Driver for the Sensortag-CC26xx WinBond W25X20CL Flash + * Driver for the LaunchPad Flash and the Sensortag WinBond W25X20CL/W25X40CL */ /*---------------------------------------------------------------------------*/ #include "contiki.h" #include "ext-flash.h" #include "ti-lib.h" #include "board-spi.h" + +#include +#include /*---------------------------------------------------------------------------*/ /* Instruction codes */ @@ -72,8 +75,11 @@ /* Part specific constants */ #define BLS_DEVICE_ID_W25X20CL 0x11 #define BLS_DEVICE_ID_W25X40CL 0x12 +#define BLS_DEVICE_ID_MX25R8035F 0x14 +#define BLS_DEVICE_ID_MX25R1635F 0x15 -#define BLS_MANUFACTURER_ID 0xEF +#define BLS_WINBOND_MID 0xEF +#define BLS_MACRONIX_MID 0xC2 #define BLS_PROGRAM_PAGE_SIZE 256 #define BLS_ERASE_SECTOR_SIZE 4096 @@ -156,7 +162,7 @@ static uint8_t verify_part(void) { const uint8_t wbuf[] = { BLS_CODE_MDID, 0xFF, 0xFF, 0x00 }; - uint8_t rbuf[2] = {0, 0}; + uint8_t rbuf[2] = { 0, 0 }; bool ret; select_on_bus(); @@ -175,8 +181,10 @@ verify_part(void) return VERIFY_PART_ERROR; } - if(rbuf[0] != BLS_MANUFACTURER_ID || - (rbuf[1] != BLS_DEVICE_ID_W25X20CL && rbuf[1] != BLS_DEVICE_ID_W25X40CL)) { + if((rbuf[0] != BLS_WINBOND_MID && rbuf[0] != BLS_MACRONIX_MID) || + (rbuf[1] != BLS_DEVICE_ID_W25X20CL && rbuf[1] != BLS_DEVICE_ID_W25X40CL + && rbuf[1] != BLS_DEVICE_ID_MX25R8035F + && rbuf[1] != BLS_DEVICE_ID_MX25R1635F)) { return VERIFY_PART_POWERED_DOWN; } return VERIFY_PART_OK; diff --git a/platform/srf06-cc26xx/sensortag/ext-flash.h b/platform/srf06-cc26xx/common/ext-flash.h similarity index 95% rename from platform/srf06-cc26xx/sensortag/ext-flash.h rename to platform/srf06-cc26xx/common/ext-flash.h index 3038872cd..5f2717edb 100644 --- a/platform/srf06-cc26xx/sensortag/ext-flash.h +++ b/platform/srf06-cc26xx/common/ext-flash.h @@ -29,14 +29,14 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup sensortag-cc26xx-peripherals + * \addtogroup common-cc26xx-peripherals * @{ * - * \defgroup sensortag-cc26xx-ext-flash SensorTag 2.0 External Flash + * \defgroup sensortag-cc26xx-ext-flash SensorTag/LaunchPad External Flash * @{ * * \file - * Header file for the Sensortag-CC26xx External Flash Driver + * Header file for the Sensortag/LaunchPad External Flash Driver */ /*---------------------------------------------------------------------------*/ #ifndef EXT_FLASH_H_ diff --git a/platform/srf06-cc26xx/contiki-conf.h b/platform/srf06-cc26xx/contiki-conf.h index 79c1d479a..c1546f6a8 100644 --- a/platform/srf06-cc26xx/contiki-conf.h +++ b/platform/srf06-cc26xx/contiki-conf.h @@ -65,6 +65,14 @@ #define NETSTACK_CONF_RDC contikimac_driver #endif +/* + * Disable turning off HF oscillator when the radio is off: + * You need to set this in order to use TSCH, disable to save more energy. + */ +#ifndef CC2650_FAST_RADIO_STARTUP +#define CC2650_FAST_RADIO_STARTUP 0 +#endif + /* Configure NullRDC for when it's selected */ #define NULLRDC_CONF_802154_AUTOACK 1 @@ -325,10 +333,53 @@ typedef uint32_t uip_stats_t; /* * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define - * RTIMER_CLOCK_LT to override this + * RTIMER_CLOCK_DIFF to override this */ typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_LT(a, b) ((int32_t)((a) - (b)) < 0) +#define RTIMER_CLOCK_DIFF(a, b) ((int32_t)((a) - (b))) + +/* --------------------------------------------------------------------- */ +/* TSCH related defines */ + +/* Delay between GO signal and SFD */ +#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(81)) +/* Delay between GO signal and start listening. + * This value is so small because the radio is constantly on within each timeslot. */ +#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(15)) +/* Delay between the SFD finishes arriving and it is detected in software. + * Not important on this platform as it uses hardware timestamps for SFD */ +#define RADIO_DELAY_BEFORE_DETECT ((unsigned)US_TO_RTIMERTICKS(0)) + +/* Timer conversion; radio is running at 4 MHz */ +#define RADIO_TIMER_SECOND 4000000u +#if (RTIMER_SECOND % 256) || (RADIO_TIMER_SECOND % 256) +#error RADIO_TO_RTIMER macro must be fixed! +#endif +#define RADIO_TO_RTIMER(X) ((uint32_t)(((uint64_t)(X) * (RTIMER_SECOND / 256)) / (RADIO_TIMER_SECOND / 256))) +#define USEC_TO_RADIO(X) ((X) * 4) + +/* The PHY header (preamble + SFD, 4+1 bytes) duration is equivalent to 10 symbols */ +#define RADIO_IEEE_802154_PHY_HEADER_DURATION_USEC 160 + +/* Do not turn off TSCH within a timeslot: not enough time */ +#define TSCH_CONF_RADIO_ON_DURING_TIMESLOT 1 + +/* Disable TSCH frame filtering */ +#define TSCH_CONF_HW_FRAME_FILTERING 0 + +/* Use hardware timestamps */ +#ifndef TSCH_CONF_RESYNC_WITH_SFD_TIMESTAMPS +#define TSCH_CONF_RESYNC_WITH_SFD_TIMESTAMPS 1 +#define TSCH_CONF_TIMESYNC_REMOVE_JITTER 0 +#endif + +/* The drift compared to "true" 10ms slots. + Enable adaptive sync to enable compensation for this. */ +#define TSCH_CONF_BASE_DRIFT_PPM -977 + +/* 10 times per second */ +#define TSCH_CONF_ASSOCIATION_CHANNEL_SWITCH_FREQUENCY 10 + /** @} */ /*---------------------------------------------------------------------------*/ /* board.h assumes that basic configuration is done */ diff --git a/platform/srf06-cc26xx/contiki-main.c b/platform/srf06-cc26xx/contiki-main.c index 83b67118f..b3f5c37f7 100644 --- a/platform/srf06-cc26xx/contiki-main.c +++ b/platform/srf06-cc26xx/contiki-main.c @@ -32,12 +32,14 @@ * \addtogroup cc26xx-platforms * @{ * - * \defgroup cc26xx-srf-tag SmartRF+CC13xx/CC26xx EM and the CC2650 SensorTag + * \defgroup cc26xx-srf-tag SmartRF+CC13xx/CC26xx EM, CC2650 SensorTag and LaunchPads * * This platform supports a number of different boards: * - A standard TI SmartRF06EB with a CC26xx EM mounted on it * - A standard TI SmartRF06EB with a CC1310 EM mounted on it * - The new TI SensorTag2.0 + * - The TI CC2650 LaunchPad + * - The TI CC1310 LaunchPad * @{ */ #include "ti-lib.h" @@ -57,6 +59,7 @@ #include "uart.h" #include "sys/clock.h" #include "sys/rtimer.h" +#include "sys/node-id.h" #include "lib/sensors.h" #include "button-sensor.h" #include "dev/serial-line.h" @@ -66,6 +69,8 @@ #include /*---------------------------------------------------------------------------*/ +unsigned short node_id = 0; +/*---------------------------------------------------------------------------*/ /** \brief Board specific iniatialisation */ void board_init(void); /*---------------------------------------------------------------------------*/ @@ -121,6 +126,10 @@ set_rf_params(void) printf("%02x\n", linkaddr_node_addr.u8[i]); } #endif + + /* also set the global node id */ + node_id = short_addr; + printf(" Node ID: %d\n", node_id); } /*---------------------------------------------------------------------------*/ /** @@ -140,6 +149,11 @@ main(void) /* Set the LF XOSC as the LF system clock source */ oscillators_select_lf_xosc(); +#if CC2650_FAST_RADIO_STARTUP + /* Also request HF XOSC to start up */ + oscillators_request_hf_xosc(); +#endif + lpm_init(); board_init(); diff --git a/platform/srf06-cc26xx/launchpad/Makefile.launchpad b/platform/srf06-cc26xx/launchpad/Makefile.launchpad new file mode 100644 index 000000000..54bd81ced --- /dev/null +++ b/platform/srf06-cc26xx/launchpad/Makefile.launchpad @@ -0,0 +1,9 @@ +CFLAGS += -DBOARD_LAUNCHPAD=1 + +CONTIKI_TARGET_DIRS += launchpad common + +BOARD_SOURCEFILES += board.c launchpad-sensors.c leds-arch.c button-sensor.c +BOARD_SOURCEFILES += ext-flash.c board-spi.c + +### Signal that we can be programmed with cc2538-bsl +BOARD_SUPPORTS_BSL=1 diff --git a/platform/srf06-cc26xx/launchpad/board-peripherals.h b/platform/srf06-cc26xx/launchpad/board-peripherals.h new file mode 100644 index 000000000..3e1220234 --- /dev/null +++ b/platform/srf06-cc26xx/launchpad/board-peripherals.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015, 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-srf-tag + * @{ + * + * \defgroup launchpad-peripherals LaunchPad peripherals + * + * Defines related to LaunchPad peripherals. + * + * @{ + * + * \file + * Header file with definitions related to LaunchPad peripherals + * + * \note Do not include this file directly. + */ +/*---------------------------------------------------------------------------*/ +#ifndef BOARD_PERIPHERALS_H_ +#define BOARD_PERIPHERALS_H_ +/*---------------------------------------------------------------------------*/ +#include "ext-flash.h" +/*---------------------------------------------------------------------------*/ +#endif /* BOARD_PERIPHERALS_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/launchpad/board.c b/platform/srf06-cc26xx/launchpad/board.c new file mode 100644 index 000000000..6482212d8 --- /dev/null +++ b/platform/srf06-cc26xx/launchpad/board.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup launchpad-peripherals + * @{ + * + * \file + * LaunchPad-specific board initialisation driver + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "lib/sensors.h" +#include "lpm.h" +#include "ti-lib.h" +#include "board-peripherals.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +static void +wakeup_handler(void) +{ + /* Turn on the PERIPH PD */ + ti_lib_prcm_power_domain_on(PRCM_DOMAIN_PERIPH); + while((ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) + != PRCM_DOMAIN_POWER_ON)); +} +/*---------------------------------------------------------------------------*/ +/* + * Declare a data structure to register with LPM. + * We don't care about what power mode we'll drop to, we don't care about + * getting notified before deep sleep. All we need is to be notified when we + * wake up so we can turn power domains back on + */ +LPM_MODULE(launchpad_module, NULL, NULL, wakeup_handler, LPM_DOMAIN_NONE); +/*---------------------------------------------------------------------------*/ +static void +configure_unused_pins(void) +{ + uint32_t pins[] = { + BOARD_IOID_CS, BOARD_IOID_TDO, BOARD_IOID_TDI, BOARD_IOID_DIO12, + BOARD_IOID_DIO15, BOARD_IOID_DIO21, BOARD_IOID_DIO22, BOARD_IOID_DIO23, + BOARD_IOID_DIO24, BOARD_IOID_DIO25, BOARD_IOID_DIO26, BOARD_IOID_DIO27, + BOARD_IOID_DIO28, BOARD_IOID_DIO29, BOARD_IOID_DIO30, + IOID_UNUSED + }; + + uint32_t *pin; + + for(pin = pins; *pin != IOID_UNUSED; pin++) { + ti_lib_ioc_pin_type_gpio_input(*pin); + ti_lib_ioc_io_port_pull_set(*pin, IOC_IOPULL_DOWN); + } +} +/*---------------------------------------------------------------------------*/ +void +board_init() +{ + /* Disable global interrupts */ + bool int_disabled = ti_lib_int_master_disable(); + + /* Turn on relevant PDs */ + wakeup_handler(); + + /* Enable GPIO peripheral */ + ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_GPIO); + + /* Apply settings and wait for them to take effect */ + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + /* Make sure the external flash is in the lower power mode */ + ext_flash_init(); + + lpm_register_module(&launchpad_module); + + /* For unsupported peripherals, select a default pin configuration */ + configure_unused_pins(); + + /* Re-enable interrupt if initially enabled. */ + if(!int_disabled) { + ti_lib_int_master_enable(); + } +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/launchpad/button-sensor.c b/platform/srf06-cc26xx/launchpad/button-sensor.c new file mode 100644 index 000000000..d37369d0a --- /dev/null +++ b/platform/srf06-cc26xx/launchpad/button-sensor.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup launchpad-button-sensor + * @{ + * + * \file + * Driver for LaunchPad buttons + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/sensors.h" +#include "launchpad/button-sensor.h" +#include "gpio-interrupt.h" +#include "sys/timer.h" +#include "lpm.h" + +#include "ti-lib.h" + +#include +/*---------------------------------------------------------------------------*/ +#ifdef BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN +#define BUTTON_SENSOR_ENABLE_SHUTDOWN BUTTON_SENSOR_CONF_ENABLE_SHUTDOWN +#else +#define BUTTON_SENSOR_ENABLE_SHUTDOWN 1 +#endif +/*---------------------------------------------------------------------------*/ +#define BUTTON_GPIO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \ + IOC_IOPULL_UP | IOC_SLEW_DISABLE | \ + IOC_HYST_DISABLE | IOC_BOTH_EDGES | \ + IOC_INT_ENABLE | IOC_IOMODE_NORMAL | \ + IOC_NO_WAKE_UP | IOC_INPUT_ENABLE) +/*---------------------------------------------------------------------------*/ +#define DEBOUNCE_DURATION (CLOCK_SECOND >> 5) + +struct btn_timer { + struct timer debounce; + clock_time_t start; + clock_time_t duration; +}; + +static struct btn_timer left_timer, right_timer; +/*---------------------------------------------------------------------------*/ +static void +button_press_handler(uint8_t ioid) +{ + if(ioid == BOARD_IOID_KEY_LEFT) { + if(!timer_expired(&left_timer.debounce)) { + return; + } + + timer_set(&left_timer.debounce, DEBOUNCE_DURATION); + + /* + * Start press duration counter on press (falling), notify on release + * (rising) + */ + if(ti_lib_gpio_pin_read(BOARD_KEY_LEFT) == 0) { + left_timer.start = clock_time(); + left_timer.duration = 0; + } else { + left_timer.duration = clock_time() - left_timer.start; + sensors_changed(&button_left_sensor); + } + } + + if(ioid == BOARD_IOID_KEY_RIGHT) { + if(BUTTON_SENSOR_ENABLE_SHUTDOWN == 0) { + if(!timer_expired(&right_timer.debounce)) { + return; + } + + timer_set(&right_timer.debounce, DEBOUNCE_DURATION); + + /* + * Start press duration counter on press (falling), notify on release + * (rising) + */ + if(ti_lib_gpio_pin_read(BOARD_KEY_RIGHT) == 0) { + right_timer.start = clock_time(); + right_timer.duration = 0; + } else { + right_timer.duration = clock_time() - right_timer.start; + sensors_changed(&button_right_sensor); + } + } else { + lpm_shutdown(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP, IOC_WAKE_ON_LOW); + } + } +} +/*---------------------------------------------------------------------------*/ +static void +config_buttons(int type, int c, uint32_t key) +{ + switch(type) { + case SENSORS_HW_INIT: + ti_lib_gpio_event_clear(1 << key); + ti_lib_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG); + ti_lib_gpio_dir_mode_set((1 << key), GPIO_DIR_MODE_IN); + gpio_interrupt_register_handler(key, button_press_handler); + break; + case SENSORS_ACTIVE: + if(c) { + ti_lib_gpio_event_clear(1 << key); + ti_lib_ioc_port_configure_set(key, IOC_PORT_GPIO, BUTTON_GPIO_CFG); + ti_lib_gpio_dir_mode_set((1 << key), GPIO_DIR_MODE_IN); + ti_lib_ioc_int_enable(key); + } else { + ti_lib_ioc_int_disable(key); + } + break; + default: + break; + } +} +/*---------------------------------------------------------------------------*/ +static int +config_left(int type, int value) +{ + config_buttons(type, value, BOARD_IOID_KEY_LEFT); + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +config_right(int type, int value) +{ + config_buttons(type, value, BOARD_IOID_KEY_RIGHT); + + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type, uint32_t key_io_id) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + if(ti_lib_ioc_port_configure_get(key_io_id) & IOC_INT_ENABLE) { + return 1; + } + break; + default: + break; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value_left(int type) +{ + if(type == BUTTON_SENSOR_VALUE_STATE) { + return ti_lib_gpio_pin_read(BOARD_KEY_LEFT) == 0 ? + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + } else if(type == BUTTON_SENSOR_VALUE_DURATION) { + return (int)left_timer.duration; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value_right(int type) +{ + if(type == BUTTON_SENSOR_VALUE_STATE) { + return ti_lib_gpio_pin_read(BOARD_KEY_RIGHT) == 0 ? + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + } else if(type == BUTTON_SENSOR_VALUE_DURATION) { + return (int)right_timer.duration; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +status_left(int type) +{ + return status(type, BOARD_IOID_KEY_LEFT); +} +/*---------------------------------------------------------------------------*/ +static int +status_right(int type) +{ + return status(type, BOARD_IOID_KEY_RIGHT); +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(button_left_sensor, BUTTON_SENSOR, value_left, config_left, + status_left); +SENSORS_SENSOR(button_right_sensor, BUTTON_SENSOR, value_right, config_right, + status_right); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/launchpad/button-sensor.h b/platform/srf06-cc26xx/launchpad/button-sensor.h new file mode 100644 index 000000000..0c945d3f7 --- /dev/null +++ b/platform/srf06-cc26xx/launchpad/button-sensor.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup launchpad-peripherals + * @{ + * + * \defgroup launchpad-button-sensor LaunchPad Button Driver + * + * One of the buttons can be configured as general purpose or as an on/off key + * @{ + * + * \file + * Header file for the LaunchPad Button Driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef BUTTON_SENSOR_H_ +#define BUTTON_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define BUTTON_SENSOR "Button" +/*---------------------------------------------------------------------------*/ +#define BUTTON_SENSOR_VALUE_STATE 0 +#define BUTTON_SENSOR_VALUE_DURATION 1 + +#define BUTTON_SENSOR_VALUE_RELEASED 0 +#define BUTTON_SENSOR_VALUE_PRESSED 1 +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor button_left_sensor; +extern const struct sensors_sensor button_right_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* BUTTON_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/launchpad/cc1310/Makefile.cc1310 b/platform/srf06-cc26xx/launchpad/cc1310/Makefile.cc1310 new file mode 100644 index 000000000..8d3d2abd4 --- /dev/null +++ b/platform/srf06-cc26xx/launchpad/cc1310/Makefile.cc1310 @@ -0,0 +1,8 @@ +### Will allow the inclusion of the correct CPU makefile +CPU_FAMILY = cc13xx + +### Add to the source dirs +CONTIKI_TARGET_DIRS += launchpad/cc1310 + +### Include the common launchpad makefile +include $(PLATFORM_ROOT_DIR)/launchpad/Makefile.launchpad diff --git a/platform/srf06-cc26xx/launchpad/cc1310/board.h b/platform/srf06-cc26xx/launchpad/cc1310/board.h new file mode 100644 index 000000000..d6cfeeedb --- /dev/null +++ b/platform/srf06-cc26xx/launchpad/cc1310/board.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2016, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** \addtogroup launchpad-peripherals + * @{ + * + * \defgroup launchpad-cc1310-specific CC1310 LaunchPad Peripherals + * + * Defines related to the CC1310 LaunchPad + * + * This file provides connectivity information on LEDs, Buttons, UART and + * other peripherals + * + * This file is not meant to be modified by the user. + * @{ + * + * \file + * Header file with definitions related to the I/O connections on the TI + * CC1310 LaunchPad + * + * \note Do not include this file directly. It gets included by contiki-conf + * after all relevant directives have been set. + */ +/*---------------------------------------------------------------------------*/ +#ifndef BOARD_H_ +#define BOARD_H_ +/*---------------------------------------------------------------------------*/ +#include "ioc.h" +/*---------------------------------------------------------------------------*/ +/** + * \name LED configurations + * + * Those values are not meant to be modified by the user + * @{ + */ +/* Some files include leds.h before us, so we need to get rid of defaults in + * leds.h before we provide correct definitions */ +#undef LEDS_GREEN +#undef LEDS_YELLOW +#undef LEDS_RED +#undef LEDS_CONF_ALL + +#define LEDS_RED 1 +#define LEDS_GREEN 2 +#define LEDS_YELLOW LEDS_GREEN +#define LEDS_ORANGE LEDS_RED + +#define LEDS_CONF_ALL 3 + +/* Notify various examples that we have LEDs */ +#define PLATFORM_HAS_LEDS 1 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name LED IOID mappings + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_LED_1 IOID_6 +#define BOARD_IOID_LED_2 IOID_7 +#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) +#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) +#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name UART IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_UART_RX IOID_2 +#define BOARD_IOID_UART_TX IOID_3 +#define BOARD_IOID_UART_RTS IOID_18 +#define BOARD_IOID_UART_CTS IOID_19 +#define BOARD_UART_RX (1 << BOARD_IOID_UART_RX) +#define BOARD_UART_TX (1 << BOARD_IOID_UART_TX) +#define BOARD_UART_RTS (1 << BOARD_IOID_UART_RTS) +#define BOARD_UART_CTS (1 << BOARD_IOID_UART_CTS) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Button IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_KEY_LEFT IOID_13 +#define BOARD_IOID_KEY_RIGHT IOID_14 +#define BOARD_KEY_LEFT (1 << BOARD_IOID_KEY_LEFT) +#define BOARD_KEY_RIGHT (1 << BOARD_IOID_KEY_RIGHT) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief SPI IOID mappings + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_SPI_MOSI IOID_9 +#define BOARD_IOID_SPI_MISO IOID_8 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name External flash IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_FLASH_CS IOID_20 +#define BOARD_FLASH_CS (1 << BOARD_IOID_FLASH_CS) +#define BOARD_IOID_SPI_CLK_FLASH IOID_10 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief I2C IOID mappings + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_SCL IOID_4 +#define BOARD_IOID_SDA IOID_5 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief Remaining pins + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_CS IOID_11 +#define BOARD_IOID_TDO IOID_16 +#define BOARD_IOID_TDI IOID_17 +#define BOARD_IOID_DIO12 IOID_12 +#define BOARD_IOID_DIO15 IOID_15 +#define BOARD_IOID_DIO21 IOID_21 +#define BOARD_IOID_DIO22 IOID_22 +#define BOARD_IOID_DIO23 IOID_23 +#define BOARD_IOID_DIO24 IOID_24 +#define BOARD_IOID_DIO25 IOID_25 +#define BOARD_IOID_DIO26 IOID_26 +#define BOARD_IOID_DIO27 IOID_27 +#define BOARD_IOID_DIO28 IOID_28 +#define BOARD_IOID_DIO29 IOID_29 +#define BOARD_IOID_DIO30 IOID_30 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Device string used on startup + * @{ + */ +#define BOARD_STRING "TI CC1310 LaunchPad" + +/** @} */ +/*---------------------------------------------------------------------------*/ +#endif /* BOARD_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/launchpad/cc2650/Makefile.cc2650 b/platform/srf06-cc26xx/launchpad/cc2650/Makefile.cc2650 new file mode 100644 index 000000000..72e50de3a --- /dev/null +++ b/platform/srf06-cc26xx/launchpad/cc2650/Makefile.cc2650 @@ -0,0 +1,8 @@ +### Will allow the inclusion of the correct CPU makefile +CPU_FAMILY = cc26xx + +### Add to the source dirs +CONTIKI_TARGET_DIRS += launchpad/cc2650 + +### Include the common launchpad makefile +include $(PLATFORM_ROOT_DIR)/launchpad/Makefile.launchpad diff --git a/platform/srf06-cc26xx/launchpad/cc2650/board.h b/platform/srf06-cc26xx/launchpad/cc2650/board.h new file mode 100644 index 000000000..a65ca5361 --- /dev/null +++ b/platform/srf06-cc26xx/launchpad/cc2650/board.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** \addtogroup launchpad-peripherals + * @{ + * + * \defgroup launchpad-cc26xx-specific CC2650 LaunchPad Peripherals + * + * Defines related to the CC2650 LaunchPad + * + * This file provides connectivity information on LEDs, Buttons, UART and + * other peripherals + * + * This file is not meant to be modified by the user. + * @{ + * + * \file + * Header file with definitions related to the I/O connections on the TI + * CC2650 LaunchPad + * + * \note Do not include this file directly. It gets included by contiki-conf + * after all relevant directives have been set. + */ +/*---------------------------------------------------------------------------*/ +#ifndef BOARD_H_ +#define BOARD_H_ +/*---------------------------------------------------------------------------*/ +#include "ioc.h" +/*---------------------------------------------------------------------------*/ +/** + * \name LED configurations + * + * Those values are not meant to be modified by the user + * @{ + */ +/* Some files include leds.h before us, so we need to get rid of defaults in + * leds.h before we provide correct definitions */ +#undef LEDS_GREEN +#undef LEDS_YELLOW +#undef LEDS_RED +#undef LEDS_CONF_ALL + +#define LEDS_RED 1 +#define LEDS_GREEN 2 +#define LEDS_YELLOW LEDS_GREEN +#define LEDS_ORANGE LEDS_RED + +#define LEDS_CONF_ALL 3 + +/* Notify various examples that we have LEDs */ +#define PLATFORM_HAS_LEDS 1 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name LED IOID mappings + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_LED_1 IOID_6 +#define BOARD_IOID_LED_2 IOID_7 +#define BOARD_LED_1 (1 << BOARD_IOID_LED_1) +#define BOARD_LED_2 (1 << BOARD_IOID_LED_2) +#define BOARD_LED_ALL (BOARD_LED_1 | BOARD_LED_2) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name UART IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_UART_RX IOID_2 +#define BOARD_IOID_UART_TX IOID_3 +#define BOARD_IOID_UART_RTS IOID_18 +#define BOARD_IOID_UART_CTS IOID_19 +#define BOARD_UART_RX (1 << BOARD_IOID_UART_RX) +#define BOARD_UART_TX (1 << BOARD_IOID_UART_TX) +#define BOARD_UART_RTS (1 << BOARD_IOID_UART_RTS) +#define BOARD_UART_CTS (1 << BOARD_IOID_UART_CTS) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Button IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_KEY_LEFT IOID_13 +#define BOARD_IOID_KEY_RIGHT IOID_14 +#define BOARD_KEY_LEFT (1 << BOARD_IOID_KEY_LEFT) +#define BOARD_KEY_RIGHT (1 << BOARD_IOID_KEY_RIGHT) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief SPI IOID mappings + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_SPI_MOSI IOID_9 +#define BOARD_IOID_SPI_MISO IOID_8 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name External flash IOID mapping + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_FLASH_CS IOID_20 +#define BOARD_FLASH_CS (1 << BOARD_IOID_FLASH_CS) +#define BOARD_IOID_SPI_CLK_FLASH IOID_10 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief I2C IOID mappings + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_SCL IOID_4 +#define BOARD_IOID_SDA IOID_5 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief Remaining pins + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_CS IOID_11 +#define BOARD_IOID_TDO IOID_16 +#define BOARD_IOID_TDI IOID_17 +#define BOARD_IOID_DIO12 IOID_12 +#define BOARD_IOID_DIO15 IOID_15 +#define BOARD_IOID_DIO21 IOID_21 +#define BOARD_IOID_DIO22 IOID_22 +#define BOARD_IOID_DIO23 IOID_23 +#define BOARD_IOID_DIO24 IOID_24 +#define BOARD_IOID_DIO25 IOID_25 +#define BOARD_IOID_DIO26 IOID_26 +#define BOARD_IOID_DIO27 IOID_27 +#define BOARD_IOID_DIO28 IOID_28 +#define BOARD_IOID_DIO29 IOID_29 +#define BOARD_IOID_DIO30 IOID_30 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Device string used on startup + * @{ + */ +#define BOARD_STRING "TI CC2650 LaunchPad" + +/** @} */ +/*---------------------------------------------------------------------------*/ +#endif /* BOARD_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/launchpad/launchpad-sensors.c b/platform/srf06-cc26xx/launchpad/launchpad-sensors.c new file mode 100644 index 000000000..c940ec68c --- /dev/null +++ b/platform/srf06-cc26xx/launchpad/launchpad-sensors.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup launchpad-peripherals + * @{ + * + * \file + * Generic module controlling LaunchPad sensors + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "launchpad/button-sensor.h" + +#include +/*---------------------------------------------------------------------------*/ +/** \brief Exports a global symbol to be used by the sensor API */ +SENSORS(&button_left_sensor, &button_right_sensor); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/launchpad/leds-arch.c b/platform/srf06-cc26xx/launchpad/leds-arch.c new file mode 100644 index 000000000..e853487fd --- /dev/null +++ b/platform/srf06-cc26xx/launchpad/leds-arch.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup launchpad-peripherals + * @{ + * + * \file + * Driver for LaunchPad LEDs + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/leds.h" + +#include "ti-lib.h" +/*---------------------------------------------------------------------------*/ +static unsigned char c; +static int inited = 0; +/*---------------------------------------------------------------------------*/ +void +leds_arch_init(void) +{ + if(inited) { + return; + } + inited = 1; + + ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_LED_1); + ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_LED_2); + + ti_lib_gpio_pin_write(BOARD_LED_ALL, 0); +} +/*---------------------------------------------------------------------------*/ +unsigned char +leds_arch_get(void) +{ + return c; +} +/*---------------------------------------------------------------------------*/ +void +leds_arch_set(unsigned char leds) +{ + c = leds; + ti_lib_gpio_pin_write(BOARD_LED_ALL, 0); + + if((leds & LEDS_RED) == LEDS_RED) { + ti_lib_gpio_pin_write(BOARD_LED_1, 1); + } + if((leds & LEDS_YELLOW) == LEDS_YELLOW) { + ti_lib_gpio_pin_write(BOARD_LED_2, 1); + } +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/Makefile.sensortag b/platform/srf06-cc26xx/sensortag/Makefile.sensortag index a37f8dd05..68e4b007f 100644 --- a/platform/srf06-cc26xx/sensortag/Makefile.sensortag +++ b/platform/srf06-cc26xx/sensortag/Makefile.sensortag @@ -1,7 +1,7 @@ CFLAGS += -DBOARD_SENSORTAG=1 CFLAGS += -DBACKDOOR_IOID=0x00000000 -CONTIKI_TARGET_DIRS += sensortag +CONTIKI_TARGET_DIRS += sensortag common BOARD_SOURCEFILES += sensortag-sensors.c sensor-common.c BOARD_SOURCEFILES += bmp-280-sensor.c tmp-007-sensor.c opt-3001-sensor.c diff --git a/platform/srf06-cc26xx/sensortag/board-i2c.c b/platform/srf06-cc26xx/sensortag/board-i2c.c index 7783cf2f0..cf74e2a93 100644 --- a/platform/srf06-cc26xx/sensortag/board-i2c.c +++ b/platform/srf06-cc26xx/sensortag/board-i2c.c @@ -221,11 +221,11 @@ board_i2c_read(uint8_t *data, uint8_t len) } if(success) { + ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); while(ti_lib_i2c_master_busy(I2C0_BASE)); success = i2c_status(); if(success) { data[len - 1] = ti_lib_i2c_master_data_get(I2C0_BASE); - ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); while(ti_lib_i2c_master_bus_busy(I2C0_BASE)); } } @@ -285,11 +285,11 @@ board_i2c_write_read(uint8_t *wdata, uint8_t wlen, uint8_t *rdata, uint8_t rlen) } if(success) { + ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); while(ti_lib_i2c_master_busy(I2C0_BASE)); success = i2c_status(); if(success) { rdata[rlen - 1] = ti_lib_i2c_master_data_get(I2C0_BASE); - ti_lib_i2c_master_control(I2C0_BASE, I2C_MASTER_CMD_BURST_RECEIVE_FINISH); while(ti_lib_i2c_master_bus_busy(I2C0_BASE)); } } diff --git a/platform/srf06-cc26xx/srf06/Makefile.srf06 b/platform/srf06-cc26xx/srf06/Makefile.srf06 index 3459cbadc..44d115ec8 100644 --- a/platform/srf06-cc26xx/srf06/Makefile.srf06 +++ b/platform/srf06-cc26xx/srf06/Makefile.srf06 @@ -3,19 +3,7 @@ CFLAGS += -DBOARD_SMARTRF06EB=1 CONTIKI_TARGET_DIRS += srf06 BOARD_SOURCEFILES += leds-arch.c srf06-sensors.c button-sensor.c board.c +BOARD_SOURCEFILES += als-sensor.c -PYTHON = python -BSL_FLAGS += -e -w -v - -ifdef PORT - BSL_FLAGS += -p $(PORT) -endif - -BSL = $(CONTIKI)/tools/cc2538-bsl/cc2538-bsl.py - -%.upload: %.bin -ifeq ($(wildcard $(BSL)), ) - @echo "ERROR: Could not find the cc2538-bsl script. Did you run 'git submodule update --init' ?" -else - $(PYTHON) $(BSL) $(BSL_FLAGS) $< -endif +### Signal that we can be programmed with cc2538-bsl +BOARD_SUPPORTS_BSL=1 diff --git a/platform/srf06-cc26xx/srf06/als-sensor.c b/platform/srf06-cc26xx/srf06/als-sensor.c new file mode 100644 index 000000000..f149d16a1 --- /dev/null +++ b/platform/srf06-cc26xx/srf06/als-sensor.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016, University of Bristol - http://www.bris.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 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 srf06-common-peripherals + * @{ + * + * \file + * Driver for the SmartRF06EB ALS when a CC13xx/CC26xxEM is mounted on it + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/sensors.h" +#include "srf06/als-sensor.h" +#include "sys/timer.h" +#include "dev/adc-sensor.h" +#include "dev/aux-ctrl.h" + +#include "ti-lib.h" + +#include +/*---------------------------------------------------------------------------*/ +static aux_consumer_module_t als_aux = { + .clocks = AUX_WUC_ADI_CLOCK | AUX_WUC_ANAIF_CLOCK | AUX_WUC_SMPH_CLOCK +}; +/*---------------------------------------------------------------------------*/ +static int +config(int type, int enable) +{ + switch(type) { + case SENSORS_HW_INIT: + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ALS_PWR); + break; + case SENSORS_ACTIVE: + 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_gpio_dir_mode_set(BOARD_ALS_OUT, GPIO_DIR_MODE_IN); + + if(enable) { + ti_lib_gpio_pin_write(BOARD_ALS_PWR, 1); + aux_ctrl_register_consumer(&als_aux); + ti_lib_aux_adc_select_input(ADC_COMPB_IN_AUXIO7); + clock_delay_usec(2000); + } else { + ti_lib_gpio_pin_write(BOARD_ALS_PWR, 0); + aux_ctrl_unregister_consumer(&als_aux); + } + break; + default: + break; + } + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + int val; + + ti_lib_aux_adc_enable_sync(AUXADC_REF_VDDS_REL, AUXADC_SAMPLE_TIME_2P7_US, + AUXADC_TRIGGER_MANUAL); + ti_lib_aux_adc_gen_manual_trigger(); + val = ti_lib_aux_adc_read_fifo(); + ti_lib_aux_adc_disable(); + + return val; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(als_sensor, ALS_SENSOR, value, config, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/srf06/als-sensor.h b/platform/srf06-cc26xx/srf06/als-sensor.h new file mode 100644 index 000000000..5d70478f8 --- /dev/null +++ b/platform/srf06-cc26xx/srf06/als-sensor.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, University of Bristol - http://www.bris.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 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 srf06-common-peripherals + * @{ + * + * \file + * Header file for the SmartRF06EB + CC13xx/CC26xxEM ALS Driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef ALS_SENSOR_H_ +#define ALS_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define ALS_SENSOR "ALS" +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor als_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* ALS_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/srf06/board-peripherals.h b/platform/srf06-cc26xx/srf06/board-peripherals.h index d76936c2d..c709ec963 100644 --- a/platform/srf06-cc26xx/srf06/board-peripherals.h +++ b/platform/srf06-cc26xx/srf06/board-peripherals.h @@ -45,7 +45,7 @@ #ifndef BOARD_PERIPHERALS_H_ #define BOARD_PERIPHERALS_H_ /*---------------------------------------------------------------------------*/ -/* ToDo: Include things here */ +#include "als-sensor.h" /*---------------------------------------------------------------------------*/ #endif /* BOARD_PERIPHERALS_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/platform/srf06-cc26xx/srf06/board.c b/platform/srf06-cc26xx/srf06/board.c index 9f53e8ae8..15528f79a 100644 --- a/platform/srf06-cc26xx/srf06/board.c +++ b/platform/srf06-cc26xx/srf06/board.c @@ -46,6 +46,16 @@ #include /*---------------------------------------------------------------------------*/ static void +lpm_handler(uint8_t mode) +{ + /* Ambient light sensor (off, output low) */ + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ALS_PWR); + ti_lib_gpio_pin_write(BOARD_ALS_PWR, 0); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_ALS_OUT); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_ALS_OUT, IOC_NO_IOPULL); +} +/*---------------------------------------------------------------------------*/ +static void wakeup_handler(void) { /* Turn on the PERIPH PD */ @@ -60,7 +70,7 @@ wakeup_handler(void) * getting notified before deep sleep. All we need is to be notified when we * wake up so we can turn power domains back on */ -LPM_MODULE(srf_module, NULL, NULL, wakeup_handler, LPM_DOMAIN_NONE); +LPM_MODULE(srf_module, NULL, lpm_handler, wakeup_handler, LPM_DOMAIN_NONE); /*---------------------------------------------------------------------------*/ static void configure_unused_pins(void) @@ -72,12 +82,6 @@ configure_unused_pins(void) /* Accelerometer (PWR output low, CSn output, high) */ ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ACC_PWR); ti_lib_gpio_pin_write(BOARD_ACC_PWR, 0); - - /* Ambient light sensor (off, output low) */ - ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ALS_PWR); - ti_lib_gpio_pin_write(BOARD_ALS_PWR, 0); - ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_ALS_OUT); - ti_lib_ioc_io_port_pull_set(BOARD_IOID_ALS_OUT, IOC_NO_IOPULL); } /*---------------------------------------------------------------------------*/ void diff --git a/platform/srf06-cc26xx/srf06/srf06-sensors.c b/platform/srf06-cc26xx/srf06/srf06-sensors.c index 9f05c1917..5f65a0cb2 100644 --- a/platform/srf06-cc26xx/srf06/srf06-sensors.c +++ b/platform/srf06-cc26xx/srf06/srf06-sensors.c @@ -39,11 +39,12 @@ /*---------------------------------------------------------------------------*/ #include "contiki.h" #include "srf06/button-sensor.h" +#include "srf06/als-sensor.h" #include /*---------------------------------------------------------------------------*/ /** \brief Exports a global symbol to be used by the sensor API */ SENSORS(&button_select_sensor, &button_left_sensor, &button_right_sensor, - &button_up_sensor, &button_down_sensor); + &button_up_sensor, &button_down_sensor, &als_sensor); /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/platform/stm32nucleo-spirit1/README.md b/platform/stm32nucleo-spirit1/README.md index 80d178dfa..dcb29caf4 100644 --- a/platform/stm32nucleo-spirit1/README.md +++ b/platform/stm32nucleo-spirit1/README.md @@ -7,13 +7,13 @@ Maintainers and Contacts ======================== Long-term maintainers: -* Marco Grella, marco.grella@st.com, github user: [STclab](https://github.com/STclab) -* Alok Mittal, alok.mittal@st.com, github user: [STclab](https://github.com/STclab) -* Indar Prakash Singhal, indar.singhal@st.com, github user: [STclab](https://github.com/STclab) +* Marco Grella, marco.grella@st.com, github user: [mgrella](https://github.com/mgrella) +* Alok Mittal, alok.mittal@st.com, github user: [alokclab](https://github.com/alokclab) +* Indar Prakash Singhal, indar.singhal@st.com, github user: [indars](https://github.com/indars) Contributors: * David Siorpaes, david.siorpaes@st.com, github user: [siorpaes](https://github.com/siorpaes) -* Luca Celetto, luca.celetto@st.com +* Luca Celetto, luca.celetto@st.com, github user: [luckyluke72](https://github.com/luckyluke72) Port Feature ============ @@ -25,11 +25,18 @@ The port supports the following boards from ST: - X-NUCLEO-IKS01A1 featuring motion MEMS and environmental sensors (optional) The following drivers are included: -- LEDs and buttons (user, reset) +- LEDs and user button - USB - SPIRIT1 sub-1GHz transceiver - HTS221, LIS3MDL, LPS25HB, LSM6DS0 sensors +Documentation +============= + +- User Manual: UM2000 "Getting started with the Contiki OS/6LoWPAN on STM32 Nucleo with SPIRIT1 and sensors expansion boards" +- Quick Start Guide (presentation): "Contiki 6LoWPAN Quick Guide" + +To access this documentation and other collaterals, please go to http://www.st.com and search for "STSW-CONTIKI6LP" part number. Hardware Requirements ===================== @@ -38,8 +45,7 @@ Hardware Requirements >The NUCLEO-L152RE board belongs to the STM32 Nucleo family. It features an STM32L152RET6 ultra-low power microcontroller based on ARM Cortex M3 MCU. -Detailed information on the NUCLEO-L152RE development board can be found at: -http://www.st.com/web/catalog/tools/FM116/SC959/SS1532/LN1847/PF260002 +For detailed information on the NUCLEO-L152RE development board, please go to http://www.st.com and search for the "NUCLEO-L152RE" part number. * X-NUCLEO-IDS01Ax sub-1GHz expansion board @@ -49,22 +55,15 @@ the module SPSGRF-868 or SPSGRF-915 based on SPIRIT1 low data rate, low power su >The user can select the X-NUCLEO-IDS01A4 board to operate the SPIRIT1 transceiver at 868MHz or the X-NUCLEO-IDS01A5 board to operate the SPIRIT1 transceiver at 915MHz. - >Detailed information on the X-NUCLEO-IDS01A4 expansion board can be found at: -http://www.st.com/web/catalog/tools/FM146/CL2167/SC2006/PF261982 - - >Detailed information on the X-NUCLEO-IDS01A5 expansion board can be found at: -http://www.st.com/web/catalog/tools/FM146/CL2167/SC2006/PF261983 - - >Detailed information on the SPIRIT1 sub-1GHz transceiver can be found at: -http://www.st.com/web/catalog/sense_power/FM2185/SC1845/PF253167 +>For detailed information on the X-NUCLEO-IDS01A4 or X-NUCLEO-IDS01A5 expansion board, or the SPIRIT1 transceiver please go to http://www.st.com and search for the specific part number. + * X-NUCLEO-IKS01A1, motion MEMS and environmental sensors expansion board (OPTIONAL) >The X-NUCLEO-IKS01A1 is a motion MEMS and environmental sensor evaluation board. The use of this board is optional in the stm32nucleo-spirit1 Contiki platform. - >Detailed information on the X-NUCLEO-IKS01A1 expansion board can be found at: -http://www.st.com/web/catalog/tools/FM146/CL2167/SC2006/PF261191 + >For detailed information on the X-NUCLEO-IKS01A1 expansion board, please go to http://www.st.com and search for the "X-NUCLEO-IKS01A1" part number. * USB type A to Mini-B USB cable, to connect the STM32 Nucleo board to the PC @@ -76,17 +75,16 @@ The following software are needed: * ST port of Contiki for STM32 Nucleo and expansion boards. - >The port is automatically installed when both the Contiki and the submodule repository are cloned: the former hosts the Contiki distribution and the ST platform interface, the latter hosts the actual library. The following commands are needed to download the full porting: + >The port is automatically installed when both the Contiki and the submodule repository are cloned: the former hosts the Contiki distribution and the ST platform interface, the latter hosts the actual library. The following command downloads the full porting: + + git clone --recursive https://github.com/contiki-os/contiki + +Alternatively, if you cloned the contiki repository without the "--recursive" option, you can simply download the submodule repository with the following commands: - git clone https://github.com/STclab/contiki.git cd contiki/ - git checkout stm32nucleo-spirit1 git submodule init git submodule update - -Note: the first and third steps are required only if using the STclab GitHub repository, they won't be needed any more once the Pull Request is accepted. - The platform name is: stm32nucleo-spirit1 * A toolchain to build the firmware: The port has been developed and tested with GNU Tools @@ -158,10 +156,3 @@ automatically created when plugging the STM32 Nucleo board to the PC. 6. Reset the MCU by using the reset button on the STM32 Nucleo board - - - - - - - diff --git a/platform/stm32nucleo-spirit1/contiki-conf.h b/platform/stm32nucleo-spirit1/contiki-conf.h index 14baa8d97..9a97ab355 100644 --- a/platform/stm32nucleo-spirit1/contiki-conf.h +++ b/platform/stm32nucleo-spirit1/contiki-conf.h @@ -106,10 +106,6 @@ #define SICSLOWPAN_CONF_MAXAGE 4 #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 -#ifndef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS -#define SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS 5 -#endif /* SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS */ - #define UIP_CONF_ICMP_DEST_UNREACH 1 #define UIP_CONF_DHCP_LIGHT diff --git a/platform/stm32nucleo-spirit1/platform-conf.h b/platform/stm32nucleo-spirit1/platform-conf.h index dede0bdeb..0f2a0077b 100644 --- a/platform/stm32nucleo-spirit1/platform-conf.h +++ b/platform/stm32nucleo-spirit1/platform-conf.h @@ -78,7 +78,7 @@ #define CLOCK_CONF_SECOND 128 /* One tick: 62.5 ms */ -#define RTIMER_CLOCK_LT(a, b) ((signed short)((a) - (b)) < 0) +#define RTIMER_CLOCK_DIFF(a, b) ((signed short)((a) - (b))) /*---------------------------------------------------------------------------*/ typedef unsigned long clock_time_t; typedef unsigned long long rtimer_clock_t; diff --git a/platform/wismote/contiki-conf.h b/platform/wismote/contiki-conf.h index bcc6c10ca..f7150c5ff 100644 --- a/platform/wismote/contiki-conf.h +++ b/platform/wismote/contiki-conf.h @@ -157,9 +157,6 @@ #define SICSLOWPAN_CONF_MAXAGE 8 #endif /* SICSLOWPAN_CONF_FRAG */ #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 2 -#ifndef SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS -#define SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS 5 -#endif /* SICSLOWPAN_CONF_MAX_MAC_TRANSMISSIONS */ #else /* NETSTACK_CONF_WITH_IPV6 */ #define UIP_CONF_IP_FORWARD 1 #define UIP_CONF_BUFFER_SIZE 108 diff --git a/platform/wismote/contiki-wismote-main.c b/platform/wismote/contiki-wismote-main.c index d65ccaf1e..f2a41a48e 100644 --- a/platform/wismote/contiki-wismote-main.c +++ b/platform/wismote/contiki-wismote-main.c @@ -324,7 +324,7 @@ main(int argc, char **argv) if(!UIP_CONF_IPV6_RPL) { uip_ipaddr_t ipaddr; int i; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); printf("Tentative global IPv6 address "); diff --git a/platform/z1/contiki-z1-main.c b/platform/z1/contiki-z1-main.c index 45e97bde9..92a7b5bd7 100644 --- a/platform/z1/contiki-z1-main.c +++ b/platform/z1/contiki-z1-main.c @@ -77,7 +77,7 @@ static struct timer mgt_timer; #if NETSTACK_CONF_WITH_IPV4 #include "net/ip/uip.h" #include "net/ipv4/uip-fw.h" -#include "net/uip-fw-drv.h" +#include "net/ipv4/uip-fw-drv.h" #include "net/ipv4/uip-over-mesh.h" static struct uip_fw_netif slipif = { UIP_FW_NETIF(192, 168, 1, 2, 255, 255, 255, 255, slip_send) }; @@ -345,7 +345,7 @@ main(int argc, char **argv) if(!UIP_CONF_IPV6_RPL) { uip_ipaddr_t ipaddr; int i; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); printf("Tentative global IPv6 address "); diff --git a/platform/z1/dev/adxl345.c b/platform/z1/dev/adxl345.c index df653d7f8..49bf9b6e6 100644 --- a/platform/z1/dev/adxl345.c +++ b/platform/z1/dev/adxl345.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2010, Swedish Institute of Computer Science. + * Copyright (c) 2016, Zolertia * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,59 +30,52 @@ * This file is part of the Contiki operating system. * */ - +/*---------------------------------------------------------------------------*/ /** * \file * Device drivers for adxl345 accelerometer in Zolertia Z1. * \author * Marcus Lundén, SICS * Enric M. Calvo, Zolertia + * Antonio Lignan, Zolertia */ - - +/*---------------------------------------------------------------------------*/ #include #include "contiki.h" #include "adxl345.h" #include "cc2420.h" #include "i2cmaster.h" #include "isr_compat.h" - +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +static uint8_t enabled; +/*---------------------------------------------------------------------------*/ /* Callback pointers when interrupt occurs */ void (*accm_int1_cb)(uint8_t reg); void (*accm_int2_cb)(uint8_t reg); - -process_event_t int1_event, int2_event; - +/*---------------------------------------------------------------------------*/ /* Bitmasks for the interrupts */ static uint16_t int1_mask = 0, int2_mask = 0; -/* Keep track of when the interrupt was last seen in order to reduce the amount - of interrupts. Kind of like button debouncing. This can't be per int-pin, as - there can be several very different int per pin (eg tap && freefall). */ -// XXX Not used now, only one global timer. -//static volatile clock_time_t ints_lasttime[] = {0, 0, 0, 0, 0, 0, 0, 0}; +/* Default values for adxl345 at startup. + * This will be sent to the adxl345 in a + * stream at init to set it up in a default state + */ -/* Bitmasks and bit flag variable for keeping track of adxl345 status. */ -enum ADXL345_STATUSTYPES { - /* must be a bit and not more, not using 0x00. */ - INITED = 0x01, - RUNNING = 0x02, - STOPPED = 0x04, - LOW_POWER = 0x08, - AAA = 0x10, // available to extend this... - BBB = 0x20, // available to extend this... - CCC = 0x40, // available to extend this... - DDD = 0x80, // available to extend this... -}; -static enum ADXL345_STATUSTYPES _ADXL345_STATUS = 0x00; - -/* Default values for adxl345 at startup. This will be sent to the adxl345 in a - stream at init to set it up in a default state */ static uint8_t adxl345_default_settings[] = { /* Note, as the two first two bulks are to be written in a stream, they contain - the register address as first byte in that section. */ - /* 0--14 are in one stream, start at ADXL345_THRESH_TAP */ - ADXL345_THRESH_TAP, // XXX NB Register address, not register value!! + * the register address as first byte in that section. + * 0--14 are in one stream, start at ADXL345_THRESH_TAP + */ + /* XXX NB Register address, not register value!! */ + ADXL345_THRESH_TAP, ADXL345_THRESH_TAP_DEFAULT, ADXL345_OFSX_DEFAULT, ADXL345_OFSY_DEFAULT, @@ -98,7 +92,8 @@ static uint8_t adxl345_default_settings[] = { ADXL345_TAP_AXES_DEFAULT, /* 15--19 start at ADXL345_BW_RATE */ - ADXL345_BW_RATE, // XXX NB Register address, not register value!! + /* XXX NB Register address, not register value!! */ + ADXL345_BW_RATE, ADXL345_BW_RATE_DEFAULT, ADXL345_POWER_CTL_DEFAULT, ADXL345_INT_ENABLE_DEFAULT, @@ -108,61 +103,45 @@ static uint8_t adxl345_default_settings[] = { ADXL345_DATA_FORMAT_DEFAULT, ADXL345_FIFO_CTL_DEFAULT }; - - /*---------------------------------------------------------------------------*/ PROCESS(accmeter_process, "Accelerometer process"); /*---------------------------------------------------------------------------*/ -/* Write to a register. - args: - reg register to write to - val value to write -*/ - -void -accm_write_reg(uint8_t reg, uint8_t val) { +static void +accm_write_reg(uint8_t reg, uint8_t val) +{ uint8_t tx_buf[] = {reg, val}; i2c_transmitinit(ADXL345_ADDR); while (i2c_busy()); - PRINTFDEBUG("I2C Ready to TX\n"); + PRINTF("ADXL345: I2C Ready to TX\n"); i2c_transmit_n(2, tx_buf); while (i2c_busy()); - PRINTFDEBUG("WRITE_REG 0x%02X @ reg 0x%02X\n", val, reg); + PRINTF("ADXL345: WRITE_REG 0x%02X @ reg 0x%02X\n", val, reg); } /*---------------------------------------------------------------------------*/ -/* Write several registers from a stream. - args: - len number of bytes to read - data pointer to where the data is read from - - First byte in stream must be the register address to begin writing to. - The data is then written from second byte and increasing. */ - -void -accm_write_stream(uint8_t len, uint8_t *data) { +/* First byte in stream must be the register address to begin writing to. + * The data is then written from second byte and increasing. + */ +static void +accm_write_stream(uint8_t len, uint8_t *data) +{ i2c_transmitinit(ADXL345_ADDR); while (i2c_busy()); - PRINTFDEBUG("I2C Ready to TX(stream)\n"); + PRINTF("ADXL345: I2C Ready to TX(stream)\n"); i2c_transmit_n(len, data); // start tx and send conf reg while (i2c_busy()); - PRINTFDEBUG("WRITE_STR %u B to 0x%02X\n", len, data[0]); + PRINTF("ADXL345: WRITE_STR %u B to 0x%02X\n", len, data[0]); } /*---------------------------------------------------------------------------*/ -/* Read one register. - args: - reg what register to read - returns the value of the read register -*/ - -uint8_t -accm_read_reg(uint8_t reg) { +static uint8_t +accm_read_reg(uint8_t reg) +{ uint8_t retVal = 0; uint8_t rtx = reg; - PRINTFDEBUG("READ_REG 0x%02X\n", reg); + PRINTF("ADXL345: READ_REG 0x%02X\n", reg); /* transmit the register to read */ i2c_transmitinit(ADXL345_ADDR); @@ -178,19 +157,12 @@ accm_read_reg(uint8_t reg) { return retVal; } - /*---------------------------------------------------------------------------*/ -/* Read several registers in a stream. - args: - reg what register to start reading from - len number of bytes to read - whereto pointer to where the data is saved -*/ - -void -accm_read_stream(uint8_t reg, uint8_t len, uint8_t *whereto) { +static void +accm_read_stream(uint8_t reg, uint8_t len, uint8_t *whereto) +{ uint8_t rtx = reg; - PRINTFDEBUG("READ_STR %u B from 0x%02X\n", len, reg); + PRINTF("ADXL345: READ_STR %u B from 0x%02X\n", len, reg); /* transmit the register to start reading from */ i2c_transmitinit(ADXL345_ADDR); @@ -206,13 +178,15 @@ accm_read_stream(uint8_t reg, uint8_t len, uint8_t *whereto) { } /*---------------------------------------------------------------------------*/ -/* Read an axis of the accelerometer (x, y or z). Return value is a signed 10 bit int. - The resolution of the acceleration measurement can be increased up to 13 bit, but - will change the data format of this read out. Refer to the data sheet if so is - wanted/needed. */ - +/* Read an axis of the accelerometer (x, y or z). Return value is a signed + * 10 bit int. + * The resolution of the acceleration measurement can be increased up to 13 bit, + * but will change the data format of this read out. Refer to the data sheet if + * so is wanted/needed. + */ int16_t -accm_read_axis(enum ADXL345_AXIS axis){ +accm_read_axis(enum ADXL345_AXIS axis) +{ int16_t rd = 0; uint8_t tmp[2]; if(axis > Z_AXIS){ @@ -222,165 +196,144 @@ accm_read_axis(enum ADXL345_AXIS axis){ rd = (int16_t)(tmp[0] | (tmp[1]<<8)); return rd; } - /*---------------------------------------------------------------------------*/ -/* Sets the g-range, ie the range the accelerometer measures (ie 2g means -2 to +2 g - on every axis). Possible values: - ADXL345_RANGE_2G - ADXL345_RANGE_4G - ADXL345_RANGE_8G - ADXL345_RANGE_16G - Example: - accm_set_grange(ADXL345_RANGE_4G); - */ - -void -accm_set_grange(uint8_t grange){ - if(grange > ADXL345_RANGE_16G) { - // invalid g-range. - PRINTFDEBUG("ADXL grange invalid: %u\n", grange); - return; - } +int +accm_set_grange(uint8_t grange) +{ uint8_t tempreg = 0; - /* preserve the previous contents of the register */ - tempreg = (accm_read_reg(ADXL345_DATA_FORMAT) & 0xFC); // zero out the last two bits (grange) - tempreg |= grange; // set new range - accm_write_reg(ADXL345_DATA_FORMAT, tempreg); -} - -/*---------------------------------------------------------------------------*/ -/* Init the accelerometer: ports, pins, registers, interrupts (none enabled), I2C, - default threshold values etc. */ - -void -accm_init(void) { - if(!(_ADXL345_STATUS & INITED)){ - PRINTFDEBUG("ADXL345 init\n"); - _ADXL345_STATUS |= INITED; - accm_int1_cb = NULL; - accm_int2_cb = NULL; - int1_event = process_alloc_event(); - int2_event = process_alloc_event(); - - /* Set up ports and pins for interrups. */ - ADXL345_DIR &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN); - ADXL345_SEL &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN); - ADXL345_SEL2 &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN); - - /* Set up ports and pins for I2C communication */ - i2c_enable(); - - /* set default register values. */ - accm_write_stream(15, &adxl345_default_settings[0]); - accm_write_stream(5, &adxl345_default_settings[15]); - accm_write_reg(ADXL345_DATA_FORMAT, adxl345_default_settings[20]); - accm_write_reg(ADXL345_FIFO_CTL, adxl345_default_settings[21]); - - process_start(&accmeter_process, NULL); - - /* Enable msp430 interrupts on the two interrupt pins. */ - dint(); - ADXL345_IES &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN); // low to high transition interrupts - ADXL345_IE |= (ADXL345_INT1_PIN | ADXL345_INT2_PIN); // enable interrupts - eint(); + if(grange > ADXL345_RANGE_16G) { + PRINTF("ADXL345: grange invalid: %u\n", grange); + return ADXL345_ERROR; } + + if(!enabled) { + return ADXL345_ERROR; + } + + /* Keep the previous contents of the register, zero out the last two bits */ + tempreg = (accm_read_reg(ADXL345_DATA_FORMAT) & 0xFC); + tempreg |= grange; + accm_write_reg(ADXL345_DATA_FORMAT, tempreg); + return ADXL345_SUCCESS; } /*---------------------------------------------------------------------------*/ -/* Map interrupt (FF, tap, dbltap etc) to interrupt pin (IRQ_INT1, IRQ_INT2). - This must come after accm_init() as the registers will otherwise be overwritten. */ - void -accm_set_irq(uint8_t int1, uint8_t int2){ +accm_init(void) +{ + PRINTF("ADXL345: init\n"); + accm_int1_cb = NULL; + accm_int2_cb = NULL; + + /* Set up ports and pins for interrups. */ + ADXL345_DIR &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN); + ADXL345_SEL &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN); + ADXL345_SEL2 &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN); + + /* Set up ports and pins for I2C communication */ + i2c_enable(); + + /* set default register values. */ + accm_write_stream(15, &adxl345_default_settings[0]); + accm_write_stream(5, &adxl345_default_settings[15]); + accm_write_reg(ADXL345_DATA_FORMAT, adxl345_default_settings[20]); + accm_write_reg(ADXL345_FIFO_CTL, adxl345_default_settings[21]); + + process_start(&accmeter_process, NULL); + + /* Enable msp430 interrupts on the two interrupt pins. */ + dint(); + /* low to high transition interrupts */ + ADXL345_IES &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN); + /* enable interrupts */ + ADXL345_IE |= (ADXL345_INT1_PIN | ADXL345_INT2_PIN); + eint(); + + enabled = 1; +} +/*---------------------------------------------------------------------------*/ +void +accm_stop(void) +{ + dint(); + ADXL345_IE &= ~(ADXL345_INT1_PIN | ADXL345_INT2_PIN); + accm_write_reg(ADXL345_INT_ENABLE, ~(int1_mask | int2_mask)); + accm_write_reg(ADXL345_INT_MAP, ~int2_mask); + eint(); + enabled = 0; +} +/*---------------------------------------------------------------------------*/ +int +accm_set_irq(uint8_t int1, uint8_t int2) +{ + if(!enabled) { + return ADXL345_ERROR; + } + /* Set the corresponding interrupt mapping to INT1 or INT2 */ - PRINTFDEBUG("IRQs set to INT1: 0x%02X IRQ2: 0x%02X\n", int1, int2); + PRINTF("ADXL345: IRQs set to INT1: 0x%02X IRQ2: 0x%02X\n", int1, int2); int1_mask = int1; int2_mask = int2; accm_write_reg(ADXL345_INT_ENABLE, (int1 | int2)); - accm_write_reg(ADXL345_INT_MAP, int2); // int1 bits are zeroes in the map register so this is for both ints + /* int1 bits are zeroes in the map register so this is for both ints */ + accm_write_reg(ADXL345_INT_MAP, int2); + return ADXL345_SUCCESS; } - -/*---------------------------------------------------------------------------*/ -#if 0 -/* now unused code that is later supposed to be turned into keeping track of every - interrupt by themselves instead of only one per INT1/2 */ - -/* XXX MUST HAVE some way of resetting the time so that we are not suppressing - erronous due to clock overflow.... XXX XXX XXX */ -/* Table with back off time periods */ -static volatile clock_time_t ints_backoffs[] = {ADXL345_INT_OVERRUN_BACKOFF, ADXL345_INT_WATERMARK_BACKOFF, - ADXL345_INT_FREEFALL_BACKOFF, ADXL345_INT_INACTIVITY_BACKOFF, - ADXL345_INT_ACTIVITY_BACKOFF, ADXL345_INT_DOUBLETAP_BACKOFF, - ADXL345_INT_TAP_BACKOFF, ADXL345_INT_DATAREADY_BACKOFF}; - -/*---------------------------------------------------------------------------*/ -/* Checks to see if an event occurred after backoff period (returns time period - past since) or not (returns 0) */ - -static clocktime_t -backoff_passed(clocktime_t happenedAt, const clocktime_t backoff){ - if(timenow-lasttime >= backoff) { - return 0; - } else { - return (timenow-lasttime); - } -} -#endif /*---------------------------------------------------------------------------*/ /* Invoked after an interrupt happened. Reads the interrupt source reg at the - accelerometer, which resets the interrupts, and invokes the corresponding - callback. It passes the source register value so the callback can determine - what interrupt happened, if several interrupts are mapped to the same pin. */ - + * accelerometer, which resets the interrupts, and invokes the corresponding + * callback. It passes the source register value so the callback can determine + * what interrupt happened, if several interrupts are mapped to the same pin. + */ static void -poll_handler(void){ +poll_handler(void) +{ uint8_t ireg = 0; ireg = accm_read_reg(ADXL345_INT_SOURCE); - //printf("0x%02X, 0x%02X, 0x%02X, 0x%02X\n", ireg, ireg2, int1_mask, int2_mask); /* Invoke callbacks for the corresponding interrupts */ if(ireg & int1_mask){ if(accm_int1_cb != NULL){ - PRINTFDEBUG("INT1 cb invoked\n"); + PRINTF("ADXL345: INT1 cb invoked\n"); accm_int1_cb(ireg); } } else if(ireg & int2_mask){ if(accm_int2_cb != NULL){ - PRINTFDEBUG("INT2 cb invoked\n"); + PRINTF("ADXL345: INT2 cb invoked\n"); accm_int2_cb(ireg); } } } - /*---------------------------------------------------------------------------*/ -/* This process is sleeping until an interrupt from the accelerometer occurs, which - polls this process from the interrupt service routine. */ - -PROCESS_THREAD(accmeter_process, ev, data) { +/* This process is sleeping until an interrupt from the accelerometer occurs, + * which polls this process from the interrupt service routine. */ +PROCESS_THREAD(accmeter_process, ev, data) +{ PROCESS_POLLHANDLER(poll_handler()); PROCESS_EXITHANDLER(); PROCESS_BEGIN(); while(1){ - PROCESS_WAIT_EVENT_UNTIL(0); // should do nothing in while loop. + PROCESS_WAIT_EVENT_UNTIL(0); } PROCESS_END(); } - /*---------------------------------------------------------------------------*/ -/* XXX This interrupt vector is shared with the interrupts from CC2420, so that - was moved here but should find a better home. XXX */ - -#if 1 +/* This interrupt vector is shared with the interrupts from CC2420, so that + * was moved here + */ static struct timer suppressTimer1, suppressTimer2; ISR(PORT1, port1_isr) { ENERGEST_ON(ENERGEST_TYPE_IRQ); - /* ADXL345_IFG.x goes high when interrupt occurs, use to check what interrupted */ - if ((ADXL345_IFG & ADXL345_INT1_PIN) && !(ADXL345_IFG & BV(CC2420_FIFOP_PIN))){ + + /* ADXL345_IFG.x goes high when interrupt occurs, use to check what + * interrupted + */ + if((ADXL345_IFG & ADXL345_INT1_PIN) && !(ADXL345_IFG & BV(CC2420_FIFOP_PIN))){ /* Check if this should be suppressed or not */ if(timer_expired(&suppressTimer1)) { timer_set(&suppressTimer1, SUPPRESS_TIME_INT1); @@ -388,11 +341,13 @@ ISR(PORT1, port1_isr) process_poll(&accmeter_process); LPM4_EXIT; } - } else if ((ADXL345_IFG & ADXL345_INT2_PIN) && !(ADXL345_IFG & BV(CC2420_FIFOP_PIN))){ + } else if((ADXL345_IFG & ADXL345_INT2_PIN) && + !(ADXL345_IFG & BV(CC2420_FIFOP_PIN))){ /* Check if this should be suppressed or not */ if(timer_expired(&suppressTimer2)) { timer_set(&suppressTimer2, SUPPRESS_TIME_INT2); - ADXL345_IFG &= ~ADXL345_INT2_PIN; // clear interrupt flag + /* clear interrupt flag */ + ADXL345_IFG &= ~ADXL345_INT2_PIN; process_poll(&accmeter_process); LPM4_EXIT; } @@ -404,7 +359,56 @@ ISR(PORT1, port1_isr) } ENERGEST_OFF(ENERGEST_TYPE_IRQ); } - /*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + if(type != SENSORS_ACTIVE) { + return ADXL345_ERROR; + } -#endif + if(value) { + accm_init(); + } else { + accm_stop(); + } + enabled = value; + return ADXL345_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + } + return ADXL345_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + if(!enabled) { + return ADXL345_ERROR; + } + + if((type != X_AXIS) && (type != Y_AXIS) && (type != Z_AXIS)) { + return ADXL345_ERROR; + } + + switch(type) { + case X_AXIS: + return accm_read_axis(X_AXIS); + case Y_AXIS: + return accm_read_axis(Y_AXIS); + case Z_AXIS: + return accm_read_axis(Z_AXIS); + default: + return ADXL345_ERROR; + } +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(adxl345, ADXL345_SENSOR, value, configure, status); +/*---------------------------------------------------------------------------*/ diff --git a/platform/z1/dev/adxl345.h b/platform/z1/dev/adxl345.h index 082572715..a8d4789d8 100644 --- a/platform/z1/dev/adxl345.h +++ b/platform/z1/dev/adxl345.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2010, Swedish Institute of Computer Science. + * Copyright (c) 2016, Zolertia * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,158 +30,106 @@ * This file is part of the Contiki operating system. * */ - +/*---------------------------------------------------------------------------*/ /** * \file * Device drivers header file for adxl345 accelerometer in Zolertia Z1. * \author * Marcus Lundén, SICS * Enric Calvo, Zolertia + * Antonio Lignan, Zolertia */ - +/*---------------------------------------------------------------------------*/ #ifndef ADXL345_H_ #define ADXL345_H_ #include #include "dev/i2cmaster.h" - -#define DEBUGLEDS 0 -#if DEBUGLEDS - #undef LEDS_ON(x) - #undef LEDS_OFF(x) - #define LEDS_ON(x) (LEDS_PxOUT &= ~x) - #define LEDS_OFF(x) (LEDS_PxOUT |= x) -#else - #undef LEDS_ON - #undef LEDS_OFF - #define LEDS_ON(x) - #define LEDS_OFF(x) -#endif - -#define LEDS_R 0x10 -#define LEDS_G 0x40 -#define LEDS_B 0x20 -#define L_ON(x) (LEDS_PxOUT &= ~x) -#define L_OFF(x) (LEDS_PxOUT |= x) - -/* Used in accm_read_axis(), eg accm_read_axis(X_AXIS);*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +/* Used in accm_read_axis(), eg accm_read_axis(X_AXIS) */ enum ADXL345_AXIS { X_AXIS = 0, Y_AXIS = 2, Z_AXIS = 4, }; - /* -------------------------------------------------------------------------- */ -/* Init the accelerometer: ports, pins, registers, interrupts (none enabled), I2C, - default threshold values etc. */ -void accm_init(void); +/* Init the accelerometer: ports, pins, registers, interrupts (none enabled), + * I2C, default threshold values etc. + */ +void accm_init(void); -/* Write to a register. - args: - reg register to write to - val value to write -*/ -void accm_write_reg(uint8_t reg, uint8_t val); - -/* Write several registers from a stream. - args: - len number of bytes to read - data pointer to where the data is read from - First byte in stream must be the register address to begin writing to. - The data is then written from the second byte and increasing. The address byte - is not included in length len. */ -void accm_write_stream(uint8_t len, uint8_t *data); - -/* Read one register. - args: - reg what register to read - returns the value of the read register -*/ -uint8_t accm_read_reg(uint8_t reg); - -/* Read several registers in a stream. - args: - reg what register to start reading from - len number of bytes to read - whereto pointer to where the data is saved -*/ -void accm_read_stream(uint8_t reg, uint8_t len, uint8_t *whereto); - -/* Read an axis of the accelerometer (x, y or z). Return value is a signed 10 bit int. - The resolution of the acceleration measurement can be increased up to 13 bit, but - will change the data format of this read out. Refer to the data sheet if so is - wanted/needed. */ +/* Read an axis of the accelerometer (x, y or z). Return value is a signed 10 + * bit int. + * The resolution of the acceleration measurement can be increased up to 13 bit, + * but will change the data format of this read out. Refer to the data sheet if + * so is wanted/needed. + */ int16_t accm_read_axis(enum ADXL345_AXIS axis); -/* Sets the g-range, ie the range the accelerometer measures (ie 2g means -2 to +2 g - on every axis). Possible values: - ADXL345_RANGE_2G - ADXL345_RANGE_4G - ADXL345_RANGE_8G - ADXL345_RANGE_16G - Example: - accm_set_grange(ADXL345_RANGE_4G); - */ -void accm_set_grange(uint8_t grange); +/* Sets the g-range, ie the range the accelerometer measures (ie 2g means -2 to + * +2 g on every axis). Possible values: + * - ADXL345_RANGE_2G + * - ADXL345_RANGE_4G + * - ADXL345_RANGE_8G + * - ADXL345_RANGE_16G + */ +int accm_set_grange(uint8_t grange); /* Map interrupt (FF, tap, dbltap etc) to interrupt pin (IRQ_INT1, IRQ_INT2). - This must come after accm_init() as the registers will otherwise be overwritten. */ -void accm_set_irq(uint8_t int1, uint8_t int2); + * This must come after accm_init() as the registers will otherwise be + * overwritten. + */ +int accm_set_irq(uint8_t int1, uint8_t int2); /* Macros for setting the pointers to callback functions from the interrupts. - The function will be called with an uint8_t as parameter, containing the interrupt - flag register from the ADXL345. That way, several interrupts can be mapped to - the same pin and be read from the */ + * The function will be called with an uint8_t as parameter, containing the + * interrupt flag register from the ADXL345. That way, several interrupts can be + * mapped to the same pin and be read + */ #define ACCM_REGISTER_INT1_CB(ptr) accm_int1_cb = ptr; #define ACCM_REGISTER_INT2_CB(ptr) accm_int2_cb = ptr; /* -------------------------------------------------------------------------- */ /* Application definitions, change if required by application. */ -/* Interrupt suppress periods */ -/* -// XXX Not used yet. -#define ADXL345_INT_OVERRUN_BACKOFF CLOCK_SECOND/8 -#define ADXL345_INT_WATERMARK_BACKOFF CLOCK_SECOND/8 -#define ADXL345_INT_FREEFALL_BACKOFF CLOCK_SECOND/8 -#define ADXL345_INT_INACTIVITY_BACKOFF CLOCK_SECOND/8 -#define ADXL345_INT_ACTIVITY_BACKOFF CLOCK_SECOND/8 -#define ADXL345_INT_DOUBLETAP_BACKOFF CLOCK_SECOND/8 -#define ADXL345_INT_TAP_BACKOFF CLOCK_SECOND/8 -#define ADXL345_INT_DATAREADY_BACKOFF CLOCK_SECOND/8 -*/ -/* Time after an interrupt that subsequent interrupts are suppressed. Should later - be turned into one specific time per type of interrupt (tap, freefall etc) */ +/* Time after an interrupt that subsequent interrupts are suppressed. Should + * later be turned into one specific time per type of interrupt (tap, freefall. + * etc) + */ #define SUPPRESS_TIME_INT1 CLOCK_SECOND/4 #define SUPPRESS_TIME_INT2 CLOCK_SECOND/4 /* Suggested defaults according to the data sheet etc */ -#define ADXL345_THRESH_TAP_DEFAULT 0x48 // 4.5g (0x30 == 3.0g) (datasheet: 3g++) -#define ADXL345_OFSX_DEFAULT 0x00 // for individual units calibration purposes +#define ADXL345_THRESH_TAP_DEFAULT 0x48 /* 4.5g (0x30 == 3.0g) */ +#define ADXL345_OFSX_DEFAULT 0x00 /* for calibration only */ #define ADXL345_OFSY_DEFAULT 0x00 #define ADXL345_OFSZ_DEFAULT 0x00 -#define ADXL345_DUR_DEFAULT 0x20 // 20 ms (datasheet: 10ms++) -#define ADXL345_LATENT_DEFAULT 0x50 // 100 ms (datasheet: 20ms++) -#define ADXL345_WINDOW_DEFAULT 0xFF // 320 ms (datasheet: 80ms++) -#define ADXL345_THRESH_ACT_DEFAULT 0x15 // 1.3g (62.5 mg/LSB) -#define ADXL345_THRESH_INACT_DEFAULT 0x08 // 0.5g (62.5 mg/LSB) -#define ADXL345_TIME_INACT_DEFAULT 0x02 // 2 s (1 s/LSB) -#define ADXL345_ACT_INACT_CTL_DEFAULT 0xFF // all axis involved, ac-coupled -#define ADXL345_THRESH_FF_DEFAULT 0x09 // 563 mg -#define ADXL345_TIME_FF_DEFAULT 0x20 // 160 ms -#define ADXL345_TAP_AXES_DEFAULT 0x07 // all axis, no suppression +#define ADXL345_DUR_DEFAULT 0x20 /* 20 ms (datasheet: 10ms++) */ +#define ADXL345_LATENT_DEFAULT 0x50 /* 100 ms (datasheet: 20ms++) */ +#define ADXL345_WINDOW_DEFAULT 0xFF /* 320 ms (datasheet: 80ms++) */ +#define ADXL345_THRESH_ACT_DEFAULT 0x15 /* 1.3g (62.5 mg/LSB) */ +#define ADXL345_THRESH_INACT_DEFAULT 0x08 /* 0.5g (62.5 mg/LSB) */ +#define ADXL345_TIME_INACT_DEFAULT 0x02 /* 2 s (1 s/LSB) */ +#define ADXL345_ACT_INACT_CTL_DEFAULT 0xFF /* all axis, ac-coupled */ +#define ADXL345_THRESH_FF_DEFAULT 0x09 /* 563 mg */ +#define ADXL345_TIME_FF_DEFAULT 0x20 /* 60 ms */ +#define ADXL345_TAP_AXES_DEFAULT 0x07 /* all axis, no suppression */ -#define ADXL345_BW_RATE_DEFAULT (0x00|ADXL345_SRATE_100) // 100 Hz, normal operation -#define ADXL345_POWER_CTL_DEFAULT 0x28 // link bit set, no autosleep, start normal measuring -#define ADXL345_INT_ENABLE_DEFAULT 0x00 // no interrupts enabled -#define ADXL345_INT_MAP_DEFAULT 0x00 // all mapped to int_1 +#define ADXL345_BW_RATE_DEFAULT (0x00 | ADXL345_SRATE_100) /* 100 Hz */ +/* link bit set, no autosleep, start normal measuring */ +#define ADXL345_POWER_CTL_DEFAULT 0x28 +#define ADXL345_INT_ENABLE_DEFAULT 0x00 /* no interrupts enabled */ +#define ADXL345_INT_MAP_DEFAULT 0x00 /* all mapped to int_1 */ /* XXX NB: In the data format register, data format of axis readings is chosen - between left or right justify. This affects the position of the MSB/LSB and is - different depending on g-range and resolution. If changed, make sure this is - reflected in the _read_axis() function. Also, the resolution can be increased - from 10 bit to at most 13 bit, but this also changes position of MSB etc on data - format so check this in read_axis() too. */ -#define ADXL345_DATA_FORMAT_DEFAULT (0x00|ADXL345_RANGE_2G) // right-justify, 2g, 10-bit mode, int is active high -#define ADXL345_FIFO_CTL_DEFAULT 0x00 // FIFO bypass mode + * between left or right justify. This affects the position of the MSB/LSB and is + * different depending on g-range and resolution. If changed, make sure this is + * reflected in the _read_axis() function. Also, the resolution can be increased + * from 10 bit to at most 13 bit, but this also changes position of MSB etc on data + * format so check this in read_axis() too. + */ +/* right-justify, 2g, 10-bit mode, int is active high */ +#define ADXL345_DATA_FORMAT_DEFAULT (0x00 | ADXL345_RANGE_2G) +#define ADXL345_FIFO_CTL_DEFAULT 0x00 /* FIFO bypass mode */ /* -------------------------------------------------------------------------- */ /* Reference definitions, should not be changed */ @@ -188,7 +137,7 @@ void accm_set_irq(uint8_t int1, uint8_t int2); #define ADXL345_ADDR 0x53 /* ADXL345 registers */ -#define ADXL345_DEVID 0x00 // read only +#define ADXL345_DEVID 0x00 /* registers 0x01 to 0x1C are reserved, do not access */ #define ADXL345_THRESH_TAP 0x1D #define ADXL345_OFSX 0x1E @@ -204,24 +153,24 @@ void accm_set_irq(uint8_t int1, uint8_t int2); #define ADXL345_THRESH_FF 0x28 #define ADXL345_TIME_FF 0x29 #define ADXL345_TAP_AXES 0x2A -#define ADXL345_ACT_TAP_STATUS 0x2B // read only +#define ADXL345_ACT_TAP_STATUS 0x2B #define ADXL345_BW_RATE 0x2C #define ADXL345_POWER_CTL 0x2D #define ADXL345_INT_ENABLE 0x2E #define ADXL345_INT_MAP 0x2F -#define ADXL345_INT_SOURCE 0x30 // read only +#define ADXL345_INT_SOURCE 0x30 #define ADXL345_DATA_FORMAT 0x31 -#define ADXL345_DATAX0 0x32 // read only, LSByte X, two's complement -#define ADXL345_DATAX1 0x33 // read only, MSByte X -#define ADXL345_DATAY0 0x34 // read only, LSByte Y -#define ADXL345_DATAY1 0x35 // read only, MSByte X -#define ADXL345_DATAZ0 0x36 // read only, LSByte Z -#define ADXL345_DATAZ1 0x37 // read only, MSByte X +#define ADXL345_DATAX0 0x32 /* read only, LSByte X, two's complement */ +#define ADXL345_DATAX1 0x33 /* read only, MSByte X */ +#define ADXL345_DATAY0 0x34 /* read only, LSByte Y */ +#define ADXL345_DATAY1 0x35 /* read only, MSByte X */ +#define ADXL345_DATAZ0 0x36 /* read only, LSByte Z */ +#define ADXL345_DATAZ1 0x37 /* read only, MSByte X */ #define ADXL345_FIFO_CTL 0x38 -#define ADXL345_FIFO_STATUS 0x39 // read only +#define ADXL345_FIFO_STATUS 0x39 /* read only */ /* ADXL345 interrupts */ -#define ADXL345_INT_DISABLE 0X00 // used for disabling interrupts +#define ADXL345_INT_DISABLE 0X00 /* used for disabling interrupts */ #define ADXL345_INT_OVERRUN 0X01 #define ADXL345_INT_WATERMARK 0X02 #define ADXL345_INT_FREEFALL 0X04 @@ -237,8 +186,8 @@ void accm_set_irq(uint8_t int1, uint8_t int2); #define ADXL345_REN P1REN #define ADXL345_SEL P1SEL #define ADXL345_SEL2 P1SEL2 -#define ADXL345_INT1_PIN (1<<6) // P1.6 -#define ADXL345_INT2_PIN (1<<7) // P1.7 +#define ADXL345_INT1_PIN (1<<6) /* P1.6 */ +#define ADXL345_INT2_PIN (1<<7) /* P1.7 */ #define ADXL345_IES P1IES #define ADXL345_IE P1IE #define ADXL345_IFG P1IFG @@ -251,43 +200,47 @@ void accm_set_irq(uint8_t int1, uint8_t int2); #define ADXL345_RANGE_16G 0x03 -/* The adxl345 has programmable sample rates, but unexpected results may occur if the wrong - rate and I2C bus speed is used (see datasheet p 17). Sample rates in Hz. This - setting does not change the internal sampling rate, just how often it is piped - to the output registers (ie the interrupt features use the full sample rate - internally). - - Example use: - adxl345_set_reg(ADXL345_BW_RATE, ((_ADXL345_STATUS & LOW_POWER) | ADXL345_SRATE_50)); - */ -#define ADXL345_SRATE_3200 0x0F // XXX NB don't use at all as I2C data rate<= 400kHz (see datasheet) -#define ADXL345_SRATE_1600 0x0E // XXX NB don't use at all as I2C data rate<= 400kHz (see datasheet) -#define ADXL345_SRATE_800 0x0D // when I2C data rate == 400 kHz -#define ADXL345_SRATE_400 0x0C // when I2C data rate == 400 kHz -#define ADXL345_SRATE_200 0x0B // when I2C data rate >= 100 kHz -#define ADXL345_SRATE_100 0x0A // when I2C data rate >= 100 kHz -#define ADXL345_SRATE_50 0x09 // when I2C data rate >= 100 kHz -#define ADXL345_SRATE_25 0x08 // when I2C data rate >= 100 kHz -#define ADXL345_SRATE_12_5 0x07 // 12.5 Hz, when I2C data rate >= 100 kHz -#define ADXL345_SRATE_6_25 0x06 // when I2C data rate >= 100 kHz -#define ADXL345_SRATE_3_13 0x05 // when I2C data rate >= 100 kHz -#define ADXL345_SRATE_1_56 0x04 // when I2C data rate >= 100 kHz -#define ADXL345_SRATE_0_78 0x03 // when I2C data rate >= 100 kHz -#define ADXL345_SRATE_0_39 0x02 // when I2C data rate >= 100 kHz -#define ADXL345_SRATE_0_20 0x01 // when I2C data rate >= 100 kHz -#define ADXL345_SRATE_0_10 0x00 // 0.10 Hz, when I2C data rate >= 100 kHz +/* The adxl345 has programmable sample rates, but unexpected results may occur + * if the wrong rate and I2C bus speed is used (see datasheet p 17). Sample + * rates in Hz. This setting does not change the internal sampling rate, just + * how often it is piped to the output registers (ie the interrupt features use + * the full sample rate internally). + * Example use: + * adxl345_set_reg(ADXL345_BW_RATE, ((_ADXL345_STATUS & LOW_POWER) + * | ADXL345_SRATE_50)); + */ +/* XXX NB don't use at all as I2C data rate<= 400kHz */ +#define ADXL345_SRATE_3200 0x0F +/* XXX NB don't use at all as I2C data rate<= 400kHz */ +#define ADXL345_SRATE_1600 0x0E +#define ADXL345_SRATE_800 0x0D /* when I2C data rate == 400 kHz */ +#define ADXL345_SRATE_400 0x0C /* when I2C data rate == 400 kHz */ +#define ADXL345_SRATE_200 0x0B /* when I2C data rate >= 100 kHz */ +#define ADXL345_SRATE_100 0x0A /* when I2C data rate >= 100 kHz */ +#define ADXL345_SRATE_50 0x09 /* when I2C data rate >= 100 kHz */ +#define ADXL345_SRATE_25 0x08 /* when I2C data rate >= 100 kHz */ +#define ADXL345_SRATE_12_5 0x07 /* 12.5 Hz, when I2C data rate >= 100 kHz */ +#define ADXL345_SRATE_6_25 0x06 /* when I2C data rate >= 100 kHz */ +#define ADXL345_SRATE_3_13 0x05 /* when I2C data rate >= 100 kHz */ +#define ADXL345_SRATE_1_56 0x04 /* when I2C data rate >= 100 kHz */ +#define ADXL345_SRATE_0_78 0x03 /* when I2C data rate >= 100 kHz */ +#define ADXL345_SRATE_0_39 0x02 /* when I2C data rate >= 100 kHz */ +#define ADXL345_SRATE_0_20 0x01 /* when I2C data rate >= 100 kHz */ +#define ADXL345_SRATE_0_10 0x00 /* 0.10 Hz, when I2C data rate >= 100 kHz */ +/* -------------------------------------------------------------------------- */ /* Callback pointers for the interrupts */ extern void (*accm_int1_cb)(uint8_t reg); extern void (*accm_int2_cb)(uint8_t reg); - -/* Interrupt 1 and 2 events; ADXL345 signals interrupt on INT1 or INT2 pins, - ISR is invoked and polls the accelerometer process which invokes the callbacks. */ -extern process_event_t int1_event, int2_event; // static ? - -#define ACCM_INT1 0x01 -#define ACCM_INT2 0x02 - - +/* -------------------------------------------------------------------------- */ +#define ACCM_INT1 0x01 +#define ACCM_INT2 0x02 +#define ADXL345_SUCCESS 0x00 +#define ADXL345_ERROR (-1) +/* -------------------------------------------------------------------------- */ +#define ADXL345_SENSOR "ADXL345 sensor" +/* -------------------------------------------------------------------------- */ +extern const struct sensors_sensor adxl345; +/* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ #endif /* ifndef ADXL345_H_ */ diff --git a/platform/z1/dev/tmp102.c b/platform/z1/dev/tmp102.c index cc9394b7b..4bf267246 100644 --- a/platform/z1/dev/tmp102.c +++ b/platform/z1/dev/tmp102.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2010, Swedish Institute of Computer Science. + * Copyright (c) 2016, Zolertia * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,65 +30,55 @@ * This file is part of the Contiki operating system. * */ - +/*---------------------------------------------------------------------------*/ /** * \file * Device drivers for tmp102 temperature sensor in Zolertia Z1. * \author * Enric M. Calvo, Zolertia * Marcus Lundén, SICS + * Antonio Lignan, Zolertia */ - +/*---------------------------------------------------------------------------*/ #include #include "contiki.h" #include "i2cmaster.h" #include "tmp102.h" - -/* Bitmasks and bit flag variable for keeping track of tmp102 status. */ -enum TMP102_STATUSTYPES { - /* must be a bit and not more, not using 0x00. */ - INITED = 0x01, - RUNNING = 0x02, - STOPPED = 0x04, - LOW_POWER = 0x08, - AAA = 0x10, /* available to extend this... */ - BBB = 0x20, /* available to extend this... */ - CCC = 0x40, /* available to extend this... */ - DDD = 0x80 /* available to extend this... */ -}; -static enum TMP102_STATUSTYPES _TMP102_STATUS = 0x00; - +#include "lib/sensors.h" /*---------------------------------------------------------------------------*/ -/* PROCESS(tmp102_process, "Temperature Sensor process"); */ - +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +static uint8_t enabled; /*---------------------------------------------------------------------------*/ -/* Init the temperature sensor: ports, pins, registers, interrupts (none enabled), I2C, - default threshold values etc. */ - void tmp102_init(void) { - if(!(_TMP102_STATUS & INITED)) { - PRINTFDEBUG("TMP102 init\n"); - _TMP102_STATUS |= INITED; - /* Power Up TMP102 via pin */ - TMP102_PWR_DIR |= TMP102_PWR_PIN; - TMP102_PWR_SEL &= ~TMP102_PWR_SEL; - TMP102_PWR_SEL2 &= ~TMP102_PWR_SEL; - TMP102_PWR_REN &= ~TMP102_PWR_SEL; - TMP102_PWR_OUT |= TMP102_PWR_PIN; + /* Power Up TMP102 via pin */ + TMP102_PWR_DIR |= TMP102_PWR_PIN; + TMP102_PWR_SEL &= ~TMP102_PWR_SEL; + TMP102_PWR_SEL2 &= ~TMP102_PWR_SEL; + TMP102_PWR_REN &= ~TMP102_PWR_SEL; + TMP102_PWR_OUT |= TMP102_PWR_PIN; - /* Set up ports and pins for I2C communication */ - i2c_enable(); - } + /* Set up ports and pins for I2C communication */ + i2c_enable(); + + enabled = 1; +} +/*---------------------------------------------------------------------------*/ +void +tmp102_stop(void) +{ + /* Power off */ + TMP102_PWR_OUT &= ~TMP102_PWR_PIN; + enabled = 0; } /*---------------------------------------------------------------------------*/ -/* Write to a 16-bit register. - args: - reg register to write to - val value to write - */ - void tmp102_write_reg(uint8_t reg, uint16_t val) { @@ -98,26 +89,20 @@ tmp102_write_reg(uint8_t reg, uint16_t val) i2c_transmitinit(TMP102_ADDR); while(i2c_busy()); - PRINTFDEBUG("I2C Ready to TX\n"); + PRINTF("I2C Ready to TX\n"); i2c_transmit_n(3, tx_buf); while(i2c_busy()); - PRINTFDEBUG("WRITE_REG 0x%04X @ reg 0x%02X\n", val, reg); + PRINTF("WRITE_REG 0x%04X @ reg 0x%02X\n", val, reg); } /*---------------------------------------------------------------------------*/ -/* Read register. - args: - reg what register to read - returns the value of the read register type uint16_t - */ - uint16_t tmp102_read_reg(uint8_t reg) { uint8_t buf[] = { 0x00, 0x00 }; uint16_t retVal = 0; uint8_t rtx = reg; - PRINTFDEBUG("READ_REG 0x%02X\n", reg); + PRINTF("READ_REG 0x%02X\n", reg); /* transmit the register to read */ i2c_transmitinit(TMP102_ADDR); @@ -136,19 +121,14 @@ tmp102_read_reg(uint8_t reg) return retVal; } /*---------------------------------------------------------------------------*/ -/* Read temperature in a raw format. Further processing will be needed - to make an interpretation of these 12 or 13-bit data, depending on configuration - */ - uint16_t tmp102_read_temp_raw(void) { uint16_t rd = 0; - rd = tmp102_read_reg(TMP102_TEMP); - return rd; } +/*---------------------------------------------------------------------------*/ int16_t tmp102_read_temp_x100(void) { @@ -167,24 +147,47 @@ tmp102_read_temp_x100(void) /* Integer part of the temperature value and percents*/ temp_int = (abstemp >> 8) * sign * 100; temp_int += ((abstemp & 0xff) * 100) / 0x100; - - /* See test-tmp102.c on how to print values of temperature with decimals - fractional part in 1/10000 of degree - temp_frac = ((abstemp >>4) % 16) * 625; - Data could be multiplied by 63 to have less bit-growth and 1/1000 precision - Data could be multiplied by 64 (<< 6) to trade-off precision for speed - */ - return temp_int; } /*---------------------------------------------------------------------------*/ -/* Simple Read temperature. Return is an integer with temperature in 1deg. precision - Return value is a signed 8 bit integer. - */ - int8_t tmp102_read_temp_simple(void) { /* Casted to int8_t: We don't expect temperatures outside -128 to 127 C */ return tmp102_read_temp_x100() / 100; } +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + if(type != SENSORS_ACTIVE) { + return TMP102_ERROR; + } + if(value) { + tmp102_init(); + } else { + tmp102_stop(); + } + enabled = value; + return TMP102_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + } + return TMP102_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + return (int)tmp102_read_temp_x100(); +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(tmp102, TMP102_SENSOR, value, configure, status); +/*---------------------------------------------------------------------------*/ diff --git a/platform/z1/dev/tmp102.h b/platform/z1/dev/tmp102.h index 777577747..cf7a71eb8 100644 --- a/platform/z1/dev/tmp102.h +++ b/platform/z1/dev/tmp102.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2010, Swedish Institute of Computer Science. + * Copyright (c) 2016, Zolertia * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,75 +33,47 @@ /** * \file - * Device drivers header file for tmp102 temperature sensor in Zolertia Z1 WSN Platform. + * Device drivers header file for tmp102 temperature sensor in Zolertia + * Z1 WSN Platform. * \author * Enric M. Calvo, Zolertia * Marcus Lundén, SICS + * Antonio Lignan, Zolertia */ - +/* -------------------------------------------------------------------------- */ #ifndef TMP102_H_ #define TMP102_H_ #include +#include "lib/sensors.h" #include "i2cmaster.h" - /* -------------------------------------------------------------------------- */ -/* Init the temperature sensor: ports, pins, I2C, interrupts (XXX none so far), -*/ -void tmp102_init(void); - -/* Write to a register. - args: - reg register to write to - val value to write -*/ -void tmp102_write_reg(uint8_t reg, uint16_t val); - -/* Read one register. - args: - reg what register to read - returns the value of the read register -*/ +void tmp102_init(void); +void tmp102_write_reg(uint8_t reg, uint16_t val); uint16_t tmp102_read_reg(uint8_t reg); - -/* Read temperature in raw format - no args needed -*/ uint16_t tmp102_read_temp_raw(); - -/* Read only integer part of the temperature in 1deg. precision. - no args needed -*/ int8_t tmp102_read_temp_simple(); - -/* Read only integer part of the temperature in 1deg. precision. - no args needed -*/ int16_t tmp102_read_temp_x100(); - /* -------------------------------------------------------------------------- */ -/* Reference definitions */ -/* TMP102 slave address */ #define TMP102_ADDR 0x48 - -/* TMP102 registers */ -#define TMP102_TEMP 0x00 // read only +#define TMP102_TEMP 0x00 #define TMP102_CONF 0x01 #define TMP102_TLOW 0x02 #define TMP102_THIGH 0x03 -/* TMP102 Ports */ -/* Accelerometer hardware ports, pins and registers on the msp430 µC */ +/* TMP102 pin-out */ #define TMP102_PWR_DIR P5DIR #define TMP102_PWR_SEL P5SEL #define TMP102_PWR_SEL2 P5SEL2 #define TMP102_PWR_REN P5REN #define TMP102_PWR_OUT P5OUT -#define TMP102_PWR_PIN (1<<0) // P5.0 -//#define TMP102_INT_PIN (1<<7) // P1.7 - - +#define TMP102_PWR_PIN (1<<0) /* P5.0 */ +/* -------------------------------------------------------------------------- */ +#define TMP102_SUCCESS 0 +#define TMP102_ERROR (-1) +#define TMP102_READ 0x01 +/* -------------------------------------------------------------------------- */ +#define TMP102_SENSOR "TMP102 sensor" +/* -------------------------------------------------------------------------- */ +extern const struct sensors_sensor tmp102; /* -------------------------------------------------------------------------- */ #endif /* ifndef TMP102_H_ */ - - - diff --git a/platform/zoul/contiki-conf.h b/platform/zoul/contiki-conf.h index cef99108c..59463f691 100644 --- a/platform/zoul/contiki-conf.h +++ b/platform/zoul/contiki-conf.h @@ -71,12 +71,20 @@ typedef uint32_t uip_stats_t; /* * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define - * RTIMER_CLOCK_LT to override this + * RTIMER_CLOCK_DIFF to override this */ typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_LT(a, b) ((int32_t)((a) - (b)) < 0) +#define RTIMER_CLOCK_DIFF(a, b) ((int32_t)((a) - (b))) /** @} */ /*---------------------------------------------------------------------------*/ +#define TSCH_CONF_HW_FRAME_FILTERING 0 + +/* 352us from calling transmit() until the SFD byte has been sent */ +#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(352)) +/* 192us as in datasheet but ACKs are not always received, so adjusted to 250us */ +#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(250)) +#define RADIO_DELAY_BEFORE_DETECT 0 +/*---------------------------------------------------------------------------*/ /** * \name Serial Boot Loader Backdoor configuration * @@ -101,7 +109,9 @@ typedef uint32_t rtimer_clock_t; * * @{ */ +#ifndef COFFEE_CONF_SIZE #define COFFEE_CONF_SIZE (4 * COFFEE_SECTOR_SIZE) +#endif /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -510,10 +520,10 @@ typedef uint32_t rtimer_clock_t; #define UIP_CONF_ND6_RETRANS_TIMER 10000 #ifndef NBR_TABLE_CONF_MAX_NEIGHBORS -#define NBR_TABLE_CONF_MAX_NEIGHBORS 20 +#define NBR_TABLE_CONF_MAX_NEIGHBORS 16 #endif #ifndef UIP_CONF_MAX_ROUTES -#define UIP_CONF_MAX_ROUTES 20 +#define UIP_CONF_MAX_ROUTES 16 #endif /* uIP */ @@ -540,8 +550,8 @@ typedef uint32_t rtimer_clock_t; #define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 1 #ifndef SICSLOWPAN_CONF_ADDR_CONTEXT_0 #define SICSLOWPAN_CONF_ADDR_CONTEXT_0 { \ - addr_contexts[0].prefix[0] = 0xaa; \ - addr_contexts[0].prefix[1] = 0xaa; \ + addr_contexts[0].prefix[0] = UIP_DS6_DEFAULT_PREFIX_0; \ + addr_contexts[0].prefix[1] = UIP_DS6_DEFAULT_PREFIX_1; \ } #endif diff --git a/platform/zoul/contiki-main.c b/platform/zoul/contiki-main.c index 80ca1ab21..0779681d0 100644 --- a/platform/zoul/contiki-main.c +++ b/platform/zoul/contiki-main.c @@ -65,6 +65,7 @@ #include "net/ip/tcpip.h" #include "net/ip/uip.h" #include "net/mac/frame802154.h" +#include "soc.h" #include "cpu.h" #include "reg.h" #include "ieee-addr.h" @@ -185,6 +186,9 @@ main(void) PUTS(CONTIKI_VERSION_STRING); PUTS(BOARD_STRING); +#if STARTUP_CONF_VERBOSE + soc_print_info(); +#endif /* Initialise the H/W RNG engine. */ random_init(0); @@ -218,9 +222,9 @@ main(void) #endif /* NETSTACK_CONF_WITH_IPV6 */ process_start(&sensors_process, NULL); - +#if PLATFORM_HAS_BUTTON SENSORS_ACTIVATE(button_sensor); - +#endif energest_init(); ENERGEST_ON(ENERGEST_TYPE_CPU); diff --git a/platform/zoul/dev/adc-sensors.c b/platform/zoul/dev/adc-sensors.c index c38455f19..6cc37fb4b 100644 --- a/platform/zoul/dev/adc-sensors.c +++ b/platform/zoul/dev/adc-sensors.c @@ -175,7 +175,7 @@ configure(int type, int value) return ADC_WRAPPER_ERROR; } - if((value < 0x01) || (value > 0x07) || (value == BUTTON_USER_PIN)) { + if((value < 0x01) || (value > 0x07) || ((value == BUTTON_USER_PIN) && (ADC_SENSORS_ADC6_PIN < 0))) { PRINTF("ADC sensors: invalid pin value, (PA0-PA1, PA3) are reserved\n"); return ADC_WRAPPER_ERROR; } diff --git a/platform/zoul/dev/adc-zoul.c b/platform/zoul/dev/adc-zoul.c index f31a303ed..f19daab48 100644 --- a/platform/zoul/dev/adc-zoul.c +++ b/platform/zoul/dev/adc-zoul.c @@ -93,6 +93,9 @@ get_channel_pin(int type) if((ZOUL_SENSORS_ADC5) && (type == ZOUL_SENSORS_ADC5)) { return SOC_ADC_ADCCON_CH_AIN0 + ADC_SENSORS_ADC5_PIN; } + if((ZOUL_SENSORS_ADC6) && (type == ZOUL_SENSORS_ADC6)) { + return SOC_ADC_ADCCON_CH_AIN0 + ADC_SENSORS_ADC6_PIN; + } return ZOUL_SENSORS_ERROR; } /*---------------------------------------------------------------------------*/ @@ -154,9 +157,12 @@ configure(int type, int value) if(value & ZOUL_SENSORS_ADC5) { ioc_set_over(GPIO_A_NUM, ADC_SENSORS_ADC5_PIN, IOC_OVERRIDE_ANA); } + if(value & ZOUL_SENSORS_ADC6) { + ioc_set_over(GPIO_A_NUM, ADC_SENSORS_ADC6_PIN, IOC_OVERRIDE_ANA); + } adc_init(); set_decimation_rate(SOC_ADC_ADCCON_DIV_512); - enabled_channels = value; + enabled_channels += value; break; case ZOUL_SENSORS_CONFIGURE_TYPE_DECIMATION_RATE: diff --git a/platform/zoul/dev/adc-zoul.h b/platform/zoul/dev/adc-zoul.h index d47da43c7..fca2643eb 100644 --- a/platform/zoul/dev/adc-zoul.h +++ b/platform/zoul/dev/adc-zoul.h @@ -38,7 +38,9 @@ * * Driver for the Zoul ADC interface * - * This driver supports analogue sensors connected to ADC1, ADC2 and AND3 inputs + * This driver supports analogue sensors connected to ADC1, ADC2, ADC3, + * ADC4, ADC5 and ADC6 inputs. ADC6 is shared with the user button, so disable + * user button if ADC6 is needed. * This is controlled by the type argument of the value() function. Possible * choices are: * @@ -47,6 +49,7 @@ * - ZOUL_SENSORS_ADC3 * - ZOUL_SENSORS_ADC4 * - ZOUL_SENSORS_ADC5 + * - ZOUL_SENSORS_ADC6 * * To initialize the ADC sensors use the configure() function, using as first * argument SENSORS_HW_INIT, and choose which ADC channels to enable passing as @@ -128,13 +131,20 @@ #else #define ZOUL_SENSORS_ADC5 0 #endif + +/* ADC phidget-like connector ADC6 */ +#if ADC_SENSORS_ADC6_PIN >= ZOUL_SENSORS_ADC_MIN +#define ZOUL_SENSORS_ADC6 GPIO_PIN_MASK(ADC_SENSORS_ADC6_PIN) +#else +#define ZOUL_SENSORS_ADC6 0 +#endif /* * This is safe as the disabled sensors should have a zero value thus not * affecting the mask operations */ #define ZOUL_SENSORS_ADC_ALL (ZOUL_SENSORS_ADC1 + ZOUL_SENSORS_ADC2 + \ ZOUL_SENSORS_ADC3 + ZOUL_SENSORS_ADC4 + \ - ZOUL_SENSORS_ADC5) + ZOUL_SENSORS_ADC5 + ZOUL_SENSORS_ADC6) /** @} */ /*---------------------------------------------------------------------------*/ extern const struct sensors_sensor adc_zoul; diff --git a/platform/zoul/dev/relay.c b/platform/zoul/dev/relay.c new file mode 100644 index 000000000..aa4f88dd5 --- /dev/null +++ b/platform/zoul/dev/relay.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2016, Zolertia - http://www.zolertia.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 Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup zoul-relay + * @{ + * + * \file + * Driver for a relay actuator + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "relay.h" +#include "dev/gpio.h" +#include "lib/sensors.h" +#include "dev/ioc.h" +/*---------------------------------------------------------------------------*/ +#define RELAY_PORT_BASE GPIO_PORT_TO_BASE(RELAY_PORT) +#define RELAY_PIN_MASK GPIO_PIN_MASK(RELAY_PIN) +/*---------------------------------------------------------------------------*/ +static uint8_t enabled; +/*---------------------------------------------------------------------------*/ +static int +relay_on(void) +{ + if(enabled) { + GPIO_SET_PIN(RELAY_PORT_BASE, RELAY_PIN_MASK); + return RELAY_SUCCESS; + } + return RELAY_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int +relay_off(void) +{ + if(enabled) { + GPIO_CLR_PIN(RELAY_PORT_BASE, RELAY_PIN_MASK); + return RELAY_SUCCESS; + } + return RELAY_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + return GPIO_READ_PIN(RELAY_PORT_BASE, RELAY_PIN_MASK); + case SENSORS_READY: + return enabled; + } + return RELAY_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + switch(type) { + case RELAY_OFF: + return relay_on(); + case RELAY_ON: + return relay_off(); + case RELAY_TOGGLE: + if(status(SENSORS_ACTIVE)) { + return relay_off(); + } else { + return relay_on(); + } + default: + return RELAY_ERROR; + } +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + if(type != SENSORS_ACTIVE) { + return RELAY_ERROR; + } + + if(value) { + GPIO_SOFTWARE_CONTROL(RELAY_PORT_BASE, RELAY_PIN_MASK); + GPIO_SET_OUTPUT(RELAY_PORT_BASE, RELAY_PIN_MASK); + ioc_set_over(RELAY_PORT, RELAY_PIN, IOC_OVERRIDE_OE); + GPIO_CLR_PIN(RELAY_PORT_BASE, RELAY_PIN_MASK); + enabled = 1; + return RELAY_SUCCESS; + } + + GPIO_SET_INPUT(RELAY_PORT_BASE, RELAY_PIN_MASK); + enabled = 0; + return RELAY_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(relay, RELAY_ACTUATOR, value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/zoul/dev/relay.h b/platform/zoul/dev/relay.h new file mode 100644 index 000000000..4123f9e99 --- /dev/null +++ b/platform/zoul/dev/relay.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2016, Zolertia - http://www.zolertia.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 Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup zoul-sensors + * @{ + * + * \defgroup zoul-relay Generic relay driver + * + * Driver for a generic relay driver + * @{ + * + * \file + * Header file for the generic relay driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef RELAY_H_ +#define RELAY_H_ +/* -------------------------------------------------------------------------- */ +/** + * \name Relay default pin and port + * @{ + */ +#ifdef RELAY_CONF_PIN +#define RELAY_PIN RELAY_CONF_PIN +#else +#define RELAY_PIN 5 +#endif +#ifdef RELAY_CONF_PORT +#define RELAY_PORT RELAY_CONF_PORT +#else +#define RELAY_PORT GPIO_A_NUM +#endif +/** @} */ +/* -------------------------------------------------------------------------- */ +/** + * \name Relay available commands + * @{ + */ +#define RELAY_OFF 0x00 +#define RELAY_ON 0x01 +#define RELAY_TOGGLE 0x02 +/** @} */ +/* -------------------------------------------------------------------------- */ +/** + * \name Relay return types + * @{ + */ +#define RELAY_ERROR (-1) +#define RELAY_SUCCESS 0x00 +/** @} */ +/* -------------------------------------------------------------------------- */ +#define RELAY_ACTUATOR "Generic Relay" +/* -------------------------------------------------------------------------- */ +extern const struct sensors_sensor relay; +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ +#endif /* RELAY_H_ */ +/* -------------------------------------------------------------------------- */ +/** + * @} + * @} + */ diff --git a/platform/zoul/dev/zonik.c b/platform/zoul/dev/zonik.c new file mode 100644 index 000000000..a087b620a --- /dev/null +++ b/platform/zoul/dev/zonik.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2016, Zolertia + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup remote-zonik + * @{ + * Driver for the RE-Mote Zonik sonometer board + * @{ + * \file + * Driver for the RE-Mote Zonik sound sensor (ZONIK) + * \author + * Aitor Mejias + */ +/*---------------------------------------------------------------------------*/ +#include +#include "contiki.h" +#include "dev/gpio.h" +#include "dev/i2c.h" +#include "zonik.h" +#include "sys/timer.h" +#include "sys/etimer.h" +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +#define ZONIK_INT1_PORT_BASE GPIO_PORT_TO_BASE(ZONIK_INT_PORT) +#define ZONIK_INT1_PIN_MASK GPIO_PIN_MASK(ZONIK_INT_PIN) +/*---------------------------------------------------------------------------*/ +static uint8_t zonik_buffer[ZONIK_FRAME_SIZE+1]; +static uint16_t zonik_status = ZONIK_DISABLED; +/*---------------------------------------------------------------------------*/ +static struct etimer et; +/*---------------------------------------------------------------------------*/ +PROCESS(zonik_stm_process, "Zonik process process handler"); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(zonik_stm_process, ev, data) +{ + #if DEBUG + static int i; + #endif + PROCESS_EXITHANDLER(); + PROCESS_BEGIN(); + + while(1) { + /* Wait a process */ + etimer_set(&et, ZONIK_SECOND_INTERVAL); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + /* Control the interrupt for activate the sensor */ + GPIO_SET_OUTPUT(ZONIK_INT1_PORT_BASE, ZONIK_INT1_PIN_MASK); + GPIO_CLR_PIN(ZONIK_INT1_PORT_BASE, ZONIK_INT1_PIN_MASK); + clock_delay_usec(ZONIK_INITIAL_WAIT_DELAY); + i2c_master_enable(); + if(i2c_single_send(ZONIK_ADDR, ZONIK_CMD_READ) != I2C_MASTER_ERR_NONE) { + zonik_status = ZONIK_ERROR; + PRINTF("Zonik: Error in I2C Communication\n"); + } + GPIO_SET_PIN(ZONIK_INT1_PORT_BASE, ZONIK_INT1_PIN_MASK); + GPIO_SET_INPUT(ZONIK_INT1_PORT_BASE, ZONIK_INT1_PIN_MASK); + if(zonik_status != ZONIK_ERROR) { + etimer_set(&et, ZONIK_WAIT_ACQ); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + clock_delay_usec(ZONIK_FINAL_WAIT_DELAY); + i2c_master_enable(); + if(i2c_burst_receive(ZONIK_ADDR, &zonik_buffer[0], ZONIK_FRAME_SIZE) != + I2C_MASTER_ERR_NONE) { + zonik_status = ZONIK_ERROR; + PRINTF("Zonik: Error in I2C Burst Mode Receive"); + } + #if DEBUG + PRINTF("\nZonik: "); + for(i=0; i + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ +/* -------------------------------------------------------------------------- */ +/** + * \addtogroup zoul-sensors + * @{ + * + * \defgroup remote-zonik Zonik sound sensor + * @{ + * + * \file + * Header file for the Zolertia Zonik sound sensor + */ +/* -------------------------------------------------------------------------- */ +#ifndef ZONIK_H_ +#define ZONIK_H_ +/* -------------------------------------------------------------------------- */ +#include +#include "lib/sensors.h" +#include "dev/zoul-sensors.h" +#include "i2c.h" +#include "sys/rtimer.h" +/* -------------------------------------------------------------------------- */ +/** \name ZONIK address and definitions + * @{ + */ +#define ZONIK_ADDR 0x68 +#define ZONIK_SENSOR "Zonik Sound Sensor" + +#define ZONIK_INITIAL_WAIT_DELAY 11000L +#define ZONIK_FINAL_WAIT_DELAY 22000L + +#ifndef ZONIK_INT_CONF_PORT +#define ZONIK_INT_PORT I2C_INT_PORT +#else +#define ZONIK_INT_PORT ZONIK_INT_CONF_PORT +#endif + +#ifndef ZONIK_INT_CONF_PIN +#define ZONIK_INT_PIN I2C_INT_PIN +#else +#define ZONIK_INT_PIN ZONIK_INT_CONF_PIN +#endif + +#define ZONIK_FRAME_SIZE 4 + +#define ZONIK_WAIT_ACQ (CLOCK_SECOND / 5) + +/* Zonik wait sensor delay: ~800ms */ +#define ZONIK_SECOND_INTERVAL 106 + +/** @} */ +/* -------------------------------------------------------------------------- */ +/** \name ZONIK error values and definitions + * @{ + */ +#define ZONIK_ACTIVE SENSORS_ACTIVE +#define ZONIK_HW_INIT SENSORS_HW_INIT +#define ZONIK_ENABLED 1 +#define ZONIK_VALUE_DEACTIVATE 0 +#define ZONIK_DISABLED 0xD1ED +#define ZONIK_ERROR (-1) +#define ZONIK_DBA_LEQ_VALUE 0x00 +#define ZONIK_COUNT_VALUE 0x01 +/** @} */ +/* -------------------------------------------------------------------------- */ +/** \name ZONIK command definitions + * @{ + */ +#define ZONIK_CMD_READ 0x01 +/** @} */ +/* -------------------------------------------------------------------------- */ +/** \name ZONIK sensor type + * @{ + */ +extern const struct sensors_sensor zonik; +/** @} */ +/* -------------------------------------------------------------------------- */ +#endif +/* -------------------------------------------------------------------------- */ +/** + * @} + * @} + */ diff --git a/platform/zoul/dev/zoul-sensors.c b/platform/zoul/dev/zoul-sensors.c index e6e02c258..da755fc79 100644 --- a/platform/zoul/dev/zoul-sensors.c +++ b/platform/zoul/dev/zoul-sensors.c @@ -47,7 +47,12 @@ #include /*---------------------------------------------------------------------------*/ /** \brief Exports global symbols for the sensor API */ -SENSORS(&button_sensor, &vdd3_sensor, &cc2538_temp_sensor); +SENSORS(&vdd3_sensor, +#if PLATFORM_HAS_BUTTON + &button_sensor, +#endif + &cc2538_temp_sensor +); /*---------------------------------------------------------------------------*/ /** * @} diff --git a/platform/zoul/firefly/board.h b/platform/zoul/firefly/board.h index 101a95706..7cf92b39c 100644 --- a/platform/zoul/firefly/board.h +++ b/platform/zoul/firefly/board.h @@ -168,6 +168,92 @@ #define UART1_RTS_PIN (-1) /**< 0 */ /** @} */ /*---------------------------------------------------------------------------*/ +/** + * \name ADC configuration + * + * These values configure which CC2538 pins and ADC channels to use for the ADC + * inputs. There pins are suggested as they can be changed, but note that only + * pins from PA can be configured as ADC. + * + * - ADC1: up to 3.3V. + * - ADC2: up to 3.3V. + * - ADC3: up to 3.3V. + * - ADC4: up to 3.3V. + * - ADC5: up to 3.3V. + * - ADC6: up to 3.3V, shared with user button. + * + * Only ADC1 and ADC3 are enabled as default. + * + * The internal ADC reference is 1190mV, use either a voltage divider as input, + * or a different voltage reference, like AVDD5 or other externally (AIN7 or + * AIN6). + * @{ + */ +#define ADC_SENSORS_PORT GPIO_A_NUM /**< ADC GPIO control port */ + +#ifndef ADC_SENSORS_CONF_ADC1_PIN +#define ADC_SENSORS_ADC1_PIN 5 /**< ADC1 to PA5 */ +#else +#if ((ADC_SENSORS_CONF_ADC1_PIN != -1) && (ADC_SENSORS_CONF_ADC1_PIN != 5)) +#error "ADC1 channel should be mapped to PA5 or disabled with -1" +#else +#define ADC_SENSORS_ADC1_PIN ADC_SENSORS_CONF_ADC1_PIN +#endif +#endif + +#ifndef ADC_SENSORS_CONF_ADC2_PIN +#define ADC_SENSORS_ADC2_PIN 4 /**< ADC2 to PA4 */ +#else +#if ((ADC_SENSORS_CONF_ADC2_PIN != -1) && (ADC_SENSORS_CONF_ADC2_PIN != 4)) +#error "ADC2 channel should be mapped to PA4 or disabled with -1" +#else +#define ADC_SENSORS_ADC2_PIN ADC_SENSORS_CONF_ADC2_PIN +#endif +#endif + +#ifndef ADC_SENSORS_CONF_ADC3_PIN +#define ADC_SENSORS_ADC3_PIN 2 /**< ADC3 to PA2 */ +#else +#if ((ADC_SENSORS_CONF_ADC3_PIN != -1) && (ADC_SENSORS_CONF_ADC3_PIN != 2)) +#error "ADC3 channel should be mapped to PA2 or disabled with -1" +#else +#define ADC_SENSORS_ADC3_PIN ADC_SENSORS_CONF_ADC3_PIN +#endif +#endif + +#ifndef ADC_SENSORS_CONF_ADC4_PIN +#define ADC_SENSORS_ADC4_PIN 6 /**< ADC4 to PA6 */ +#else +#if ((ADC_SENSORS_CONF_ADC4_PIN != -1) && (ADC_SENSORS_CONF_ADC4_PIN != 6)) +#error "ADC4 channel should be mapped to PA6 or disabled with -1" +#else +#define ADC_SENSORS_ADC4_PIN ADC_SENSORS_CONF_ADC4_PIN +#endif +#endif + +#ifndef ADC_SENSORS_CONF_ADC5_PIN +#define ADC_SENSORS_ADC5_PIN 7 /**< ADC5 to PA7 */ +#else +#if ((ADC_SENSORS_CONF_ADC5_PIN != -1) && (ADC_SENSORS_CONF_ADC5_PIN != 7)) +#error "ADC5 channel should be mapped to PA7 or disabled with -1" +#else +#define ADC_SENSORS_ADC5_PIN ADC_SENSORS_CONF_ADC5_PIN +#endif +#endif + +#ifndef ADC_SENSORS_CONF_ADC6_PIN +#define ADC_SENSORS_ADC6_PIN (-1) /**< ADC6 not declared */ +#else +#define ADC_SENSORS_ADC6_PIN 3 /**< Hard-coded to PA3 */ +#endif + +#ifndef ADC_SENSORS_CONF_MAX +#define ADC_SENSORS_MAX 5 /**< Maximum sensors */ +#else +#define ADC_SENSORS_MAX ADC_SENSORS_CONF_MAX +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ /** \name Firefly Button configuration * * Buttons on the Firefly are connected as follows: @@ -180,31 +266,19 @@ #define BUTTON_USER_PIN 3 #define BUTTON_USER_VECTOR NVIC_INT_GPIO_PORT_A -/* Notify various examples that we have Buttons */ -#define PLATFORM_HAS_BUTTON 1 -/** @} */ -/*---------------------------------------------------------------------------*/ -/** - * \name ADC configuration - * - * These values configure which CC2538 pins and ADC channels to use for the ADC - * inputs. There pins are suggested as they can be changed, but note that only - * pins from PA can be configured as ADC. - * - * The Firefly, as it is, only allows 3.3VDC sensors. - * - * The internal ADC reference is 1190mV, use either a voltage divider as input, - * or a different voltage reference, like AVDD5 or other externally (AIN7 or - * AIN6). - * @{ +/* Notify various examples that we have an user button. + * If ADC6 channel is used, then disable the user button */ -#define ADC_SENSORS_PORT GPIO_A_NUM /**< ADC GPIO control port */ -#define ADC_SENSORS_ADC1_PIN 5 /**< ADC1 to PA5, 3V3 */ -#define ADC_SENSORS_ADC2_PIN 4 /**< ADC2 to PA4, 3V3 */ -#define ADC_SENSORS_ADC3_PIN 2 /**< ADC3 to PA2, 3V3 */ -#define ADC_SENSORS_ADC4_PIN 6 /**< ADC4 to PA6, 3V3 */ -#define ADC_SENSORS_ADC5_PIN 7 /**< ADC5 to PA7, 3V3 */ -#define ADC_SENSORS_MAX 5 /**< PA2, PA4, PA5, PA6, PA7 */ +#ifdef PLATFORM_CONF_WITH_BUTTON +#if (PLATFORM_CONF_WITH_BUTTON && (ADC_SENSORS_ADC6_PIN == 3)) +#error "The ADC6 (PA3) and user button cannot be enabled at the same time" +#else +#define PLATFORM_HAS_BUTTON (PLATFORM_CONF_WITH_BUTTON && \ + !(ADC_SENSORS_ADC6_PIN == 3)) +#endif /* (PLATFORM_CONF_WITH_BUTTON && (ADC_SENSORS_ADC6_PIN == 3)) */ +#else +#define PLATFORM_HAS_BUTTON !(ADC_SENSORS_ADC6_PIN == 3) +#endif /* PLATFORM_CONF_WITH_BUTTON */ /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/platform/zoul/images/remote-pinout-front.png b/platform/zoul/images/remote-pinout-front.png index c32427d08..18a9bf40c 100755 Binary files a/platform/zoul/images/remote-pinout-front.png and b/platform/zoul/images/remote-pinout-front.png differ diff --git a/platform/zoul/remote/board.h b/platform/zoul/remote/board.h index 2ae4d8927..2887f452a 100644 --- a/platform/zoul/remote/board.h +++ b/platform/zoul/remote/board.h @@ -171,23 +171,6 @@ #define UART1_RTS_PIN (-1) /** @} */ /*---------------------------------------------------------------------------*/ -/** \name RE-Mote Button configuration - * - * Buttons on the RE-Mote are connected as follows: - * - BUTTON_USER -> PA3, S1 user button, shared with bootloader and RTC_INT1 - * - BUTTON_RESET -> RESET_N line, S2 reset both CC2538 and CoP - * - BUTTON_PIC1W -> shared with SHUTDOWN_ENABLE, not mounted. - * @{ - */ -/** BUTTON_USER -> PA3 */ -#define BUTTON_USER_PORT GPIO_A_NUM -#define BUTTON_USER_PIN 3 -#define BUTTON_USER_VECTOR NVIC_INT_GPIO_PORT_A - -/* Notify various examples that we have Buttons */ -#define PLATFORM_HAS_BUTTON 1 -/** @} */ -/*---------------------------------------------------------------------------*/ /** * \name ADC configuration * @@ -201,6 +184,12 @@ * - ADC2: up to 3.3V, shared with RTC_INT * - ADC3: up to 5V, by means of a 2/3 voltage divider. * + * Also there are other ADC channels shared by default with Micro SD card and + * user button implementations: + * - ADC4: up to 3.3V. + * - ADC5: up to 3.3V. + * - ADC6: up to 3.3V. + * * ADC inputs can only be on port A. * All ADCx are exposed in JP5 connector, but only ADC1 and ADC3 have GND and * VDD (3/5V) pins next to it, so these can be exposed into a 3-pin phidget-like @@ -216,12 +205,84 @@ * @{ */ #define ADC_SENSORS_PORT GPIO_A_NUM /**< ADC GPIO control port */ -#define ADC_SENSORS_ADC1_PIN 5 /**< ADC1 to PA5, 3V3 */ -#define ADC_SENSORS_ADC2_PIN (-1) /**< ADC2 to PA4, 3V3 */ -#define ADC_SENSORS_ADC3_PIN 2 /**< ADC3 to PA2, 5V0 */ -#define ADC_SENSORS_ADC4_PIN (-1) /**< Not present */ -#define ADC_SENSORS_ADC5_PIN (-1) /**< Not present */ -#define ADC_SENSORS_MAX 2 /**< PA2, PA5 */ + +#ifndef ADC_SENSORS_CONF_ADC1_PIN +#define ADC_SENSORS_ADC1_PIN 5 /**< ADC1 to PA5, 3V3 */ +#else +#if ((ADC_SENSORS_CONF_ADC1_PIN != -1) && (ADC_SENSORS_CONF_ADC1_PIN != 5)) +#error "ADC1 channel should be mapped to PA5 or disabled with -1" +#else +#define ADC_SENSORS_ADC1_PIN ADC_SENSORS_CONF_ADC1_PIN +#endif +#endif + +#ifndef ADC_SENSORS_CONF_ADC3_PIN +#define ADC_SENSORS_ADC3_PIN 2 /**< ADC3 to PA2, 5V */ +#else +#if ((ADC_SENSORS_CONF_ADC3_PIN != -1) && (ADC_SENSORS_CONF_ADC3_PIN != 2)) +#error "ADC3 channel should be mapped to PA2 or disabled with -1" +#else +#define ADC_SENSORS_ADC3_PIN ADC_SENSORS_CONF_ADC3_PIN +#endif +#endif + +#ifndef ADC_SENSORS_CONF_ADC2_PIN +#define ADC_SENSORS_ADC2_PIN (-1) /**< ADC2 no declared */ +#else +#define ADC_SENSORS_ADC2_PIN 4 /**< Hard-coded to PA4 */ +#endif + +#ifndef ADC_SENSORS_CONF_ADC4_PIN +#define ADC_SENSORS_ADC4_PIN (-1) /**< ADC4 not declared */ +#else +#define ADC_SENSORS_ADC4_PIN 6 /**< Hard-coded to PA6 */ +#endif + +#ifndef ADC_SENSORS_CONF_ADC5_PIN +#define ADC_SENSORS_ADC5_PIN (-1) /**< ADC5 not declared */ +#else +#define ADC_SENSORS_ADC5_PIN 7 /**< Hard-coded to PA7 */ +#endif + +#ifndef ADC_SENSORS_CONF_ADC6_PIN +#define ADC_SENSORS_ADC6_PIN (-1) /**< ADC6 not declared */ +#else +#define ADC_SENSORS_ADC6_PIN 3 /**< Hard-coded to PA3 */ +#endif + +#ifndef ADC_SENSORS_CONF_MAX +#define ADC_SENSORS_MAX 2 /**< Maximum sensors */ +#else +#define ADC_SENSORS_MAX ADC_SENSORS_CONF_MAX +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name RE-Mote Button configuration + * + * Buttons on the RE-Mote are connected as follows: + * - BUTTON_USER -> PA3, S1 user button, shared with bootloader and RTC_INT1 + * - BUTTON_RESET -> RESET_N line, S2 reset both CC2538 and CoP + * - BUTTON_PIC1W -> shared with SHUTDOWN_ENABLE, not mounted. + * @{ + */ +/** BUTTON_USER -> PA3 */ +#define BUTTON_USER_PORT GPIO_A_NUM +#define BUTTON_USER_PIN 3 +#define BUTTON_USER_VECTOR NVIC_INT_GPIO_PORT_A + +/* Notify various examples that we have an user button. + * If ADC6 channel is used, then disable the user button + */ +#ifdef PLATFORM_CONF_WITH_BUTTON +#if (PLATFORM_CONF_WITH_BUTTON && (ADC_SENSORS_ADC6_PIN == 3)) +#error "The ADC6 (PA3) and user button cannot be enabled at the same time" +#else +#define PLATFORM_HAS_BUTTON (PLATFORM_CONF_WITH_BUTTON && \ + !(ADC_SENSORS_ADC6_PIN == 3)) +#endif /* (PLATFORM_CONF_WITH_BUTTON && (ADC_SENSORS_ADC6_PIN == 3)) */ +#else +#define PLATFORM_HAS_BUTTON !(ADC_SENSORS_ADC6_PIN == 3) +#endif /* PLATFORM_CONF_WITH_BUTTON */ /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/regression-tests/01-compile-base/Makefile b/regression-tests/01-compile-base/Makefile index bbfbd0c6b..bc38a9777 100644 --- a/regression-tests/01-compile-base/Makefile +++ b/regression-tests/01-compile-base/Makefile @@ -37,8 +37,11 @@ settings-example/avr-raven \ ipv6/multicast/sky \ ipv6/rpl-tsch/z1 \ ipv6/rpl-tsch/z1:MAKE_WITH_ORCHESTRA=1 \ -ipv6/rpl-tsch/z1:MAKE_WITH_SECURITY=1 - +ipv6/rpl-tsch/z1:MAKE_WITH_SECURITY=1 \ +cfs-coffee/sky \ +cfs-coffee/z1 \ +cfs-coffee/wismote \ +cfs-coffee/avr-raven TOOLS= diff --git a/regression-tests/03-base/02-sky-coffee.csc b/regression-tests/03-base/02-sky-coffee.csc index f017a3e7d..050b4abc9 100644 --- a/regression-tests/03-base/02-sky-coffee.csc +++ b/regression-tests/03-base/02-sky-coffee.csc @@ -24,10 +24,10 @@ org.contikios.cooja.mspmote.SkyMoteType sky1 Sky Mote Type #1 - [CONTIKI_DIR]/examples/sky/test-coffee.c + [CONTIKI_DIR]/examples/cfs-coffee/test-coffee.c make clean TARGET=sky make test-coffee.sky TARGET=sky - [CONTIKI_DIR]/examples/sky/test-coffee.sky + [CONTIKI_DIR]/examples/cfs-coffee/test-coffee.sky org.contikios.cooja.interfaces.Position org.contikios.cooja.interfaces.IPAddress org.contikios.cooja.interfaces.Mote2MoteRelations @@ -89,7 +89,7 @@ make test-coffee.sky TARGET=sky org.contikios.cooja.plugins.ScriptRunner - - true - - 600 - 1 - 357 - 281 - 1 - - - org.contikios.cooja.plugins.TimeLine - - 0 - 1 - 2 - - 500.0 - - 882 - 3 - 149 - -1 - 357 - - - org.contikios.cooja.plugins.LogListener - - - - - - 882 - 0 - 195 - -1 - 504 - - - diff --git a/regression-tests/04-rime/05-sky-runicast.csc b/regression-tests/04-rime/04-sky-runicast.csc similarity index 100% rename from regression-tests/04-rime/05-sky-runicast.csc rename to regression-tests/04-rime/04-sky-runicast.csc diff --git a/regression-tests/04-rime/06-sky-trickle.csc b/regression-tests/04-rime/05-sky-trickle.csc similarity index 100% rename from regression-tests/04-rime/06-sky-trickle.csc rename to regression-tests/04-rime/05-sky-trickle.csc diff --git a/regression-tests/04-rime/06-sky-collect.csc b/regression-tests/04-rime/06-sky-collect.csc new file mode 100644 index 000000000..3fe71e180 --- /dev/null +++ b/regression-tests/04-rime/06-sky-collect.csc @@ -0,0 +1,245 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + generated + 10000000 + + org.contikios.cooja.radiomediums.UDGM + 30.0 + 40.0 + 0.9 + 0.9 + + + 40000 + + + org.contikios.cooja.mspmote.SkyMoteType + sky1 + Sky Mote Type #1 + [CONTIKI_DIR]/examples/sky/sky-collect.c + make clean TARGET=sky +make sky-collect.sky TARGET=sky + [CONTIKI_DIR]/examples/sky/sky-collect.sky + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.IPAddress + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.mspmote.interfaces.MspClock + org.contikios.cooja.mspmote.interfaces.MspMoteID + org.contikios.cooja.mspmote.interfaces.SkyButton + org.contikios.cooja.mspmote.interfaces.SkyFlash + org.contikios.cooja.mspmote.interfaces.Msp802154Radio + org.contikios.cooja.mspmote.interfaces.MspSerial + org.contikios.cooja.mspmote.interfaces.SkyLED + + + + + org.contikios.cooja.interfaces.Position + 9.333811152651393 + 89.28114548870677 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 1 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 33.040227185226826 + 54.184283361563054 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 2 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + -2.2559922410521516 + 50.71648775308175 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 3 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 12.959353575718179 + 43.874396471224806 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 4 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 15.917348901177405 + 66.93526904376517 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 5 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 26.735174243053933 + 35.939375910459084 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 6 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 41.5254792748469 + 28.370611308140152 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 7 + + sky1 + + + + org.contikios.cooja.plugins.SimControl + 265 + 3 + 200 + 0 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + 1.9551775516837413 0.0 0.0 1.9551775516837413 87.61059024269439 -50.01503690267507 + + 264 + 1 + 185 + 0 + 200 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 600 + 2 + 385 + 266 + 0 + + + org.contikios.cooja.plugins.TimeLine + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + + 500.0 + + 866 + 0 + 152 + 0 + 384 + + + diff --git a/regression-tests/04-rime/07-sky-collect.csc b/regression-tests/04-rime/07-sky-collect.csc index 3fe71e180..5184bf959 100644 --- a/regression-tests/04-rime/07-sky-collect.csc +++ b/regression-tests/04-rime/07-sky-collect.csc @@ -9,25 +9,25 @@ My simulation generated - 10000000 + 1000000 org.contikios.cooja.radiomediums.UDGM - 30.0 - 40.0 - 0.9 - 0.9 + 50.0 + 50.0 + 1.0 + 1.0 - 40000 + 400000 org.contikios.cooja.mspmote.SkyMoteType sky1 Sky Mote Type #1 - [CONTIKI_DIR]/examples/sky/sky-collect.c + [CONTIKI_DIR]/examples/rime/example-collect.c make clean TARGET=sky -make sky-collect.sky TARGET=sky - [CONTIKI_DIR]/examples/sky/sky-collect.sky +make example-collect.sky TARGET=sky + [CONTIKI_DIR]/examples/rime/example-collect.sky org.contikios.cooja.interfaces.Position org.contikios.cooja.interfaces.IPAddress org.contikios.cooja.interfaces.Mote2MoteRelations @@ -38,13 +38,18 @@ make sky-collect.sky TARGET=sky org.contikios.cooja.mspmote.interfaces.Msp802154Radio org.contikios.cooja.mspmote.interfaces.MspSerial org.contikios.cooja.mspmote.interfaces.SkyLED + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.interfaces.MoteAttributes + org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem + org.contikios.cooja.mspmote.interfaces.MspDebugOutput + org.contikios.cooja.mspmote.interfaces.SkyTemperature org.contikios.cooja.interfaces.Position - 9.333811152651393 - 89.28114548870677 + 87.29845932913939 + 60.286214311723164 0.0 @@ -57,8 +62,8 @@ make sky-collect.sky TARGET=sky org.contikios.cooja.interfaces.Position - 33.040227185226826 - 54.184283361563054 + 94.30809966340686 + 22.50388779326399 0.0 @@ -71,8 +76,8 @@ make sky-collect.sky TARGET=sky org.contikios.cooja.interfaces.Position - -2.2559922410521516 - 50.71648775308175 + 82.40423567500785 + 39.56979106929553 0.0 @@ -85,8 +90,8 @@ make sky-collect.sky TARGET=sky org.contikios.cooja.interfaces.Position - 12.959353575718179 - 43.874396471224806 + 26.185019854469438 + 4.800834369523899 0.0 @@ -99,8 +104,8 @@ make sky-collect.sky TARGET=sky org.contikios.cooja.interfaces.Position - 15.917348901177405 - 66.93526904376517 + 1.9530156130507015 + 78.3175061800706 0.0 @@ -113,8 +118,8 @@ make sky-collect.sky TARGET=sky org.contikios.cooja.interfaces.Position - 26.735174243053933 - 35.939375910459084 + 48.35216700543414 + 80.36988713780997 0.0 @@ -127,8 +132,8 @@ make sky-collect.sky TARGET=sky org.contikios.cooja.interfaces.Position - 41.5254792748469 - 28.370611308140152 + 24.825985087266833 + 74.27809432062487 0.0 @@ -137,12 +142,194 @@ make sky-collect.sky TARGET=sky sky1 + + + + org.contikios.cooja.interfaces.Position + 8.356165164293616 + 94.33967355724187 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 8 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 45.11740613004886 + 31.7059041432301 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 9 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 68.9908548386292 + 55.01991960639596 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 10 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 13.181122543889046 + 55.9636533130127 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 11 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 2.1749985906538427 + 78.39666095789707 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 12 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 37.79795217518357 + 7.164284163506062 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 13 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 64.4595177394984 + 72.115414337433 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 14 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 81.85663737096085 + 89.31412706434035 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 15 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 44.74952276297882 + 18.78566116347574 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 16 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 96.11333426285873 + 90.64560410751824 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 17 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 21.651464136783527 + 7.1381043251259495 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 18 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 83.6006916200628 + 26.97170140682981 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 19 + + sky1 + + + + + org.contikios.cooja.interfaces.Position + 1.3446070721664705 + 7.340373220385176 + 0.0 + + + org.contikios.cooja.mspmote.interfaces.MspMoteID + 20 + + sky1 + org.contikios.cooja.plugins.SimControl - 265 - 3 - 200 + 247 + 0 + 227 0 0 @@ -151,95 +338,110 @@ make sky-collect.sky TARGET=sky org.contikios.cooja.plugins.skins.IDVisualizerSkin org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - 1.9551775516837413 0.0 0.0 1.9551775516837413 87.61059024269439 -50.01503690267507 + 1.685403700540615 0.0 0.0 1.685403700540615 23.872012513439184 -0.545889466623605 - 264 + 224 + 3 + 225 + 247 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 469 1 - 185 + 473 0 - 200 + 226 org.contikios.cooja.plugins.ScriptRunner - + if(num_reported == num_nodes) { + print_stats(); + log.testOK(); + } + } true 600 2 - 385 - 266 + 700 + 469 0 - - org.contikios.cooja.plugins.TimeLine - - 0 - 1 - 2 - 3 - 4 - 5 - 6 - - 500.0 - - 866 - 0 - 152 - 0 - 384 - diff --git a/regression-tests/04-rime/09-cooja-trickle.csc b/regression-tests/04-rime/08-cooja-trickle.csc similarity index 100% rename from regression-tests/04-rime/09-cooja-trickle.csc rename to regression-tests/04-rime/08-cooja-trickle.csc diff --git a/regression-tests/04-rime/08-sky-collect.csc b/regression-tests/04-rime/08-sky-collect.csc deleted file mode 100644 index 5184bf959..000000000 --- a/regression-tests/04-rime/08-sky-collect.csc +++ /dev/null @@ -1,447 +0,0 @@ - - - [APPS_DIR]/mrm - [APPS_DIR]/mspsim - [APPS_DIR]/avrora - [APPS_DIR]/serial_socket - [APPS_DIR]/collect-view - [APPS_DIR]/powertracker - - My simulation - generated - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 50.0 - 1.0 - 1.0 - - - 400000 - - - org.contikios.cooja.mspmote.SkyMoteType - sky1 - Sky Mote Type #1 - [CONTIKI_DIR]/examples/rime/example-collect.c - make clean TARGET=sky -make example-collect.sky TARGET=sky - [CONTIKI_DIR]/examples/rime/example-collect.sky - org.contikios.cooja.interfaces.Position - org.contikios.cooja.interfaces.IPAddress - org.contikios.cooja.interfaces.Mote2MoteRelations - org.contikios.cooja.mspmote.interfaces.MspClock - org.contikios.cooja.mspmote.interfaces.MspMoteID - org.contikios.cooja.mspmote.interfaces.SkyButton - org.contikios.cooja.mspmote.interfaces.SkyFlash - org.contikios.cooja.mspmote.interfaces.Msp802154Radio - org.contikios.cooja.mspmote.interfaces.MspSerial - org.contikios.cooja.mspmote.interfaces.SkyLED - org.contikios.cooja.interfaces.RimeAddress - org.contikios.cooja.interfaces.MoteAttributes - org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem - org.contikios.cooja.mspmote.interfaces.MspDebugOutput - org.contikios.cooja.mspmote.interfaces.SkyTemperature - - - - - org.contikios.cooja.interfaces.Position - 87.29845932913939 - 60.286214311723164 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 94.30809966340686 - 22.50388779326399 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 82.40423567500785 - 39.56979106929553 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 3 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 26.185019854469438 - 4.800834369523899 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 4 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 1.9530156130507015 - 78.3175061800706 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 5 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 48.35216700543414 - 80.36988713780997 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 6 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 24.825985087266833 - 74.27809432062487 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 7 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 8.356165164293616 - 94.33967355724187 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 8 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 45.11740613004886 - 31.7059041432301 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 9 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 68.9908548386292 - 55.01991960639596 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 10 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 13.181122543889046 - 55.9636533130127 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 11 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 2.1749985906538427 - 78.39666095789707 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 12 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 37.79795217518357 - 7.164284163506062 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 13 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 64.4595177394984 - 72.115414337433 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 14 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 81.85663737096085 - 89.31412706434035 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 15 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 44.74952276297882 - 18.78566116347574 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 16 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 96.11333426285873 - 90.64560410751824 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 17 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 21.651464136783527 - 7.1381043251259495 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 18 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 83.6006916200628 - 26.97170140682981 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 19 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 1.3446070721664705 - 7.340373220385176 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 20 - - sky1 - - - - org.contikios.cooja.plugins.SimControl - 247 - 0 - 227 - 0 - 0 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - 1.685403700540615 0.0 0.0 1.685403700540615 23.872012513439184 -0.545889466623605 - - 224 - 3 - 225 - 247 - 1 - - - org.contikios.cooja.plugins.LogListener - - - - - - 469 - 1 - 473 - 0 - 226 - - - org.contikios.cooja.plugins.ScriptRunner - - - true - - 600 - 2 - 700 - 469 - 0 - - - diff --git a/regression-tests/04-rime/10-cooja-mesh.csc b/regression-tests/04-rime/09-cooja-mesh.csc similarity index 100% rename from regression-tests/04-rime/10-cooja-mesh.csc rename to regression-tests/04-rime/09-cooja-mesh.csc diff --git a/regression-tests/11-ipv6/21-z1-rpl-tsch-security.csc b/regression-tests/11-ipv6/21-z1-rpl-tsch-security.csc index a24f7fe5b..e2cda7e44 100644 --- a/regression-tests/11-ipv6/21-z1-rpl-tsch-security.csc +++ b/regression-tests/11-ipv6/21-z1-rpl-tsch-security.csc @@ -270,9 +270,6 @@ make node.z1 TARGET=z1 MAKE_WITH_ORCHESTRA=0 MAKE_WITH_SECURITY=1 diff --git a/regression-tests/12-rpl/02-rpl-root-reboot.csc b/regression-tests/12-rpl/02-rpl-root-reboot.csc index ce9f3cee0..6c4ce9d28 100644 --- a/regression-tests/12-rpl/02-rpl-root-reboot.csc +++ b/regression-tests/12-rpl/02-rpl-root-reboot.csc @@ -315,22 +315,20 @@ while(true) { } else if(msg.startsWith("#L") && msg.endsWith("1; red")) { hops++; } else if(msg.startsWith("Data")) { -// log.log("" + msg + "\n"); data = msg.split(" "); num = parseInt(data[14]); - packets = packets.substr(0, num) + "*"; - log.log("" + hops + " " + packets + "\n"); -// log.log("Num " + num + "\n"); if(lastMsg != -1) { if(num != lastMsg + 1) { numMissed = num - lastMsg - 1; - lostMsgs += numMissed; + lostMsgs += numMissed; log.log("Missed messages " + numMissed + " before " + num + "\n"); for(i = 0; i < numMissed; i++) { - packets = packets.substr(0, lastMsg + i) + "_"; + packets = packets.substr(0, lastMsg + i + 1).concat("_"); } } } + packets = packets.substr(0, num).concat("*"); + log.log("" + hops + " " + packets + "\n"); lastMsg = num; } } diff --git a/regression-tests/12-rpl/03-rpl-28-hours.csc b/regression-tests/12-rpl/03-rpl-28-hours.csc index a8cefd469..3ebc7adda 100644 --- a/regression-tests/12-rpl/03-rpl-28-hours.csc +++ b/regression-tests/12-rpl/03-rpl-28-hours.csc @@ -264,22 +264,20 @@ while(true) { } else if(msg.startsWith("#L") && msg.endsWith("1; red")) { hops++; } else if(msg.startsWith("Data")) { -// log.log("" + msg + "\n"); data = msg.split(" "); num = parseInt(data[14]); - packets = packets.substr(0, num) + "*"; - log.log("" + hops + " " + packets + "\n"); -// log.log("Num " + num + "\n"); if(lastMsg != -1) { if(num != lastMsg + 1) { numMissed = num - lastMsg - 1; - lostMsgs += numMissed; + lostMsgs += numMissed; log.log("Missed messages " + numMissed + " before " + num + "\n"); for(i = 0; i < numMissed; i++) { - packets = packets.substr(0, lastMsg + i) + "_"; + packets = packets.substr(0, lastMsg + i + 1).concat("_"); } } } + packets = packets.substr(0, num).concat("*"); + log.log("" + hops + " " + packets + "\n"); lastMsg = num; } } diff --git a/regression-tests/12-rpl/04-rpl-large-network.csc b/regression-tests/12-rpl/04-rpl-large-network.csc index 8b3ca0d8a..f4ea0fda8 100644 --- a/regression-tests/12-rpl/04-rpl-large-network.csc +++ b/regression-tests/12-rpl/04-rpl-large-network.csc @@ -7030,22 +7030,20 @@ while(true) { } else if(msg.startsWith("#L") && msg.endsWith("1; red")) { hops++; } else if(msg.startsWith("Data")) { -// log.log("" + msg + "\n"); data = msg.split(" "); num = parseInt(data[14]); - packets = packets.substr(0, num) + "*"; - log.log("" + hops + " " + packets + "\n"); -// log.log("Num " + num + "\n"); if(lastMsg != -1) { if(num != lastMsg + 1) { numMissed = num - lastMsg - 1; - lostMsgs += numMissed; + lostMsgs += numMissed; log.log("Missed messages " + numMissed + " before " + num + "\n"); for(i = 0; i < numMissed; i++) { - packets = packets.substr(0, lastMsg + i) + "_"; + packets = packets.substr(0, lastMsg + i + 1).concat("_"); } } } + packets = packets.substr(0, num).concat("*"); + log.log("" + hops + " " + packets + "\n"); lastMsg = num; } } @@ -7057,5 +7055,4 @@ while(true) { 603 43 - - + \ No newline at end of file diff --git a/regression-tests/12-rpl/05-rpl-up-and-down-routes.csc b/regression-tests/12-rpl/05-rpl-up-and-down-routes.csc index 3ed5a71f7..0dd110738 100644 --- a/regression-tests/12-rpl/05-rpl-up-and-down-routes.csc +++ b/regression-tests/12-rpl/05-rpl-up-and-down-routes.csc @@ -313,22 +313,20 @@ while(true) { } else if(msg.startsWith("#L") && msg.endsWith("1; red")) { hops++; } else if(msg.startsWith("Data")) { -// log.log("" + msg + "\n"); data = msg.split(" "); num = parseInt(data[14]); - packets = packets.substr(0, num) + "*"; - log.log("" + hops + " " + packets + "\n"); -// log.log("Num " + num + "\n"); if(lastMsg != -1) { if(num != lastMsg + 1) { numMissed = num - lastMsg - 1; - lostMsgs += numMissed; + lostMsgs += numMissed; log.log("Missed messages " + numMissed + " before " + num + "\n"); for(i = 0; i < numMissed; i++) { - packets = packets.substr(0, lastMsg + i) + "_"; + packets = packets.substr(0, lastMsg + i + 1).concat("_"); } } } + packets = packets.substr(0, num).concat("*"); + log.log("" + hops + " " + packets + "\n"); lastMsg = num; } } diff --git a/regression-tests/12-rpl/06-rpl-temporary-root-loss.csc b/regression-tests/12-rpl/06-rpl-temporary-root-loss.csc index bd771d7e7..6c29c643f 100644 --- a/regression-tests/12-rpl/06-rpl-temporary-root-loss.csc +++ b/regression-tests/12-rpl/06-rpl-temporary-root-loss.csc @@ -289,9 +289,9 @@ lostMsgs = 0; // we check that we got up to at least message 62 and // (the simulation is 4000000ms = 66 minutes long) -// that we did not lose anything since 34 +// that we did not lose anything since 45 // (the sink is back at 2000000ms = 33 minutes) -TIMEOUT(4000000, if(lastMsg >= 62 && lastMissed <= 34) { log.testOK(); } ); +TIMEOUT(4000000, if(lastMsg >= 62 && lastMissed <= 45) { log.testOK(); } ); lastMsg = -1; lastMissed = -1; @@ -318,23 +318,21 @@ while(true) { } else if(msg.startsWith("#L") && msg.endsWith("1; red")) { hops++; } else if(msg.startsWith("Data")) { -// log.log("" + msg + "\n"); data = msg.split(" "); num = parseInt(data[14]); - packets = packets.substr(0, num) + "*"; - log.log("" + hops + " " + packets + "\n"); -// log.log("Num " + num + "\n"); if(lastMsg != -1) { if(num != lastMsg + 1) { lastMissed = num; numMissed = num - lastMsg - 1; - lostMsgs += numMissed; + lostMsgs += numMissed; log.log("Missed messages " + numMissed + " before " + num + "\n"); for(i = 0; i < numMissed; i++) { - packets = packets.substr(0, lastMsg + i) + "_"; + packets = packets.substr(0, lastMsg + i + 1).concat("_"); } } } + packets = packets.substr(0, num).concat("*"); + log.log("" + hops + " " + packets + "\n"); lastMsg = num; } } diff --git a/regression-tests/12-rpl/08-rpl-dao-route-loss-0.csc b/regression-tests/12-rpl/08-rpl-dao-route-loss-0.csc index afdbed672..0fc6e032d 100644 --- a/regression-tests/12-rpl/08-rpl-dao-route-loss-0.csc +++ b/regression-tests/12-rpl/08-rpl-dao-route-loss-0.csc @@ -330,23 +330,21 @@ while(true) { } else if(msg.startsWith("#L") && msg.endsWith("1; red")) { hops++; } else if(msg.startsWith("Data")) { -// log.log("" + msg + "\n"); data = msg.split(" "); num = parseInt(data[14]); - packets = packets.substr(0, num) + "*"; - log.log("" + hops + " " + packets + "\n"); seenMsgs++; -// log.log("Num " + num + "\n"); if(lastMsg != -1) { if(num != lastMsg + 1) { numMissed = num - lastMsg - 1; - lostMsgs += numMissed; + lostMsgs += numMissed; log.log("Missed messages " + numMissed + " before " + num + "\n"); for(i = 0; i < numMissed; i++) { - packets = packets.substr(0, lastMsg + i) + "_"; + packets = packets.substr(0, lastMsg + i + 1).concat("_"); } } } + packets = packets.substr(0, num).concat("*"); + log.log("" + hops + " " + packets + "\n"); lastMsg = num; } } diff --git a/regression-tests/12-rpl/08-rpl-dao-route-loss-1.csc b/regression-tests/12-rpl/08-rpl-dao-route-loss-1.csc index 3657d4b8a..2c0ce41ff 100644 --- a/regression-tests/12-rpl/08-rpl-dao-route-loss-1.csc +++ b/regression-tests/12-rpl/08-rpl-dao-route-loss-1.csc @@ -330,23 +330,21 @@ while(true) { } else if(msg.startsWith("#L") && msg.endsWith("1; red")) { hops++; } else if(msg.startsWith("Data")) { -// log.log("" + msg + "\n"); data = msg.split(" "); num = parseInt(data[14]); - packets = packets.substr(0, num) + "*"; - log.log("" + hops + " " + packets + "\n"); seenMsgs++; -// log.log("Num " + num + "\n"); if(lastMsg != -1) { if(num != lastMsg + 1) { numMissed = num - lastMsg - 1; - lostMsgs += numMissed; + lostMsgs += numMissed; log.log("Missed messages " + numMissed + " before " + num + "\n"); for(i = 0; i < numMissed; i++) { - packets = packets.substr(0, lastMsg + i) + "_"; + packets = packets.substr(0, lastMsg + i + 1).concat("_"); } } } + packets = packets.substr(0, num).concat("*"); + log.log("" + hops + " " + packets + "\n"); lastMsg = num; } } diff --git a/regression-tests/12-rpl/08-rpl-dao-route-loss-2.csc b/regression-tests/12-rpl/08-rpl-dao-route-loss-2.csc index 8c78725a3..cdb2bd748 100644 --- a/regression-tests/12-rpl/08-rpl-dao-route-loss-2.csc +++ b/regression-tests/12-rpl/08-rpl-dao-route-loss-2.csc @@ -330,23 +330,21 @@ while(true) { } else if(msg.startsWith("#L") && msg.endsWith("1; red")) { hops++; } else if(msg.startsWith("Data")) { -// log.log("" + msg + "\n"); data = msg.split(" "); num = parseInt(data[14]); - packets = packets.substr(0, num) + "*"; - log.log("" + hops + " " + packets + "\n"); seenMsgs++; -// log.log("Num " + num + "\n"); if(lastMsg != -1) { if(num != lastMsg + 1) { numMissed = num - lastMsg - 1; - lostMsgs += numMissed; + lostMsgs += numMissed; log.log("Missed messages " + numMissed + " before " + num + "\n"); for(i = 0; i < numMissed; i++) { - packets = packets.substr(0, lastMsg + i) + "_"; + packets = packets.substr(0, lastMsg + i + 1).concat("_"); } } } + packets = packets.substr(0, num).concat("*"); + log.log("" + hops + " " + packets + "\n"); lastMsg = num; } } diff --git a/regression-tests/12-rpl/08-rpl-dao-route-loss-3.csc b/regression-tests/12-rpl/08-rpl-dao-route-loss-3.csc index fd1983379..34b930c0d 100644 --- a/regression-tests/12-rpl/08-rpl-dao-route-loss-3.csc +++ b/regression-tests/12-rpl/08-rpl-dao-route-loss-3.csc @@ -330,23 +330,21 @@ while(true) { } else if(msg.startsWith("#L") && msg.endsWith("1; red")) { hops++; } else if(msg.startsWith("Data")) { -// log.log("" + msg + "\n"); data = msg.split(" "); num = parseInt(data[14]); - packets = packets.substr(0, num) + "*"; - log.log("" + hops + " " + packets + "\n"); seenMsgs++; -// log.log("Num " + num + "\n"); if(lastMsg != -1) { if(num != lastMsg + 1) { numMissed = num - lastMsg - 1; - lostMsgs += numMissed; + lostMsgs += numMissed; log.log("Missed messages " + numMissed + " before " + num + "\n"); for(i = 0; i < numMissed; i++) { - packets = packets.substr(0, lastMsg + i) + "_"; + packets = packets.substr(0, lastMsg + i + 1).concat("_"); } } } + packets = packets.substr(0, num).concat("*"); + log.log("" + hops + " " + packets + "\n"); lastMsg = num; } } diff --git a/regression-tests/12-rpl/08-rpl-dao-route-loss-4.csc b/regression-tests/12-rpl/08-rpl-dao-route-loss-4.csc index 8db19c568..ff9a400c1 100644 --- a/regression-tests/12-rpl/08-rpl-dao-route-loss-4.csc +++ b/regression-tests/12-rpl/08-rpl-dao-route-loss-4.csc @@ -330,23 +330,21 @@ while(true) { } else if(msg.startsWith("#L") && msg.endsWith("1; red")) { hops++; } else if(msg.startsWith("Data")) { -// log.log("" + msg + "\n"); data = msg.split(" "); num = parseInt(data[14]); - packets = packets.substr(0, num) + "*"; - log.log("" + hops + " " + packets + "\n"); seenMsgs++; -// log.log("Num " + num + "\n"); if(lastMsg != -1) { if(num != lastMsg + 1) { numMissed = num - lastMsg - 1; - lostMsgs += numMissed; + lostMsgs += numMissed; log.log("Missed messages " + numMissed + " before " + num + "\n"); for(i = 0; i < numMissed; i++) { - packets = packets.substr(0, lastMsg + i) + "_"; + packets = packets.substr(0, lastMsg + i + 1).concat("_"); } } } + packets = packets.substr(0, num).concat("*"); + log.log("" + hops + " " + packets + "\n"); lastMsg = num; } } diff --git a/regression-tests/12-rpl/08-rpl-dao-route-loss-5.csc b/regression-tests/12-rpl/08-rpl-dao-route-loss-5.csc index 0f4d7db7d..e491b666f 100644 --- a/regression-tests/12-rpl/08-rpl-dao-route-loss-5.csc +++ b/regression-tests/12-rpl/08-rpl-dao-route-loss-5.csc @@ -330,23 +330,21 @@ while(true) { } else if(msg.startsWith("#L") && msg.endsWith("1; red")) { hops++; } else if(msg.startsWith("Data")) { -// log.log("" + msg + "\n"); data = msg.split(" "); num = parseInt(data[14]); - packets = packets.substr(0, num) + "*"; - log.log("" + hops + " " + packets + "\n"); seenMsgs++; -// log.log("Num " + num + "\n"); if(lastMsg != -1) { if(num != lastMsg + 1) { numMissed = num - lastMsg - 1; - lostMsgs += numMissed; + lostMsgs += numMissed; log.log("Missed messages " + numMissed + " before " + num + "\n"); for(i = 0; i < numMissed; i++) { - packets = packets.substr(0, lastMsg + i) + "_"; + packets = packets.substr(0, lastMsg + i + 1).concat("_"); } } } + packets = packets.substr(0, num).concat("*"); + log.log("" + hops + " " + packets + "\n"); lastMsg = num; } } diff --git a/regression-tests/12-rpl/09-rpl-probing.csc b/regression-tests/12-rpl/09-rpl-probing.csc index bc29029af..66a156e9c 100644 --- a/regression-tests/12-rpl/09-rpl-probing.csc +++ b/regression-tests/12-rpl/09-rpl-probing.csc @@ -226,23 +226,21 @@ while(true) { } else if(msg.startsWith("#L") && msg.endsWith("1; red")) { hops++; } else if(msg.startsWith("Data")) { -// log.log("" + msg + "\n"); data = msg.split(" "); num = parseInt(data[14]); - packets = packets.substr(0, num) + "*"; - log.log("" + hops + " " + packets + "\n"); -// log.log("Num " + num + "\n"); if(lastMsg != -1) { if(num != lastMsg + 1) { numMissed = num - lastMsg - 1; - lostMsgs += numMissed; + lostMsgs += numMissed; log.log("Missed messages " + numMissed + " before " + num + "\n"); for(i = 0; i < numMissed; i++) { - packets = packets.substr(0, lastMsg + i) + "_"; + packets = packets.substr(0, lastMsg + i + 1).concat("_"); } } } lastMsgHops = hops; + packets = packets.substr(0, num).concat("*"); + log.log("" + hops + " " + packets + "\n"); lastMsg = num; } } diff --git a/regression-tests/12-rpl/10-rpl-multi-dodag.csc b/regression-tests/12-rpl/10-rpl-multi-dodag.csc index aa0ab3d43..0f446cc65 100644 --- a/regression-tests/12-rpl/10-rpl-multi-dodag.csc +++ b/regression-tests/12-rpl/10-rpl-multi-dodag.csc @@ -356,12 +356,8 @@ while(true) { } else if(msg.startsWith("#L") && msg.endsWith("1; red")) { hops++; } else if(msg.startsWith("Data")) { -// log.log("" + msg + "\n"); data = msg.split(" "); num = parseInt(data[14]); - packets = packets.substr(0, num) + "*"; - log.log("" + hops + " " + packets + "\n"); -// log.log("Num " + num + "\n"); if(newSink) { newDagOk++; newSink = 0; @@ -369,13 +365,15 @@ while(true) { if(lastMsg != -1) { if(num != lastMsg + 1) { numMissed = num - lastMsg - 1; - lostMsgs += numMissed; + lostMsgs += numMissed; log.log("Missed messages " + numMissed + " before " + num + "\n"); for(i = 0; i < numMissed; i++) { - packets = packets.substr(0, lastMsg + i) + "_"; + packets = packets.substr(0, lastMsg + i + 1).concat("_"); } } } + packets = packets.substr(0, num).concat("*"); + log.log("" + hops + " " + packets + "\n"); lastMsg = num; } } diff --git a/regression-tests/12-rpl/code/receiver-node.c b/regression-tests/12-rpl/code/receiver-node.c index 4ba3cb148..727a23f84 100644 --- a/regression-tests/12-rpl/code/receiver-node.c +++ b/regression-tests/12-rpl/code/receiver-node.c @@ -73,7 +73,7 @@ set_global_address(void) int i; uint8_t state; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); diff --git a/regression-tests/12-rpl/code/root-node.c b/regression-tests/12-rpl/code/root-node.c index 0609e1bd8..fdea828f8 100644 --- a/regression-tests/12-rpl/code/root-node.c +++ b/regression-tests/12-rpl/code/root-node.c @@ -77,7 +77,7 @@ set_global_address(void) int i; uint8_t state; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); @@ -106,7 +106,7 @@ create_rpl_dag(uip_ipaddr_t *ipaddr) rpl_set_root(RPL_DEFAULT_INSTANCE, ipaddr); dag = rpl_get_any_dag(); - uip_ip6addr(&prefix, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); rpl_set_prefix(dag, &prefix, 64); PRINTF("created a new RPL dag\n"); } else { diff --git a/regression-tests/12-rpl/code/sender-node.c b/regression-tests/12-rpl/code/sender-node.c index 08d81b62d..55dfdd15f 100644 --- a/regression-tests/12-rpl/code/sender-node.c +++ b/regression-tests/12-rpl/code/sender-node.c @@ -72,7 +72,7 @@ set_global_address(void) int i; uint8_t state; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); @@ -109,7 +109,7 @@ PROCESS_THREAD(sender_node_process, ev, data) PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&send_timer)); - uip_ip6addr(&addr, 0xaaaa, 0, 0, 0, 0x0201, 0x001, 0x001, 0x001); + uip_ip6addr(&addr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0x0201, 0x001, 0x001, 0x001); { static unsigned int message_number; diff --git a/regression-tests/13-ipv6-apps/x02-sky-coap.csc b/regression-tests/13-ipv6-apps/x02-sky-coap.csc index ad3155f3d..d3d284a2d 100644 --- a/regression-tests/13-ipv6-apps/x02-sky-coap.csc +++ b/regression-tests/13-ipv6-apps/x02-sky-coap.csc @@ -181,14 +181,14 @@ PROCESS_CONF_NO_PROCESS_NAMES=1 The test script communicates with the REST server via the RPL border router using external commands. (* $ make connect-router-cooja) -* $ ping6 -c 10 -I tun0 aaaa::212:7401:1:101 -* $ ping6 -c 10 -I tun0 aaaa::212:7402:2:202 -* $ wget -t 1 -T 10 -O - http://[aaaa::212:7402:2:202] +* $ ping6 -c 10 -I tun0 fd00::212:7401:1:101 +* $ ping6 -c 10 -I tun0 fd00::212:7402:2:202 +* $ wget -t 1 -T 10 -O - http://[fd00::212:7402:2:202] The final test uses the CoAP Java implementation by Matthias Kovatsch, downloaded from: https://github.com/mkovatsc/Californium/blob/master/run/ExampleClient.jar -* $ java -jar ExampleClient.jar DISCOVER coap://[aaaa::212:7402:2:202] -* $ java -jar ExampleClient.jar GET coap://[aaaa::212:7402:2:202]/hello +* $ java -jar ExampleClient.jar DISCOVER coap://[fd00::212:7402:2:202] +* $ java -jar ExampleClient.jar GET coap://[fd00::212:7402:2:202]/hello true 751 diff --git a/regression-tests/18-compile-arm-ports/Makefile b/regression-tests/18-compile-arm-ports/Makefile index dbac11d43..e0addfa9f 100644 --- a/regression-tests/18-compile-arm-ports/Makefile +++ b/regression-tests/18-compile-arm-ports/Makefile @@ -11,9 +11,12 @@ cc26xx/cc26xx-web-demo/srf06-cc26xx \ cc26xx/very-sleepy-demo/srf06-cc26xx:BOARD=sensortag/cc2650 \ cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=sensortag/cc2650 \ cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=srf06/cc13xx \ +cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=launchpad/cc2650 \ +cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=launchpad/cc1310 \ cc26xx/very-sleepy-demo/srf06-cc26xx \ hello-world/cc2538dk \ ipv6/rpl-border-router/cc2538dk \ +ipv6/rpl-border-router/cc2538dk:MAKE_WITH_NON_STORING=1 \ er-rest-example/cc2538dk \ ipso-objects/cc2538dk \ webserver-ipv6/cc2538dk \ @@ -32,6 +35,7 @@ cc2538-common/crypto/zoul \ cc2538-common/pka/zoul \ zolertia/zoul/zoul \ zolertia/zoul/cc1200-demo/zoul \ +openmote-cc2538/openmote-cc2538 \ er-rest-example/zoul \ ipso-objects/zoul \ hello-world/zoul \ @@ -43,6 +47,9 @@ stm32nucleo-spirit1/sensor-demo/stm32nucleo-spirit1 \ ipv6/multicast/stm32nucleo-spirit1 \ udp-ipv6/stm32nucleo-spirit1 \ hello-world/stm32nucleo-spirit1 \ +cfs-coffee/cc2538dk \ +cfs-coffee/openmote-cc2538 \ +cfs-coffee/zoul TOOLS= diff --git a/regression-tests/20-compile-osd-ports/Makefile b/regression-tests/20-compile-osd-ports/Makefile index f4f21e8ff..26224a1b5 100644 --- a/regression-tests/20-compile-osd-ports/Makefile +++ b/regression-tests/20-compile-osd-ports/Makefile @@ -3,28 +3,52 @@ EXAMPLESDIR=../../examples TOOLSDIR=../../tools EXAMPLES = \ -hello-world/osd-merkur \ -osd/er-rest-example-merkurboard/osd-merkur \ -osd/rpl-border-router/osd-merkur \ -osd/slip-radio/osd-merkur \ -osd/arduino-dooralert/osd-merkur \ -osd/arduino-merkurboard/osd-merkur \ -osd/arduino-plantobserving/osd-merkur \ -osd/arduino-roomalert/osd-merkur \ -osd/arduino-sketch/osd-merkur \ -osd/arduino-wateralert/osd-merkur \ -osd/climate/osd-merkur \ -osd/climate2/osd-merkur \ -osd/servo-sensor/osd-merkur \ -osd/pingtheplug/osd-merkur \ -osd/powerbox/osd-merkur \ -osd/embedd-vm-merkurboard/osd-merkur \ -osd/light-actor/osd-merkur \ -#osd/dual-rgbw-actor/osd-merkur \ -#osd/light-shutter-control/osd-merkur \ -#osd/pir-sensor/osd-merkur \ -#osd/pwm-example/osd-merkur \ -#osd/wallclock-timer/osd-merkur +hello-world/osd-merkur-128 \ +osd/er-rest-example-merkurboard/osd-merkur-128 \ +osd/rpl-border-router/osd-merkur-128 \ +osd/slip-radio/osd-merkur-128 \ +osd/arduino-dooralert/osd-merkur-128 \ +osd/arduino-merkurboard/osd-merkur-128 \ +osd/arduino-plantobserving/osd-merkur-128 \ +osd/arduino-roomalert/osd-merkur-128 \ +osd/arduino-sketch/osd-merkur-128 \ +osd/arduino-wateralert/osd-merkur-128 \ +osd/climate/osd-merkur-128 \ +osd/climate2/osd-merkur-128 \ +osd/servo-sensor/osd-merkur-128 \ +osd/pingtheplug/osd-merkur-128 \ +osd/powerbox/osd-merkur-128 \ +osd/embedd-vm-merkurboard/osd-merkur-128 \ +osd/light-actor/osd-merkur-128 \ +hello-world/osd-merkur-256 \ +osd/er-rest-example-merkurboard/osd-merkur-256 \ +osd/rpl-border-router/osd-merkur-256 \ +osd/slip-radio/osd-merkur-256 \ +osd/arduino-dooralert/osd-merkur-256 \ +osd/arduino-merkurboard/osd-merkur-256 \ +osd/arduino-plantobserving/osd-merkur-256 \ +osd/arduino-roomalert/osd-merkur-256 \ +osd/arduino-sketch/osd-merkur-256 \ +osd/arduino-wateralert/osd-merkur-256 \ +osd/climate/osd-merkur-256 \ +osd/climate2/osd-merkur-256 \ +osd/servo-sensor/osd-merkur-256 \ +osd/pingtheplug/osd-merkur-256 \ +osd/powerbox/osd-merkur-256 \ +osd/embedd-vm-merkurboard/osd-merkur-256 \ +osd/light-actor/osd-merkur-256 \ + +#osd/dual-rgbw-actor/osd-merkur-128 \ +#osd/light-shutter-control/osd-merkur-128 \ +#osd/pir-sensor/osd-merkur-128 \ +#osd/pwm-example/osd-merkur-128 \ +#osd/wallclock-timer/osd-merkur-128 \ + +#osd/dual-rgbw-actor/osd-merkur-256 \ +#osd/light-shutter-control/osd-merkur-256 \ +#osd/pir-sensor/osd-merkur-256 \ +#osd/pwm-example/osd-merkur-256 \ +#osd/wallclock-timer/osd-merkur-256 \ TOOLS= diff --git a/regression-tests/20-ip64/01-cooja-ip64-http-socket.csc b/regression-tests/20-ip64/01-cooja-ip64-http-socket.csc index bc075971b..cec228b5e 100644 --- a/regression-tests/20-ip64/01-cooja-ip64-http-socket.csc +++ b/regression-tests/20-ip64/01-cooja-ip64-http-socket.csc @@ -151,7 +151,7 @@ if (travis == null) { /* Instant Contiki */ CMD_TUNNEL = "echo '-vj' > ~/.slirprc && make Connect.class && java Connect 'nc localhost 60001' 'script -t -f -c slirp'"; CMD_PING = "ping -c 5 8.8.8.8"; - CMD_DIR = "../../wpcapslip"; + CMD_DIR = "../../tools/wpcapslip"; } else { /* Travis */ CMD_TUNNEL = "cd $TRAVIS_BUILD_DIR/tools/wpcapslip && sudo apt-get install slirp && echo '-vj' > ~/.slirprc && make Connect.class && java Connect 'nc localhost 60001' 'script -t -f -c slirp'"; diff --git a/regression-tests/21-large-rpl/code/node/client.c b/regression-tests/21-large-rpl/code/node/client.c index 386f18529..1e82e2df0 100644 --- a/regression-tests/21-large-rpl/code/node/client.c +++ b/regression-tests/21-large-rpl/code/node/client.c @@ -10,6 +10,7 @@ static struct http_socket s; static int bytes_received = 0; static int restarts; static struct ctimer reconnect_timer; +static int connect = 0; static void callback(struct http_socket *s, void *ptr, http_socket_event_t e, @@ -22,9 +23,9 @@ AUTOSTART_PROCESSES(&http_example_process); static void reconnect(void *dummy) { + printf("#A color=orange\n"); rpl_set_mode(RPL_MODE_MESH); - http_socket_get(&s, "http://www.contiki-os.org/", 0, 0, - callback, NULL); + connect = 1; } /*---------------------------------------------------------------------------*/ static void @@ -33,6 +34,8 @@ restart(void) int scale; restarts++; printf("restart %d\n", restarts); + rpl_set_mode(RPL_MODE_FEATHER); + printf("#A color=red\n"); scale = restarts; if(scale > 5) { @@ -62,6 +65,7 @@ callback(struct http_socket *s, void *ptr, if(bytes_received > 0) { printf("HTTP socket closed, %d bytes received\n", bytes_received); leds_off(LEDS_RED); + printf("#A color=blue\n"); rpl_set_mode(RPL_MODE_FEATHER); } else { restart(); @@ -72,6 +76,7 @@ callback(struct http_socket *s, void *ptr, } } /*---------------------------------------------------------------------------*/ + PROCESS_THREAD(http_example_process, ev, data) { static struct etimer et; @@ -88,14 +93,26 @@ PROCESS_THREAD(http_example_process, ev, data) PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); http_socket_init(&s); - http_socket_get(&s, "http://www.contiki-os.org/", 0, 0, - callback, NULL); + connect = 1; leds_on(LEDS_RED); restarts = 0; - etimer_set(&et, CLOCK_SECOND); + etimer_set(&et, CLOCK_SECOND * 5); while(1) { PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); etimer_reset(&et); + if(connect && rpl_has_downward_route()) { + printf("#A color=green\n"); + http_socket_get(&s, "http://www.contiki-os.org/", 0, 0, + callback, NULL); + connect = 0; + } else if(connect) { + connect++; + /* If connect have been "tried" 5 timer we quit trying now... */ + if(connect > 5) { + restart(); + connect = 0; + } + } } PROCESS_END(); diff --git a/regression-tests/21-large-rpl/code/router/project-conf.h b/regression-tests/21-large-rpl/code/router/project-conf.h index eb0b0b1a7..857ab6929 100644 --- a/regression-tests/21-large-rpl/code/router/project-conf.h +++ b/regression-tests/21-large-rpl/code/router/project-conf.h @@ -7,5 +7,5 @@ #undef NBR_TABLE_CONF_MAX_NEIGHBORS #define NBR_TABLE_CONF_MAX_NEIGHBORS 8 -/*#define RPL_CONF_DEFAULT_LIFETIME_UNIT 10 - #define RPL_CONF_DEFAULT_LIFETIME 10*/ +/* #define RPL_CONF_DEFAULT_LIFETIME_UNIT 60 */ +/* #define RPL_CONF_DEFAULT_LIFETIME 10 */ diff --git a/regression-tests/21-large-rpl/code/router/router.c b/regression-tests/21-large-rpl/code/router/router.c index 844afdc1c..65882c36c 100644 --- a/regression-tests/21-large-rpl/code/router/router.c +++ b/regression-tests/21-large-rpl/code/router/router.c @@ -3,13 +3,23 @@ #include "ip64.h" #include "net/netstack.h" #include "net/rpl/rpl-dag-root.h" - +#include "net/rpl/rpl.h" +#include "net/ipv6/uip-ds6-route.h" +#include /*---------------------------------------------------------------------------*/ PROCESS(router_node_process, "Router node"); AUTOSTART_PROCESSES(&router_node_process); /*---------------------------------------------------------------------------*/ +uip_lladdr_t * uip_ds6_route_nexthop_lladdr(uip_ds6_route_t *route); + + PROCESS_THREAD(router_node_process, ev, data) { + uip_ipaddr_t *nexthop = NULL; + uip_ds6_defrt_t *defrt; + uip_ipaddr_t *ipaddr; + uip_ds6_route_t *r; + static struct etimer et; PROCESS_BEGIN(); /* Set us up as a RPL root node. */ @@ -18,9 +28,41 @@ PROCESS_THREAD(router_node_process, ev, data) /* Initialize the IP64 module so we'll start translating packets */ ip64_init(); + /* etimer_set(&et, CLOCK_SECOND * 60); */ + /* PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); */ + /* ... and do nothing more. */ while(1) { - PROCESS_WAIT_EVENT(); + etimer_set(&et, CLOCK_SECOND * 20); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + defrt = NULL; + if((ipaddr = uip_ds6_defrt_choose()) != NULL) { + defrt = uip_ds6_defrt_lookup(ipaddr); + } + if(defrt != NULL) { + printf("DefRT: :: -> %02d", defrt->ipaddr.u8[15]); + printf(" lt:%lu inf:%d\n", stimer_remaining(&defrt->lifetime), + defrt->isinfinite); + } else { + printf("DefRT: :: -> NULL\n"); + } + + if(uip_ds6_route_head() != NULL) { + printf("found head\n"); + for(r = uip_ds6_route_head(); + r != NULL; + r = uip_ds6_route_next(r)) { + nexthop = uip_ds6_route_nexthop(r); + if(nexthop != NULL) { + printf("Route: %02d -> %02d", r->ipaddr.u8[15], nexthop->u8[15]); + } else { + //printf("Route: %p %02d -> ? nbr-routes:%p", r, r->ipaddr.u8[15], + //r->neighbor_routes); + } + printf(" lt:%lu\n", r->state.lifetime); + } + } } PROCESS_END(); diff --git a/regression-tests/21-large-rpl/testscript.js b/regression-tests/21-large-rpl/testscript.js index 0c23bceef..1481d6bf5 100644 --- a/regression-tests/21-large-rpl/testscript.js +++ b/regression-tests/21-large-rpl/testscript.js @@ -1,5 +1,5 @@ -TIMEOUT(2400000); /* 40 minutes */ +TIMEOUT(3000000); /* 50 minutes */ var NR_FEATHERS = mote.getSimulation().getMotesCount() - 1; @@ -9,7 +9,7 @@ if (travis == null) { /* Instant Contiki */ CMD_TUNNEL = "echo '-vj' > ~/.slirprc && make Connect.class && java Connect 'nc localhost 60001' 'script -t -f -c slirp'"; CMD_PING = "ping -c 5 8.8.8.8"; - CMD_DIR = "../../wpcapslip"; + CMD_DIR = "../../tools/wpcapslip"; } else { /* Travis */ CMD_TUNNEL = "cd $TRAVIS_BUILD_DIR/tools/wpcapslip && sudo apt-get install slirp && echo '-vj' > ~/.slirprc && make Connect.class && java Connect 'nc localhost 60001' 'script -t -f -c slirp'"; diff --git a/regression-tests/23-compile-avr/Makefile b/regression-tests/23-compile-avr/Makefile new file mode 100644 index 000000000..e7d2dff77 --- /dev/null +++ b/regression-tests/23-compile-avr/Makefile @@ -0,0 +1,14 @@ +EXAMPLESDIR=../.. +TOOLSDIR=../../tools + +# build avr-rss2 examples, covering IPv6, RPL, Rime, Nullrdc, Contikimac + +EXAMPLES = \ +examples/avr-rss2/hello-sensors/avr-rss2 \ +examples/avr-rss2/ipv6/rpl-udp-report/avr-rss2 \ +examples/avr-rss2/ipv6/rpl-border-router/avr-rss2 \ +examples/powertrace/avr-rss2 \ +examples/rime/avr-rss2 +TOOLS= + +include ../Makefile.compile-test diff --git a/regression-tests/23-rpl-non-storing/01-rpl-up-route.csc b/regression-tests/23-rpl-non-storing/01-rpl-up-route.csc new file mode 100644 index 000000000..da4743d44 --- /dev/null +++ b/regression-tests/23-rpl-non-storing/01-rpl-up-route.csc @@ -0,0 +1,344 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype488 + Sender + [CONTIKI_DIR]/regression-tests/12-rpl/code/sender-node.c + make TARGET=cooja clean +make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype32 + RPL root + [CONTIKI_DIR]/regression-tests/12-rpl/code/root-node.c + make TARGET=cooja clean +make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype352 + Receiver + [CONTIKI_DIR]/regression-tests/12-rpl/code/receiver-node.c + make TARGET=cooja clean +make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + 6.9596575829049145 + -25.866060090958513 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype352 + + + + org.contikios.cooja.interfaces.Position + 132.8019872469463 + 146.1533406452311 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype488 + + + + org.contikios.cooja.interfaces.Position + 0.026556260457749753 + 39.54055615854325 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype352 + + + + org.contikios.cooja.interfaces.Position + 95.52021598473031 + 148.11553913271615 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype352 + + + + org.contikios.cooja.interfaces.Position + 62.81690785997944 + 127.1854219328756 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype352 + + + + org.contikios.cooja.interfaces.Position + 32.07579822271361 + 102.33090775806494 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype352 + + + + org.contikios.cooja.interfaces.Position + 5.913151722912886 + 73.55199660828417 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype352 + + + + org.contikios.cooja.interfaces.Position + 0.0 + 0.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype32 + + + + org.contikios.cooja.plugins.SimControl + 280 + 2 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 0.9555608221893928 0.0 0.0 0.9555608221893928 177.34962387792274 139.71659364731656 + + 400 + 1 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 1184 + 3 + 240 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 962 + 0 + 596 + 603 + 43 + + + diff --git a/regression-tests/23-rpl-non-storing/02-rpl-root-reboot.csc b/regression-tests/23-rpl-non-storing/02-rpl-root-reboot.csc new file mode 100644 index 000000000..6c4ce9d28 --- /dev/null +++ b/regression-tests/23-rpl-non-storing/02-rpl-root-reboot.csc @@ -0,0 +1,344 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype958 + Sender + [CONTIKI_DIR]/regression-tests/12-rpl/code/sender-node.c + make TARGET=cooja clean +make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype837 + RPL root + [CONTIKI_DIR]/regression-tests/12-rpl/code/root-node.c + make TARGET=cooja clean +make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype358 + Receiver + [CONTIKI_DIR]/regression-tests/12-rpl/code/receiver-node.c + make TARGET=cooja clean +make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + -22.5728586847096 + 123.9358664968653 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype358 + + + + org.contikios.cooja.interfaces.Position + 116.13379149678028 + 88.36698920455684 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype958 + + + + org.contikios.cooja.interfaces.Position + -1.39303771455413 + 100.21446701029119 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype358 + + + + org.contikios.cooja.interfaces.Position + 95.25095618820441 + 63.14998053005015 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype358 + + + + org.contikios.cooja.interfaces.Position + 66.09378990830604 + 38.32698761608261 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype358 + + + + org.contikios.cooja.interfaces.Position + 29.05630841762433 + 30.840688165838436 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype358 + + + + org.contikios.cooja.interfaces.Position + 10.931583432822638 + 69.848248459216 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype358 + + + + org.contikios.cooja.interfaces.Position + 0.0 + 0.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype837 + + + + org.contikios.cooja.plugins.SimControl + 280 + 0 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 2.5379695437350276 0.0 0.0 2.5379695437350276 75.2726010197627 15.727272727272757 + + 400 + 2 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 1184 + 3 + 240 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 962 + 1 + 596 + 603 + 43 + + + diff --git a/regression-tests/23-rpl-non-storing/03-rpl-28-hours.csc b/regression-tests/23-rpl-non-storing/03-rpl-28-hours.csc new file mode 100644 index 000000000..3ebc7adda --- /dev/null +++ b/regression-tests/23-rpl-non-storing/03-rpl-28-hours.csc @@ -0,0 +1,293 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype110 + Sender + [CONTIKI_DIR]/regression-tests/12-rpl/code/sender-node.c + make TARGET=cooja clean +make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype792 + RPL root + [CONTIKI_DIR]/regression-tests/12-rpl/code/root-node.c + make TARGET=cooja clean +make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype964 + Receiver + [CONTIKI_DIR]/regression-tests/12-rpl/code/receiver-node.c + make TARGET=cooja clean +make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + 7.772906112657773 + 86.396910401861 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype964 + + + + org.contikios.cooja.interfaces.Position + 75.54361692539452 + 14.292026223193414 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype110 + + + + org.contikios.cooja.interfaces.Position + 47.962513687652844 + 7.199742533488408 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype964 + + + + org.contikios.cooja.interfaces.Position + 1.8626697045702818 + 47.783365869022624 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype964 + + + + org.contikios.cooja.interfaces.Position + 0.0 + 0.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype792 + + + + org.contikios.cooja.plugins.SimControl + 280 + 0 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 2.5379695437350276 0.0 0.0 2.5379695437350276 78.27260101976275 40.72727272727276 + + 400 + 2 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 1184 + 3 + 240 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 962 + 1 + 596 + 603 + 43 + + + diff --git a/regression-tests/23-rpl-non-storing/04-rpl-large-network.csc b/regression-tests/23-rpl-non-storing/04-rpl-large-network.csc new file mode 100644 index 000000000..f4ea0fda8 --- /dev/null +++ b/regression-tests/23-rpl-non-storing/04-rpl-large-network.csc @@ -0,0 +1,7058 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype710 + Sender + [CONTIKI_DIR]/regression-tests/12-rpl/code/sender-node.c + make TARGET=cooja clean +make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype709 + RPL root + [CONTIKI_DIR]/regression-tests/12-rpl/code/root-node.c + make TARGET=cooja clean +make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype332 + Receiver + [CONTIKI_DIR]/regression-tests/12-rpl/code/receiver-node.c + make TARGET=cooja clean +make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + -15.604889524290883 + -27.272920930192623 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 218.29521040499824 + 216.70287561143516 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype710 + + + + org.contikios.cooja.interfaces.Position + 0.0 + 0.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype709 + + + + org.contikios.cooja.interfaces.Position + 27.44274795318258 + 36.980443988209856 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 185.6055859234863 + 192.99166984979271 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 7.827315175624361 + 107.95833747378225 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 82.49199862549197 + 34.72851022020231 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 35.671428723363064 + 125.82590119075962 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 33.044376889885754 + 62.443378727185774 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 9 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 152.53659733643553 + 165.87608708149403 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 10 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 22.023077232445942 + 18.41094139254531 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 11 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 41.19368867821842 + 49.201157808285224 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 12 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 114.62128502432532 + 88.58807114217633 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 13 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 61.21405469314478 + 188.6851979777661 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 14 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 104.78326932115709 + 100.84889281105585 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 15 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 90.26861048950052 + 40.550864496421404 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 16 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 137.39112328314076 + 126.5333637365394 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 17 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 14.07616766247768 + 99.85572366133869 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 18 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 192.30563307960443 + 66.83563821262344 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 19 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 129.08253247651874 + 117.20437669309078 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 20 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 21.82717410659969 + 47.523771402541335 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 21 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 35.95102103988239 + 21.74677482276881 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 22 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 61.71108896268191 + 79.91617509627334 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 23 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 16.029809485043288 + 171.05935835280616 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 24 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 138.8418552766128 + 61.418703448852185 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 25 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 151.23299942414673 + 92.41820871538522 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 26 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 197.33157775573343 + 20.6013482653864 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 27 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 121.20762229879878 + 184.81107462083565 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 28 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 102.32432527534694 + 91.9912435435037 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 29 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 88.10909646999544 + 191.21251904898142 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 30 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 72.19774934085703 + 113.58131529956069 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 31 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 53.49967737007204 + 72.45172156882643 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 32 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 172.07186411958625 + 51.47715718716961 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 33 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 185.41983532466634 + 85.60078269414 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 34 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 83.34993971740548 + 193.98111239532744 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 35 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 105.03752362550378 + 131.24078026424087 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 36 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 176.09318670322102 + 41.46760901468247 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 37 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 76.80689915307215 + 47.13815728542057 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 38 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 155.907739287817 + 15.24009422994106 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 39 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 45.992463430523436 + 124.573811024683 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 40 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 159.11361032671832 + 81.65319598335425 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 41 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 41.838657583001314 + 163.47591213471193 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 42 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 25.560001904073125 + 147.48610852243928 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 43 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 139.56489350213488 + 191.15379557180913 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 44 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 105.71342550700061 + 136.09089690661503 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 45 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 122.59378462201298 + 196.22862961645998 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 46 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 147.61372446125088 + 55.314287700435536 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 47 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 77.70218628780312 + 95.59561907133107 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 48 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 71.88244578562713 + 168.57963926907163 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 49 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 6.722298767036894 + 101.09668965729898 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 50 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 62.96680217979964 + 77.66951408660954 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 51 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 162.49011735601982 + 199.07086470932003 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 52 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 87.87526390617558 + 114.39424478293958 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 53 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 74.29230372180815 + 36.995699473573836 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 54 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 77.34619341407321 + 60.070446577058576 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 55 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 76.32695571818826 + 135.82669004433725 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 56 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 68.10326013650814 + 5.04157445893032 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 57 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 95.76993029214962 + 45.046282401332945 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 58 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 79.87963205080952 + 110.7023948653882 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 59 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 195.90349780899223 + 132.38904172009444 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 60 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 80.40108440304007 + 25.86673418569547 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 61 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 52.268877618080744 + 176.12888723955277 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 62 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 40.545541404899765 + 166.9450252729589 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 63 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 10.676184465528205 + 0.9871174057552334 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 64 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 87.35673216830257 + 23.25131234780027 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 65 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 26.745126931691352 + 87.3101256645554 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 66 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 183.2724008541638 + 167.69026002459069 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 67 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 5.934720840855223 + 77.21248812623693 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 68 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 76.49604470599058 + 108.80963795015302 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 69 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 86.10145414955488 + 12.798582653303603 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 70 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 32.435370110193816 + 29.344591306898813 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 71 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 163.72950518161596 + 154.15283820759655 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 72 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 143.96396308843373 + 132.40312602892786 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 73 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 139.20530179839795 + 144.18958011498225 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 74 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 75.22453368236212 + 119.69913560274786 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 75 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 21.83836116635087 + 191.21696522067728 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 76 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 187.94640511976667 + 113.95684826994561 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 77 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 114.61289565250618 + 27.61001303446735 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 78 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 70.83569869750504 + 113.88992677636021 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 79 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 11.616059362048992 + 45.59401384110464 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 80 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 3.4282454263252937 + 35.97653370545284 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 81 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 54.33122057405715 + 1.9759087814547494 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 82 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 69.6612091444155 + 0.45982758130533874 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 83 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 169.98417155202168 + 87.76678058442593 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 84 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 148.98441194234616 + 104.32820155415494 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 85 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 66.23883124891583 + 162.92685536074129 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 86 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 181.6348837921769 + 183.07267240808343 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 87 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 88.9829570206748 + 119.72520333459575 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 88 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 179.1527012143494 + 84.25685075020328 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 89 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 117.82537007493707 + 41.10319533518651 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 90 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 52.611633540398486 + 94.71918054798351 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 91 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 128.22088664324633 + 115.50290142480077 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 92 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 102.53841128002531 + 11.784449645612295 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 93 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 187.69871925603667 + 131.28317666772048 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 94 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 71.13897508938263 + 106.29335632876602 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 95 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 71.2216469861295 + 148.38612859488788 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 96 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 36.152562577928784 + 67.541796718348 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 97 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 118.84793016344604 + 0.49906433835273933 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 98 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 135.20417096106954 + 170.20704631856816 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 99 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 156.082359043526 + 57.62103450217495 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 100 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 180.58695188377737 + 80.75266645775669 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 101 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 38.93889890269273 + 138.60259660238856 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 102 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 159.5172788118917 + 192.24950143209503 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 103 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 154.02096825135868 + 139.67175722659056 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 104 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 38.480826888323904 + 5.502866276505292 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 105 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 27.95908088015704 + 193.85188308665965 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 106 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 198.61700949829074 + 171.1877312716402 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 107 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 106.30468818084609 + 25.058380770654654 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 108 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 40.335672117825624 + 179.59080234641004 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 109 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 22.316357638510897 + 158.94323888090028 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 110 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 99.56281553229194 + 85.64260133077535 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 111 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 60.71556414510035 + 121.53040248649711 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 112 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 27.08600745576586 + 38.17025720346818 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 113 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 147.03642509910586 + 39.51320588416096 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 114 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 180.2031547656297 + 141.5646561330238 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 115 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 73.12314629214424 + 167.80783320779847 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 116 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 167.93567452922767 + 10.060141001139144 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 117 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 163.99198875105768 + 147.48735207074026 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 118 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 154.98654737808127 + 121.17266324007643 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 119 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 57.898499791676386 + 149.3487194893122 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 120 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 64.82082963563904 + 174.0100480348673 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 121 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 114.13623920898752 + 15.754246175503095 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 122 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 0.00848902940355778 + 195.50701335573908 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 123 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 182.81764401709623 + 78.57837811285111 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 124 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 11.462145876504714 + 95.37444120802225 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 125 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 115.5020283241771 + 28.49431396939579 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 126 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 62.463952359877275 + 77.78913013330184 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 127 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 9.766778039117696 + 136.7421944039438 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 128 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 35.320514349220055 + 100.56248258192493 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 129 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 56.26732169234614 + 3.095097140731262 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 130 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 76.90164393617998 + 3.5671096386384216 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 131 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 81.97549075841862 + 13.020422155003475 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 132 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 54.87200208203389 + 77.29445717372947 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 133 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 193.47651032749548 + 144.9357554583657 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 134 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 51.65288193591992 + 126.16687604535504 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 135 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 151.66849746442173 + 158.7699863850836 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 136 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 32.469410974826005 + 113.10993021698361 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 137 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 33.04622512107349 + 25.425445944702794 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 138 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 33.53444748873715 + 112.25721598241579 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 139 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 128.9401580272291 + 100.73482184242926 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 140 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 194.6592727528704 + 102.73664509470841 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 141 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 125.47343036050516 + 106.53155237731285 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 142 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 147.40129296416038 + 12.37607345376115 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 143 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 113.32045045397959 + 126.79285457987103 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 144 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 27.174837677715825 + 66.84349985536826 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 145 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 164.20252670136998 + 51.635539499142524 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 146 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 39.351673884988394 + 65.05462325698123 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 147 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 143.91486202542433 + 171.28435110465497 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 148 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 30.926988343440186 + 130.3647571119649 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 149 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 19.897357003413617 + 22.905473451246785 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 150 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 128.36369031733133 + 170.71462512320227 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 151 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 172.1648617546042 + 184.1928317689217 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 152 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 148.16672573170842 + 107.99684523382686 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 153 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 83.90300186263724 + 169.4761782218257 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 154 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 90.86887922361453 + 142.8036645841288 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 155 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 23.18966921326753 + 69.42635534680753 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 156 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 134.59433377860168 + 37.633119904417796 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 157 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 127.97132285920065 + 158.57917470101572 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 158 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 166.2450456558778 + 108.67197275397042 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 159 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 167.334034200758 + 22.173554305333166 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 160 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 163.54194527237107 + 189.41605447848966 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 161 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 14.863357513573018 + 93.36644051662617 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 162 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 178.4370382798651 + 191.48348446587636 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 163 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 172.96087703915273 + 183.78535300027013 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 164 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 2.45779137738229 + 58.750309492130114 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 165 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 15.730601618735495 + 96.52335072173565 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 166 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 19.890833428932165 + 56.993000152370364 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 167 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 154.69166608840504 + 164.8598339150269 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 168 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 199.77196118880582 + 26.034321005016903 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 169 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 5.216343266336931 + 17.867912968799615 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 170 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 138.71273406283296 + 55.31024592694844 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 171 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 168.21144361519595 + 163.1843284579423 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 172 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 61.82504434646854 + 134.03197926926038 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 173 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 14.007317972338473 + 146.98475859141027 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 174 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 108.44210606040488 + 127.81076428732186 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 175 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 133.41957560864708 + 122.91534078890439 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 176 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 184.89266828168118 + 195.7201293014503 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 177 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 121.10492556426465 + 78.54418709376823 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 178 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 42.05271519544296 + 183.14259881514795 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 179 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 92.12119616387746 + 44.853464007589714 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 180 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 136.44039199596196 + 1.111619893261917 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 181 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 64.37440878278696 + 188.3078368775181 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 182 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 37.774149552594594 + 73.81683900641865 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 183 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 24.618589360988175 + 164.89708336795567 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 184 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 152.5950797265111 + 140.96774353352123 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 185 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 37.96933854365052 + 131.92434845994435 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 186 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 14.05145808951862 + 26.159084136809916 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 187 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 61.47558158857349 + 68.73507104275693 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 188 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 35.420404733112385 + 108.47794695541302 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 189 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 129.0179255565185 + 176.46977408461998 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 190 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 4.437687657989087 + 191.43801818673953 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 191 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 132.39232886927158 + 105.56546037448346 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 192 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 193.9356389936735 + 76.8987220921185 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 193 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 123.49672189705024 + 16.28922647444049 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 194 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 40.44058024960566 + 94.77629608096818 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 195 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 93.54168452285269 + 102.10342793159373 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 196 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 176.91858637781746 + 81.80773827257306 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 197 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 182.5062159995403 + 10.047631291589564 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 198 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 151.3211952231698 + 160.98807517681706 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 199 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 167.8826595707132 + 160.3686256248768 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 200 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 93.38491122055773 + 61.04322963139093 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 201 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 155.20211039479165 + 104.99915002371228 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 202 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 154.56882959476744 + 192.77647809954323 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 203 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 119.88029558288524 + 48.71837870038327 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 204 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 8.237800167806908 + 123.56280331420268 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 205 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 53.424877837249696 + 87.33638375233281 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 206 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 199.25320093864096 + 66.76343110330383 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 207 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 166.7255674935148 + 165.31992478582075 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 208 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 135.9334286576811 + 130.36986226660702 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 209 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 65.60950768388696 + 14.081940005079275 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 210 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 56.68133966983844 + 196.61338214776293 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 211 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 2.562777529582072 + 66.73129709411079 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 212 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 34.10919172462936 + 176.31986637140767 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 213 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 33.846173186403306 + 142.33660392777279 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 214 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 128.76326079790124 + 90.05136184351706 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 215 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 80.39617891964872 + 111.48714907972395 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 216 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 21.97338508940303 + 61.032785792453815 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 217 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 158.00182839254427 + 175.79991821384095 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 218 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 64.21702017661488 + 197.8650659620092 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 219 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 58.261430108425174 + 69.56229252260285 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 220 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 114.85635789777962 + 130.3021189977344 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 221 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 24.601661057872736 + 196.33046445845073 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 222 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 136.22037670133446 + 18.019579846123435 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 223 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 71.91168973841357 + 193.3123397692768 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 224 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 76.67497322258676 + 156.30488619961912 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 225 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 85.70841880772959 + 39.914700874835106 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 226 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 142.3427145819395 + 76.80244108802334 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 227 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 45.6821653485997 + 33.96733547026549 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 228 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 146.16353499121948 + 5.58117117441268 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 229 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 34.32680631388174 + 111.76495490887346 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 230 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 138.5676204843924 + 161.4559204389253 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 231 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 196.36096598095253 + 19.9809316402896 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 232 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 190.5761031572042 + 118.16570999859783 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 233 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 137.89894164409372 + 114.36842366282201 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 234 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 13.942927177934262 + 25.042265908173977 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 235 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 21.808225381827363 + 89.51408500063611 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 236 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 82.1665299576559 + 89.41818802221223 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 237 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 100.24631818801446 + 85.16089691564225 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 238 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 150.87166478995505 + 124.32687790892683 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 239 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 196.72953604773366 + 89.0589559016778 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 240 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 178.10423185724105 + 108.01295472332721 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 241 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 24.852336661830865 + 107.10027825925053 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 242 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 198.2838988728342 + 185.2533889301396 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 243 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 122.42366366542863 + 13.685145107609165 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 244 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 113.58516359448151 + 59.212889358544054 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 245 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 148.6689453992514 + 65.76664113968091 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 246 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 110.90604811956779 + 118.12368970120251 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 247 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 195.48877933255176 + 71.61703558744803 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 248 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 90.74911177135543 + 151.9662290090636 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 249 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 5.669662023293154 + 80.71705944385323 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 250 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 77.57071934873466 + 25.884947016521597 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 251 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 172.38535892291588 + 6.827522113737539 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 252 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 62.61595677732154 + 171.52926299696654 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 253 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 163.1605182212256 + 136.67511261098457 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 254 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 174.98684717123461 + 163.9648526025463 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 255 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 112.4179766207543 + 108.05999669756379 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 256 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 71.60510656526031 + 96.23183516652448 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 257 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 51.39949089302518 + 181.73639564248649 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 258 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 140.61625635482116 + 118.88528060437326 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 259 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 81.11235868256772 + 71.16703221921186 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 260 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 106.30383323544051 + 47.66664077552125 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 261 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 78.36392430481997 + 145.12300889005226 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 262 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 159.2795584664916 + 175.42365153724947 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 263 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 89.12806123792214 + 163.88074620615808 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 264 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 188.00194321004403 + 167.99738752402368 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 265 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 186.544702443713 + 156.12158395696437 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 266 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 2.8406717287810412 + 38.380349570314664 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 267 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 28.76119804764801 + 168.10637626762275 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 268 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 190.1115654346047 + 36.24498374070968 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 269 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 67.43484884843447 + 118.69086680825731 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 270 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 50.7959234692023 + 165.04960719272802 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 271 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 50.75575271798458 + 144.55723570362358 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 272 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 128.94257968083764 + 47.32490472068322 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 273 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 1.9193343221312942 + 112.82658785936086 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 274 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 51.82023785974064 + 148.28034473499338 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 275 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 98.55603081185546 + 178.02566808501155 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 276 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 143.40572664084078 + 183.27302398341982 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 277 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 141.0619733646239 + 54.122738136324955 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 278 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 162.29942916334053 + 67.55247227617933 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 279 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 185.29686875363197 + 118.81126461905944 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 280 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 104.06690998854779 + 5.511220514887172 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 281 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 181.82429252421596 + 47.0700962247878 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 282 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 17.604228655775245 + 96.78328313290936 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 283 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 60.74231839144737 + 136.8041677309854 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 284 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 158.57791000335715 + 90.16811700419458 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 285 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 26.040369760119475 + 115.48428978095157 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 286 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 155.33825554510548 + 122.61758874267335 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 287 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 171.04754637183774 + 49.44780022857469 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 288 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 130.8601631228818 + 115.38443324744807 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 289 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 138.51066172926747 + 85.05731662406394 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 290 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 17.01860916014879 + 85.74431631403492 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 291 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 63.632763185894994 + 73.28193598294403 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 292 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 145.51992557600448 + 190.19645657449914 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 293 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 141.3669225587347 + 128.37798094188392 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 294 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 5.624436269305666 + 10.321359475496084 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 295 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 32.62210104212715 + 80.99365929301005 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 296 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 146.82462375206796 + 189.00512676494264 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 297 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 96.89937776974169 + 61.868257009019125 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 298 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 71.17532023107206 + 32.87953533289934 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 299 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 37.21430187397199 + 21.880189704400976 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 300 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 123.17178528937387 + 23.802492560334287 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 301 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 139.8264101859233 + 106.93416114169838 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 302 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 34.97792194896952 + 182.11554692137054 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 303 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 156.016327676095 + 83.35423896139108 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 304 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 33.33352678715003 + 148.24111721535743 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 305 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 22.525965053498552 + 94.23130431241577 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 306 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 145.40586007739483 + 194.77296443866655 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 307 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 64.78487058910738 + 34.59908782949142 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 308 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 59.86114357954142 + 143.29623794752337 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 309 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 133.03711837762597 + 0.29677881350260726 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 310 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 184.05437940334514 + 80.34917749334691 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 311 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 43.18494391360306 + 0.7070568470557648 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 312 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 87.88579984985796 + 183.6845166360299 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 313 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 35.679149788796785 + 59.900754257451624 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 314 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 10.837936713278706 + 68.65555543408139 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 315 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 28.088726188466005 + 66.6117410256945 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 316 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 24.15305881985441 + 127.36722357863377 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 317 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 167.92463302345024 + 95.32246240241238 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 318 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 150.07537910034364 + 189.29680149689028 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 319 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 36.60193942102408 + 4.850860928459388 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 320 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 131.4804357164766 + 107.37981261172979 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 321 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 4.702056299253576 + 145.3571381517292 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 322 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 76.83393335740108 + 40.92489706855471 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 323 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 81.41902810900726 + 59.67311069186907 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 324 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 157.9286881274713 + 35.89390157980119 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 325 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 172.59261547136273 + 162.21173966194792 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 326 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 63.77983240079481 + 110.66181735649987 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 327 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 94.27259269172448 + 102.22907067171563 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 328 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 87.82927755519094 + 154.83172363042706 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 329 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 61.424763006386954 + 73.54903523332621 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 330 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 193.50994444846046 + 100.37438735826956 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 331 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 160.15646353486886 + 197.56265442862397 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 332 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 33.41179410209567 + 85.51716211010236 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 333 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 39.55932830334419 + 79.79114070992594 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 334 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 29.81531743952457 + 106.52370973616816 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 335 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 145.66591758403607 + 93.84627277397392 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 336 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 121.12689025085304 + 141.7616054105135 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 337 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 31.696932817539736 + 73.39512842700171 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 338 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 73.55413175311341 + 184.10063535264334 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 339 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 179.21266954315877 + 157.77936426661222 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 340 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 5.861701400590658 + 176.44679868441557 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 341 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 164.32858198885157 + 127.1649251930171 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 342 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 104.78813885934602 + 2.6978015525372934 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 343 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 9.036210189825722 + 37.29651951364714 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 344 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 69.09633192708777 + 131.08113653458605 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 345 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 23.989325789242024 + 102.76529191595212 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 346 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 32.563144827068456 + 174.05783874991164 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 347 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 26.84717981820497 + 33.708035418260465 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 348 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 23.651571274100892 + 150.9696150146202 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 349 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 7.263970263317554 + 178.4551746541966 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 350 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 137.19080046610807 + 195.47642758858956 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 351 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 100.60258790901588 + 10.122226122279043 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 352 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 158.02955707421086 + 15.552042272281575 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 353 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 69.03288347183658 + 86.65939835169405 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 354 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 197.11534487465465 + 12.227887489891408 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 355 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 109.32664513099861 + 51.47545505189106 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 356 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 7.450618560323541 + 114.12792666368863 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 357 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 96.73499758330652 + 87.34903664585806 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 358 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 143.42568088659735 + 154.7201550387036 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 359 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 16.055115327242596 + 23.72235108907279 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 360 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 36.54118641672248 + 71.60060131854802 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 361 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 153.4641555525212 + 182.30266241969497 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 362 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 179.79961054026052 + 52.374917374947486 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 363 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 51.89511924887278 + 55.715278818289924 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 364 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 160.22911392558143 + 197.03727711739174 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 365 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 141.50401865962175 + 198.17183635084353 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 366 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 144.1436553724308 + 66.26788567722302 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 367 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 114.85639238072662 + 187.02866922391485 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 368 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 14.754418142216963 + 189.75568091879705 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 369 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 40.445861020644756 + 132.87622199437286 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 370 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 70.41846318684537 + 16.353121961748673 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 371 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 11.524098377391411 + 188.46037552576104 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 372 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 19.80490164758435 + 193.31200682922997 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 373 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 170.32256510777594 + 170.204813941954 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 374 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 35.11638379627671 + 106.63452905636245 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 375 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 87.80726944100199 + 69.16884374165753 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 376 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 45.63781115512378 + 137.1790704392972 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 377 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 120.23124867416645 + 21.60172442725463 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 378 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 42.584241021086264 + 172.9365035614701 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 379 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 106.9111221907689 + 35.38132573733432 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 380 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 115.65012523180343 + 149.06748739273075 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 381 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 66.70597176653999 + 151.96624665556067 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 382 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 116.86108695969573 + 92.96503821223025 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 383 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 138.3454858274232 + 60.335069940591254 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 384 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 35.21169262537829 + 57.75683948274251 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 385 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 183.64109836494706 + 187.89865943504947 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 386 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 124.92709985349823 + 7.139364140447135 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 387 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 121.19563498360651 + 163.5898829983739 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 388 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 141.67701483198246 + 36.967824799613645 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 389 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 116.85490603618803 + 192.1746914581395 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 390 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 157.23646122348265 + 101.21354943885676 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 391 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 58.04596641555313 + 180.0770488919343 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 392 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 118.342960728573 + 65.22048911724025 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 393 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 61.42203823259405 + 117.333210601775 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 394 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 136.13358028390385 + 97.99627507346685 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 395 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 82.86089860898949 + 25.22615052347874 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 396 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 6.721379593879373 + 94.78763681182285 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 397 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 38.69266957378596 + 24.113141554020046 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 398 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 111.22857295130957 + 95.51634459331788 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 399 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 126.7915415569141 + 32.23798771734878 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 400 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 186.84699461455236 + 34.76662976923288 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 401 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 122.45497909139493 + 167.0773654715768 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 402 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.interfaces.Position + 33.03449972907999 + 172.77024458531486 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 403 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype332 + + + + org.contikios.cooja.plugins.SimControl + 280 + 3 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + 1.1671649566739442 0.0 0.0 1.1671649566739442 66.21348020552065 40.83199757586018 + + 400 + 2 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 1184 + 0 + 240 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 962 + 1 + 596 + 603 + 43 + + \ No newline at end of file diff --git a/regression-tests/23-rpl-non-storing/05-rpl-up-and-down-routes.csc b/regression-tests/23-rpl-non-storing/05-rpl-up-and-down-routes.csc new file mode 100644 index 000000000..0dd110738 --- /dev/null +++ b/regression-tests/23-rpl-non-storing/05-rpl-up-and-down-routes.csc @@ -0,0 +1,342 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype743 + Sender + [CONFIG_DIR]/code/sender-node.c + make clean TARGET=cooja +make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype452 + RPL root + [CONFIG_DIR]/code/root-node.c + make clean TARGET=cooja +make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype782 + Receiver + [CONFIG_DIR]/code/receiver-node.c + make clean TARGET=cooja +make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + -22.5728586847096 + 123.9358664968653 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 116.13379149678028 + 88.36698920455684 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype743 + + + + org.contikios.cooja.interfaces.Position + -1.39303771455413 + 100.21446701029119 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 95.25095618820441 + 63.14998053005015 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 66.09378990830604 + 38.32698761608261 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 29.05630841762433 + 30.840688165838436 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 10.931583432822638 + 69.848248459216 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype782 + + + + org.contikios.cooja.interfaces.Position + 0.0 + 0.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype452 + + + + org.contikios.cooja.plugins.SimControl + 280 + 1 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 2.5379695437350276 0.0 0.0 2.5379695437350276 75.2726010197627 15.727272727272757 + + 400 + 2 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + 1184 + 3 + 240 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 962 + 0 + 596 + 603 + 43 + + + diff --git a/regression-tests/23-rpl-non-storing/06-rpl-temporary-root-loss.csc b/regression-tests/23-rpl-non-storing/06-rpl-temporary-root-loss.csc new file mode 100644 index 000000000..6c29c643f --- /dev/null +++ b/regression-tests/23-rpl-non-storing/06-rpl-temporary-root-loss.csc @@ -0,0 +1,348 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype951 + Sender + [CONFIG_DIR]/code/sender-node.c + make clean TARGET=cooja +make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype170 + RPL root + [CONFIG_DIR]/code/root-node.c + make clean TARGET=cooja +make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype767 + Receiver + [CONFIG_DIR]/code/receiver-node.c + make clean TARGET=cooja +make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + -22.5728586847096 + 123.9358664968653 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype767 + + + + org.contikios.cooja.interfaces.Position + 116.13379149678028 + 88.36698920455684 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype951 + + + + org.contikios.cooja.interfaces.Position + -1.39303771455413 + 100.21446701029119 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype767 + + + + org.contikios.cooja.interfaces.Position + 95.25095618820441 + 63.14998053005015 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype767 + + + + org.contikios.cooja.interfaces.Position + 66.09378990830604 + 38.32698761608261 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype767 + + + + org.contikios.cooja.interfaces.Position + 29.05630841762433 + 30.840688165838436 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype767 + + + + org.contikios.cooja.interfaces.Position + 10.931583432822638 + 69.848248459216 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype767 + + + + org.contikios.cooja.interfaces.Position + 0.0 + 0.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype170 + + + + org.contikios.cooja.plugins.SimControl + 280 + 0 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 2.5379695437350276 0.0 0.0 2.5379695437350276 75.2726010197627 15.727272727272757 + + 400 + 2 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + 1184 + 3 + 240 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 962 + 1 + 596 + 603 + 43 + + + diff --git a/regression-tests/23-rpl-non-storing/07-rpl-random-rearrangement.csc b/regression-tests/23-rpl-non-storing/07-rpl-random-rearrangement.csc new file mode 100644 index 000000000..cdb62c420 --- /dev/null +++ b/regression-tests/23-rpl-non-storing/07-rpl-random-rearrangement.csc @@ -0,0 +1,647 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype419 + Sender + [CONFIG_DIR]/code/sender-node.c + make clean TARGET=cooja +make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype484 + RPL root + [CONFIG_DIR]/code/root-node.c + make clean TARGET=cooja +make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype718 + Receiver + [CONFIG_DIR]/code/receiver-node.c + make clean TARGET=cooja +make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + -0.4799968467515439 + 98.79087181374759 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 99.56423154395364 + 50.06466731257512 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype419 + + + + org.contikios.cooja.interfaces.Position + -0.4799968467515439 + 0.30173505605854883 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype484 + + + + org.contikios.cooja.interfaces.Position + 12.779318616702257 + 8.464865358169643 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 9.391922400291703 + 49.22878206790311 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 48.16367625505583 + 33.27520746599595 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 16.582742473429345 + 24.932911331640646 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 8.445564421140666 + 6.770205395698742 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 87.04968129458189 + 34.46536562612724 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 9 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 94.47123252519145 + 18.275940194868184 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 10 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 95.28044254364556 + 17.683438211793558 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 11 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 56.124622439456076 + 33.88966252832571 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 12 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 98.33149749474546 + 37.448034626592744 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 13 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 58.75337436025891 + 68.64082018992522 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 14 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 66.83816496627988 + 68.38008376830592 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 15 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 90.88648665466316 + 50.942053906416575 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 16 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 68.80089833632896 + 84.17294684073734 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 17 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 73.6760846183129 + 81.76699743886633 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 18 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 0.2960103456537466 + 98.5587829617092 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 19 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 8.130479493904208 + 57.642099520821645 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 20 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 30.550120982984865 + 85.58346736403402 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 21 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 29.65300377698182 + 63.50257213104861 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 22 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.interfaces.Position + 34.92110687576687 + 70.71381297232249 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 23 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype718 + + + + org.contikios.cooja.plugins.SimControl + 280 + 1 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 1.92914676942954 0.0 0.0 1.92914676942954 75.9259843662471 55.41790879138101 + + 400 + 2 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 1184 + 3 + 500 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 612 + 0 + 726 + 953 + 43 + + + diff --git a/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-0.csc b/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-0.csc new file mode 100644 index 000000000..0fc6e032d --- /dev/null +++ b/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-0.csc @@ -0,0 +1,360 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype921 + Sender + [CONFIG_DIR]/code/sender-node.c + make clean TARGET=cooja +make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype873 + RPL root + [CONFIG_DIR]/code/root-node.c + make clean TARGET=cooja +make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype812 + Receiver + [CONFIG_DIR]/code/receiver-node.c + make clean TARGET=cooja +make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + -7.199692787830563 + 98.21738321803603 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype812 + + + + org.contikios.cooja.interfaces.Position + 116.13379149678028 + 88.36698920455684 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype921 + + + + org.contikios.cooja.interfaces.Position + 12.0 + 68.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype812 + + + + org.contikios.cooja.interfaces.Position + 95.25095618820441 + 63.14998053005015 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype812 + + + + org.contikios.cooja.interfaces.Position + 66.09378990830604 + 38.32698761608261 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype812 + + + + org.contikios.cooja.interfaces.Position + 29.05630841762433 + 30.840688165838436 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype812 + + + + org.contikios.cooja.interfaces.Position + 58.0 + 108.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype812 + + + + org.contikios.cooja.interfaces.Position + -40.352178879596096 + 102.66976131212861 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype873 + + + + org.contikios.cooja.plugins.SimControl + 280 + 3 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 1.6480321712565114 0.0 0.0 1.6480321712565114 98.5016889738719 55.796930342384904 + + 400 + 0 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 1184 + 2 + 500 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 612 + 1 + 726 + 953 + 43 + + + diff --git a/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-1.csc b/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-1.csc new file mode 100644 index 000000000..2c0ce41ff --- /dev/null +++ b/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-1.csc @@ -0,0 +1,360 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype672 + Sender + [CONFIG_DIR]/code/sender-node.c + make clean TARGET=cooja +make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype780 + RPL root + [CONFIG_DIR]/code/root-node.c + make clean TARGET=cooja +make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype36 + Receiver + [CONFIG_DIR]/code/receiver-node.c + make clean TARGET=cooja +make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + -7.199692787830563 + 98.21738321803603 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 116.13379149678028 + 88.36698920455684 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype672 + + + + org.contikios.cooja.interfaces.Position + 12.0 + 68.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 95.25095618820441 + 63.14998053005015 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 66.09378990830604 + 38.32698761608261 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 29.05630841762433 + 30.840688165838436 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 58.0 + 108.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + -25.71843353317142 + 43.05517674255262 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype780 + + + + org.contikios.cooja.plugins.SimControl + 280 + 3 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 2.5379695437350276 0.0 0.0 2.5379695437350276 75.2726010197627 15.727272727272757 + + 400 + 2 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 1184 + 1 + 500 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 612 + 0 + 726 + 953 + 43 + + + diff --git a/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-2.csc b/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-2.csc new file mode 100644 index 000000000..cdb2bd748 --- /dev/null +++ b/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-2.csc @@ -0,0 +1,360 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype672 + Sender + [CONFIG_DIR]/code/sender-node.c + make clean TARGET=cooja +make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype780 + RPL root + [CONFIG_DIR]/code/root-node.c + make clean TARGET=cooja +make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype36 + Receiver + [CONFIG_DIR]/code/receiver-node.c + make clean TARGET=cooja +make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + -7.199692787830563 + 98.21738321803603 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 116.13379149678028 + 88.36698920455684 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype672 + + + + org.contikios.cooja.interfaces.Position + 12.0 + 68.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 95.25095618820441 + 63.14998053005015 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 66.09378990830604 + 38.32698761608261 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 29.05630841762433 + 30.840688165838436 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 58.0 + 108.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 16.0472370839803 + 6.017695251870905 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype780 + + + + org.contikios.cooja.plugins.SimControl + 280 + 3 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 2.5379695437350276 0.0 0.0 2.5379695437350276 75.2726010197627 15.727272727272757 + + 400 + 0 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 1184 + 2 + 500 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 612 + 1 + 726 + 953 + 43 + + + diff --git a/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-3.csc b/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-3.csc new file mode 100644 index 000000000..34b930c0d --- /dev/null +++ b/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-3.csc @@ -0,0 +1,360 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype672 + Sender + [CONFIG_DIR]/code/sender-node.c + make clean TARGET=cooja +make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype780 + RPL root + [CONFIG_DIR]/code/root-node.c + make clean TARGET=cooja +make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype36 + Receiver + [CONFIG_DIR]/code/receiver-node.c + make clean TARGET=cooja +make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + -7.199692787830563 + 98.21738321803603 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 116.13379149678028 + 88.36698920455684 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype672 + + + + org.contikios.cooja.interfaces.Position + 12.0 + 68.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 95.25095618820441 + 63.14998053005015 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 66.09378990830604 + 38.32698761608261 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 29.05630841762433 + 30.840688165838436 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 58.0 + 108.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype36 + + + + org.contikios.cooja.interfaces.Position + 79.48377453078622 + 4.835647970253402 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype780 + + + + org.contikios.cooja.plugins.SimControl + 280 + 3 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 2.5379695437350276 0.0 0.0 2.5379695437350276 70.27260101976269 60.72727272727276 + + 400 + 0 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 1184 + 2 + 500 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 612 + 1 + 726 + 953 + 43 + + + diff --git a/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-4.csc b/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-4.csc new file mode 100644 index 000000000..ff9a400c1 --- /dev/null +++ b/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-4.csc @@ -0,0 +1,360 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype192 + Sender + [CONFIG_DIR]/code/sender-node.c + make clean TARGET=cooja +make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype575 + RPL root + [CONFIG_DIR]/code/root-node.c + make clean TARGET=cooja +make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype912 + Receiver + [CONFIG_DIR]/code/receiver-node.c + make clean TARGET=cooja +make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + -7.199692787830563 + 98.21738321803603 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype912 + + + + org.contikios.cooja.interfaces.Position + 116.13379149678028 + 88.36698920455684 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype192 + + + + org.contikios.cooja.interfaces.Position + 12.0 + 68.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype912 + + + + org.contikios.cooja.interfaces.Position + 95.25095618820441 + 63.14998053005015 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype912 + + + + org.contikios.cooja.interfaces.Position + 66.09378990830604 + 38.32698761608261 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype912 + + + + org.contikios.cooja.interfaces.Position + 29.05630841762433 + 30.840688165838436 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype912 + + + + org.contikios.cooja.interfaces.Position + 58.0 + 108.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype912 + + + + org.contikios.cooja.interfaces.Position + 122.82550819009461 + 29.658640884220933 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype575 + + + + org.contikios.cooja.plugins.SimControl + 280 + 3 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 2.5379695437350276 0.0 0.0 2.5379695437350276 70.27260101976269 60.72727272727276 + + 400 + 0 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 1184 + 2 + 500 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 612 + 1 + 726 + 953 + 43 + + + diff --git a/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-5.csc b/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-5.csc new file mode 100644 index 000000000..e491b666f --- /dev/null +++ b/regression-tests/23-rpl-non-storing/08-rpl-dao-route-loss-5.csc @@ -0,0 +1,360 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype372 + Sender + [CONFIG_DIR]/code/sender-node.c + make clean TARGET=cooja +make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype229 + RPL root + [CONFIG_DIR]/code/root-node.c + make clean TARGET=cooja +make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype424 + Receiver + [CONFIG_DIR]/code/receiver-node.c + make clean TARGET=cooja +make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + -7.199692787830563 + 98.21738321803603 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype424 + + + + org.contikios.cooja.interfaces.Position + 116.13379149678028 + 88.36698920455684 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype372 + + + + org.contikios.cooja.interfaces.Position + 12.0 + 68.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype424 + + + + org.contikios.cooja.interfaces.Position + 95.25095618820441 + 63.14998053005015 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype424 + + + + org.contikios.cooja.interfaces.Position + 66.09378990830604 + 38.32698761608261 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype424 + + + + org.contikios.cooja.interfaces.Position + 29.05630841762433 + 30.840688165838436 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype424 + + + + org.contikios.cooja.interfaces.Position + 58.0 + 108.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype424 + + + + org.contikios.cooja.interfaces.Position + 145.93059238811136 + 111.16474110935306 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype229 + + + + org.contikios.cooja.plugins.SimControl + 280 + 3 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 1.6480321712565114 0.0 0.0 1.6480321712565114 98.5016889738719 55.796930342384904 + + 400 + 0 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 1184 + 2 + 500 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 612 + 1 + 726 + 953 + 43 + + + diff --git a/regression-tests/23-rpl-non-storing/09-rpl-probing.csc b/regression-tests/23-rpl-non-storing/09-rpl-probing.csc new file mode 100644 index 000000000..66a156e9c --- /dev/null +++ b/regression-tests/23-rpl-non-storing/09-rpl-probing.csc @@ -0,0 +1,256 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype190 + Sender + [CONTIKI_DIR]/regression-tests/12-rpl/code/sender-node.c + make clean TARGET=cooja +make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype481 + RPL root + [CONTIKI_DIR]/regression-tests/12-rpl/code/root-node.c + make clean TARGET=cooja +make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype692 + Receiver + [CONTIKI_DIR]/regression-tests/12-rpl/code/receiver-node.c + make clean TARGET=cooja +make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + 8.0 + 2.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype481 + + + + org.contikios.cooja.interfaces.Position + -7.19071602882406 + 34.96668248624779 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype190 + + + + org.contikios.cooja.interfaces.Position + -17.870288882812428 + 4.581754854333804 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype692 + + + + org.contikios.cooja.plugins.SimControl + 280 + 2 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + true + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 2.494541140753371 0.0 0.0 2.494541140753371 168.25302383129448 116.2254386098645 + + 400 + 3 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 597 + 0 + 428 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 605 + 1 + 684 + 604 + 14 + + + diff --git a/regression-tests/23-rpl-non-storing/10-rpl-multi-dodag.csc b/regression-tests/23-rpl-non-storing/10-rpl-multi-dodag.csc new file mode 100644 index 000000000..0f446cc65 --- /dev/null +++ b/regression-tests/23-rpl-non-storing/10-rpl-multi-dodag.csc @@ -0,0 +1,389 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + [APPS_DIR]/serial2pty + [APPS_DIR]/radiologger-headless + + My simulation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 50.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype301 + Sender + [CONTIKI_DIR]/regression-tests/12-rpl/code/sender-node.c + make sender-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype820 + RPL root + [CONTIKI_DIR]/regression-tests/12-rpl/code/root-node.c + make root-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype306 + Receiver + [CONTIKI_DIR]/regression-tests/12-rpl/code/receiver-node.c + make receiver-node.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + 9.767954940345236 + 88.75813939592845 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype306 + + + + org.contikios.cooja.interfaces.Position + 63.36720084537501 + 75.88456991067605 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype301 + + + + org.contikios.cooja.interfaces.Position + -20.684049350551753 + 60.49767834794315 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 6 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype306 + + + + org.contikios.cooja.interfaces.Position + 64.61229064867878 + 39.88729002781773 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 3 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype306 + + + + org.contikios.cooja.interfaces.Position + 37.157272454309606 + 19.60335867526139 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 4 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype306 + + + + org.contikios.cooja.interfaces.Position + -21.976612887408603 + 30.69884249204435 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 5 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype306 + + + + org.contikios.cooja.interfaces.Position + 43 + 98 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 7 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype820 + + + + org.contikios.cooja.interfaces.Position + 0.0 + 0.0 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 8 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype820 + + + + org.contikios.cooja.plugins.SimControl + 280 + 3 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + 1.7624788498159916 0.0 0.0 1.7624788498159916 97.6893062637241 8.72727272727273 + + 400 + 0 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + + + + + 1184 + 2 + 240 + 402 + 162 + + + org.contikios.cooja.plugins.Notes + + Enter notes here + true + + 904 + 4 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 962 + 1 + 596 + 603 + 43 + + + diff --git a/regression-tests/23-rpl-non-storing/Makefile b/regression-tests/23-rpl-non-storing/Makefile new file mode 100644 index 000000000..272bc7da1 --- /dev/null +++ b/regression-tests/23-rpl-non-storing/Makefile @@ -0,0 +1 @@ +include ../Makefile.simulation-test diff --git a/regression-tests/23-rpl-non-storing/code/Makefile b/regression-tests/23-rpl-non-storing/code/Makefile new file mode 100644 index 000000000..616341592 --- /dev/null +++ b/regression-tests/23-rpl-non-storing/code/Makefile @@ -0,0 +1,7 @@ +all: sender-node receiver-node root-node +CONTIKI=../../.. + +CFLAGS+=-DPROJECT_CONF_H=\"project-conf.h\" + +CONTIKI_WITH_IPV6 = 1 +include $(CONTIKI)/Makefile.include diff --git a/regression-tests/23-rpl-non-storing/code/project-conf.h b/regression-tests/23-rpl-non-storing/code/project-conf.h new file mode 100644 index 000000000..9270334fb --- /dev/null +++ b/regression-tests/23-rpl-non-storing/code/project-conf.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2016, Inria. + * 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. + */ +#define TCPIP_CONF_ANNOTATE_TRANSMISSIONS 1 + +#undef RPL_CONF_MOP +#define RPL_CONF_MOP RPL_MOP_NON_STORING + +/* Add a bit of extra probing in the non-storing case to compensate for reduced DAO traffic */ +#undef RPL_CONF_PROBING_INTERVAL +#define RPL_CONF_PROBING_INTERVAL (60 * CLOCK_SECOND) diff --git a/regression-tests/23-rpl-non-storing/code/receiver-node.c b/regression-tests/23-rpl-non-storing/code/receiver-node.c new file mode 100644 index 000000000..727a23f84 --- /dev/null +++ b/regression-tests/23-rpl-non-storing/code/receiver-node.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2012, Thingsquare, www.thingsquare.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 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. + */ + +#include "contiki.h" +#include "lib/random.h" +#include "sys/ctimer.h" +#include "sys/etimer.h" +#include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" +#include "net/ip/uip-debug.h" + +#include "simple-udp.h" + +#include "net/rpl/rpl.h" +#include "dev/leds.h" + +#include +#include + +#define UDP_PORT 1234 + +static struct simple_udp_connection unicast_connection; + +/*---------------------------------------------------------------------------*/ +PROCESS(receiver_node_process, "Receiver node"); +AUTOSTART_PROCESSES(&receiver_node_process); +/*---------------------------------------------------------------------------*/ +static void +receiver(struct simple_udp_connection *c, + const uip_ipaddr_t *sender_addr, + uint16_t sender_port, + const uip_ipaddr_t *receiver_addr, + uint16_t receiver_port, + const uint8_t *data, + uint16_t datalen) +{ + printf("Data received from "); + uip_debug_ipaddr_print(sender_addr); + printf(" on port %d from port %d with length %d: '%s'\n", + receiver_port, sender_port, datalen, data); +} +/*---------------------------------------------------------------------------*/ +static uip_ipaddr_t * +set_global_address(void) +{ + static uip_ipaddr_t ipaddr; + int i; + uint8_t state; + + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + + printf("IPv6 addresses: "); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && + (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { + uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); + printf("\n"); + } + } + + return &ipaddr; +} +/*---------------------------------------------------------------------------*/ +uint8_t should_blink = 1; +static void +route_callback(int event, uip_ipaddr_t *route, uip_ipaddr_t *ipaddr, int num_routes) +{ + if(event == UIP_DS6_NOTIFICATION_DEFRT_ADD) { + should_blink = 0; + } else if(event == UIP_DS6_NOTIFICATION_DEFRT_RM) { + should_blink = 1; + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(receiver_node_process, ev, data) +{ + static struct etimer et; + static struct uip_ds6_notification n; + + PROCESS_BEGIN(); + + set_global_address(); + + uip_ds6_notification_add(&n, route_callback); + + simple_udp_register(&unicast_connection, UDP_PORT, + NULL, UDP_PORT, receiver); + + etimer_set(&et, CLOCK_SECOND); + while(1) { + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + etimer_reset(&et); + if(should_blink) { + leds_on(LEDS_ALL); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + etimer_reset(&et); + leds_off(LEDS_ALL); + } + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/regression-tests/23-rpl-non-storing/code/root-node.c b/regression-tests/23-rpl-non-storing/code/root-node.c new file mode 100644 index 000000000..fdea828f8 --- /dev/null +++ b/regression-tests/23-rpl-non-storing/code/root-node.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2012, Thingsquare, www.thingsquare.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 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. + */ + + +#include "contiki.h" +#include "lib/random.h" +#include "sys/ctimer.h" +#include "sys/etimer.h" +#include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" +#include "net/ip/uip-debug.h" + +#include "simple-udp.h" + +#include "net/rpl/rpl.h" + +#include +#include + +#define UDP_PORT 1234 +#define SERVICE_ID 190 + +#define SEND_INTERVAL (10 * CLOCK_SECOND) +#define SEND_TIME (random_rand() % (SEND_INTERVAL)) + +static struct simple_udp_connection unicast_connection; + +/*---------------------------------------------------------------------------*/ +PROCESS(unicast_receiver_process, "Unicast receiver example process"); +AUTOSTART_PROCESSES(&unicast_receiver_process); +/*---------------------------------------------------------------------------*/ +static void +receiver(struct simple_udp_connection *c, + const uip_ipaddr_t *sender_addr, + uint16_t sender_port, + const uip_ipaddr_t *receiver_addr, + uint16_t receiver_port, + const uint8_t *data, + uint16_t datalen) +{ + printf("Data received from "); + uip_debug_ipaddr_print(sender_addr); + printf(" on port %d from port %d with length %d: '%s'\n", + receiver_port, sender_port, datalen, data); +} +/*---------------------------------------------------------------------------*/ +static uip_ipaddr_t * +set_global_address(void) +{ + static uip_ipaddr_t ipaddr; + int i; + uint8_t state; + + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + + printf("IPv6 addresses: "); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && + (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { + uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); + printf("\n"); + } + } + + return &ipaddr; +} +/*---------------------------------------------------------------------------*/ +static void +create_rpl_dag(uip_ipaddr_t *ipaddr) +{ + struct uip_ds6_addr *root_if; + + root_if = uip_ds6_addr_lookup(ipaddr); + if(root_if != NULL) { + rpl_dag_t *dag; + uip_ipaddr_t prefix; + + rpl_set_root(RPL_DEFAULT_INSTANCE, ipaddr); + dag = rpl_get_any_dag(); + uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); + rpl_set_prefix(dag, &prefix, 64); + PRINTF("created a new RPL dag\n"); + } else { + PRINTF("failed to create a new RPL DAG\n"); + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(unicast_receiver_process, ev, data) +{ + uip_ipaddr_t *ipaddr; + + PROCESS_BEGIN(); + + ipaddr = set_global_address(); + + create_rpl_dag(ipaddr); + + simple_udp_register(&unicast_connection, UDP_PORT, + NULL, UDP_PORT, receiver); + + while(1) { + PROCESS_WAIT_EVENT(); + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/regression-tests/23-rpl-non-storing/code/sender-node.c b/regression-tests/23-rpl-non-storing/code/sender-node.c new file mode 100644 index 000000000..55dfdd15f --- /dev/null +++ b/regression-tests/23-rpl-non-storing/code/sender-node.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2012, Thingsquare, www.thingsquare.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 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. + */ + + +#include "contiki.h" +#include "lib/random.h" +#include "sys/ctimer.h" +#include "sys/etimer.h" +#include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" +#include "net/ip/uip-debug.h" + +#include "simple-udp.h" + +#include +#include + +#define UDP_PORT 1234 + +#define SEND_INTERVAL (60 * CLOCK_SECOND) +#define SEND_TIME (random_rand() % (SEND_INTERVAL)) + +static struct simple_udp_connection unicast_connection; + +/*---------------------------------------------------------------------------*/ +PROCESS(sender_node_process, "Sender node process"); +AUTOSTART_PROCESSES(&sender_node_process); +/*---------------------------------------------------------------------------*/ +static void +receiver(struct simple_udp_connection *c, + const uip_ipaddr_t *sender_addr, + uint16_t sender_port, + const uip_ipaddr_t *receiver_addr, + uint16_t receiver_port, + const uint8_t *data, + uint16_t datalen) +{ + printf("Sender received data on port %d from port %d with length %d\n", + receiver_port, sender_port, datalen); +} +/*---------------------------------------------------------------------------*/ +static void +set_global_address(void) +{ + uip_ipaddr_t ipaddr; + int i; + uint8_t state; + + uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); + + printf("IPv6 addresses: "); + for(i = 0; i < UIP_DS6_ADDR_NB; i++) { + state = uip_ds6_if.addr_list[i].state; + if(uip_ds6_if.addr_list[i].isused && + (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) { + uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); + printf("\n"); + } + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(sender_node_process, ev, data) +{ + static struct etimer periodic_timer; + static struct etimer send_timer; + uip_ipaddr_t addr; + + PROCESS_BEGIN(); + + set_global_address(); + + simple_udp_register(&unicast_connection, UDP_PORT, + NULL, UDP_PORT, receiver); + + etimer_set(&periodic_timer, SEND_INTERVAL); + while(1) { + + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&periodic_timer)); + etimer_reset(&periodic_timer); + etimer_set(&send_timer, SEND_TIME); + + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&send_timer)); + + uip_ip6addr(&addr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0x0201, 0x001, 0x001, 0x001); + + { + static unsigned int message_number; + char buf[20]; + + printf("Sending unicast to "); + uip_debug_ipaddr_print(&addr); + printf("\n"); + sprintf(buf, "Message %d", message_number); + message_number++; + simple_udp_sendto(&unicast_connection, buf, strlen(buf) + 1, &addr); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/regression-tests/24-compile-nrf52-ports/Makefile b/regression-tests/24-compile-nrf52-ports/Makefile new file mode 100644 index 000000000..bdf5b4a04 --- /dev/null +++ b/regression-tests/24-compile-nrf52-ports/Makefile @@ -0,0 +1,19 @@ +EXAMPLESDIR=../../examples +TOOLSDIR=../../tools + +# Note, that SERVER_IPV6_ADDR variable is set to ffff on purpose +# even though it's not a valid IPV6 address. This is due to limitation +# of the testing framework which splits compliation arguments using +# a colon. + +EXAMPLES = \ +hello-world/nrf52dk \ +nrf52dk/coap-demo/nrf52dk:coap-server \ +nrf52dk/coap-demo/nrf52dk:coap-client:SERVER_IPV6_ADDR=ffff \ +nrf52dk/mqtt-demo/nrf52dk \ +nrf52dk/blink-hello/nrf52dk \ +nrf52dk/timer-test/nrf52dk + +TOOLS= + +include ../Makefile.compile-test diff --git a/regression-tests/Makefile.simulation-test b/regression-tests/Makefile.simulation-test index 58818c328..9995eeea8 100644 --- a/regression-tests/Makefile.simulation-test +++ b/regression-tests/Makefile.simulation-test @@ -31,7 +31,7 @@ TESTLOGS=$(patsubst %.csc,%.testlog,$(TESTS)) LOGS=$(patsubst %.csc,%.log,$(TESTS)) FAILLOGS=$(patsubst %.csc,%.*.faillog,$(TESTS)) #Set random seeds to create reproduceable results. -RANDOMSEED=1 5 +RANDOMSEED=1 CONTIKI=../.. diff --git a/tools/6502/Makefile b/tools/6502/Makefile index e1e0925ef..d88a4790f 100644 --- a/tools/6502/Makefile +++ b/tools/6502/Makefile @@ -35,10 +35,6 @@ ifndef CONTIKI ${error CONTIKI not defined! You must specify where Contiki resides} endif -ifndef CC65_HOME - ${error CC65_HOME not defined! You must specify where cc65 resides} -endif - ifndef AC ${error AC not defined! You must specify where the AppleCommander jar resides} endif @@ -66,6 +62,8 @@ else ZIPCOMMENT := N/A endif +CC65 := $(shell cl65 --print-target-path) + define makes $1-makes: $(MAKE) -C ../../cpu/6502/ethconfig TARGET=$1 @@ -92,51 +90,51 @@ contiki-apple2.zip: contiki-apple2-1.dsk contiki-apple2-2.dsk contiki-apple2-3.d contiki-apple2-1.dsk: apple2enh-makes cp ../apple2enh/prodos.dsk $@ java -jar $(AC) -p $@ menu.system sys < ../apple2enh/menu.system - java -jar $(AC) -p $@ ethconfi.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ ethconfi.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ ethconfi bin < ../../cpu/6502/ethconfig/ethconfig.apple2enh - java -jar $(AC) -p $@ ipconfig.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ ipconfig.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ ipconfig bin < ../../cpu/6502/ipconfig/ipconfig.apple2enh - java -jar $(AC) -p $@ webbrows.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ webbrows.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ webbrows bin < ../../examples/webbrowser-80col/webbrowser.apple2enh - java -jar $(AC) -p $@ wget.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ wget.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ wget bin < ../../examples/wget/wget.apple2enh java -jar $(AC) -p $@ contiki.cfg bin 0 < ../apple2enh/default.cfg java -jar $(AC) -p $@ cs8900a.eth rel 0 < ../../cpu/6502/ethconfig/cs8900a.eth java -jar $(AC) -p $@ lan91c96.eth rel 0 < ../../cpu/6502/ethconfig/lan91c96.eth java -jar $(AC) -p $@ w5100.eth rel 0 < ../../cpu/6502/ethconfig/w5100.eth - java -jar $(AC) -p $@ contiki.mou rel 0 < $(CC65_HOME)/mou/a2e.stdmou.mou + java -jar $(AC) -p $@ contiki.mou rel 0 < $(CC65)/apple2enh/drv/mou/a2e.stdmou.mou contiki-apple2-2.dsk: apple2enh-makes cp ../apple2enh/prodos.dsk $@ java -jar $(AC) -p $@ menu.system sys < ../apple2enh/menu.system - java -jar $(AC) -p $@ ethconfi.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ ethconfi.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ ethconfi bin < ../../cpu/6502/ethconfig/ethconfig.apple2enh - java -jar $(AC) -p $@ ipconfig.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ ipconfig.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ ipconfig bin < ../../cpu/6502/ipconfig/ipconfig.apple2enh - java -jar $(AC) -p $@ irc.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ irc.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ irc bin < ../../examples/irc-80col/irc-client.apple2enh java -jar $(AC) -p $@ contiki.cfg bin 0 < ../apple2enh/default.cfg java -jar $(AC) -p $@ cs8900a.eth rel 0 < ../../cpu/6502/ethconfig/cs8900a.eth java -jar $(AC) -p $@ lan91c96.eth rel 0 < ../../cpu/6502/ethconfig/lan91c96.eth java -jar $(AC) -p $@ w5100.eth rel 0 < ../../cpu/6502/ethconfig/w5100.eth - java -jar $(AC) -p $@ contiki.mou rel 0 < $(CC65_HOME)/mou/a2e.stdmou.mou + java -jar $(AC) -p $@ contiki.mou rel 0 < $(CC65)/apple2enh/drv/mou/a2e.stdmou.mou contiki-apple2-3.dsk: apple2enh-makes cp ../apple2enh/prodos.dsk $@ java -jar $(AC) -p $@ menu.system sys < ../apple2enh/menu.system - java -jar $(AC) -p $@ ethconfi.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ ethconfi.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ ethconfi bin < ../../cpu/6502/ethconfig/ethconfig.apple2enh - java -jar $(AC) -p $@ ipconfig.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ ipconfig.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ ipconfig bin < ../../cpu/6502/ipconfig/ipconfig.apple2enh - java -jar $(AC) -p $@ webserv.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ webserv.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ webserv bin < ../../examples/webserver/webserver-example.apple2enh - java -jar $(AC) -p $@ telnetd.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ telnetd.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ telnetd bin < ../../examples/telnet-server/telnet-server.apple2enh java -jar $(AC) -p $@ contiki.cfg bin 0 < ../apple2enh/default.cfg java -jar $(AC) -p $@ cs8900a.eth rel 0 < ../../cpu/6502/ethconfig/cs8900a.eth java -jar $(AC) -p $@ lan91c96.eth rel 0 < ../../cpu/6502/ethconfig/lan91c96.eth java -jar $(AC) -p $@ w5100.eth rel 0 < ../../cpu/6502/ethconfig/w5100.eth - java -jar $(AC) -p $@ contiki.mou rel 0 < $(CC65_HOME)/mou/a2e.stdmou.mou + java -jar $(AC) -p $@ contiki.mou rel 0 < $(CC65)/apple2enh/drv/mou/a2e.stdmou.mou java -jar $(AC) -p $@ index.htm bin 0 < ../../examples/webserver/httpd-cfs/index.htm java -jar $(AC) -p $@ backgrnd.gif bin 0 < ../../examples/webserver/httpd-cfs/backgrnd.gif java -jar $(AC) -p $@ contiki.gif bin 0 < ../../examples/webserver/httpd-cfs/contiki.gif @@ -145,25 +143,25 @@ contiki-apple2-3.dsk: apple2enh-makes contiki-apple2.po: apple2enh-makes cp ../apple2enh/prodos.po $@ java -jar $(AC) -p $@ menu.system sys < ../apple2enh/menu.system - java -jar $(AC) -p $@ ethconfi.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ ethconfi.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ ethconfi bin < ../../cpu/6502/ethconfig/ethconfig.apple2enh - java -jar $(AC) -p $@ ipconfig.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ ipconfig.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ ipconfig bin < ../../cpu/6502/ipconfig/ipconfig.apple2enh - java -jar $(AC) -p $@ webbrows.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ webbrows.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ webbrows bin < ../../examples/webbrowser-80col/webbrowser.apple2enh - java -jar $(AC) -p $@ wget.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ wget.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ wget bin < ../../examples/wget/wget.apple2enh - java -jar $(AC) -p $@ irc.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ irc.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ irc bin < ../../examples/irc-80col/irc-client.apple2enh - java -jar $(AC) -p $@ webserv.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ webserv.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ webserv bin < ../../examples/webserver/webserver-example.apple2enh - java -jar $(AC) -p $@ telnetd.system sys < $(CC65_HOME)/targetutil/loader.system + java -jar $(AC) -p $@ telnetd.system sys < $(CC65)/apple2enh/util/loader.system java -jar $(AC) -cc65 $@ telnetd bin < ../../examples/telnet-server/telnet-server.apple2enh java -jar $(AC) -p $@ contiki.cfg bin 0 < ../apple2enh/default.cfg java -jar $(AC) -p $@ cs8900a.eth rel 0 < ../../cpu/6502/ethconfig/cs8900a.eth java -jar $(AC) -p $@ lan91c96.eth rel 0 < ../../cpu/6502/ethconfig/lan91c96.eth java -jar $(AC) -p $@ w5100.eth rel 0 < ../../cpu/6502/ethconfig/w5100.eth - java -jar $(AC) -p $@ contiki.mou rel 0 < $(CC65_HOME)/mou/a2e.stdmou.mou + java -jar $(AC) -p $@ contiki.mou rel 0 < $(CC65)/apple2enh/drv/mou/a2e.stdmou.mou java -jar $(AC) -p $@ index.htm bin 0 < ../../examples/webserver/httpd-cfs/index.htm java -jar $(AC) -p $@ backgrnd.gif bin 0 < ../../examples/webserver/httpd-cfs/backgrnd.gif java -jar $(AC) -p $@ contiki.gif bin 0 < ../../examples/webserver/httpd-cfs/contiki.gif @@ -184,11 +182,11 @@ contiki-atari-1.atr: atarixl-makes cp ../../examples/wget/wget.atarixl atr/wget.com cp ../atarixl/default.cfg atr/contiki.cfg cp ../../cpu/6502/ethconfig/cs8900a.eth atr/cs8900a.eth - cp $(CC65_HOME)/mou/atrxst.mou atr/contiki.mou - cp $(CC65_HOME)/mou/atrxami.mou atr/ami.mou - cp $(CC65_HOME)/mou/atrxjoy.mou atr/joy.mou - cp $(CC65_HOME)/mou/atrxtrk.mou atr/trk.mou - cp $(CC65_HOME)/mou/atrxtt.mou atr/tt.mou + cp $(CC65)/atarixl/drv/mou/atrxst.mou atr/contiki.mou + cp $(CC65)/atarixl/drv/mou/atrxami.mou atr/ami.mou + cp $(CC65)/atarixl/drv/mou/atrxjoy.mou atr/joy.mou + cp $(CC65)/atarixl/drv/mou/atrxtrk.mou atr/trk.mou + cp $(CC65)/atarixl/drv/mou/atrxtt.mou atr/tt.mou $(DIR2ATR) -b Dos25 1040 $@ atr rm -r atr @@ -200,11 +198,11 @@ contiki-atari-2.atr: atarixl-makes cp ../../examples/irc/irc-client.atarixl atr/irc.com cp ../atarixl/default.cfg atr/contiki.cfg cp ../../cpu/6502/ethconfig/cs8900a.eth atr/cs8900a.eth - cp $(CC65_HOME)/mou/atrxst.mou atr/contiki.mou - cp $(CC65_HOME)/mou/atrxami.mou atr/ami.mou - cp $(CC65_HOME)/mou/atrxjoy.mou atr/joy.mou - cp $(CC65_HOME)/mou/atrxtrk.mou atr/trk.mou - cp $(CC65_HOME)/mou/atrxtt.mou atr/tt.mou + cp $(CC65)/atarixl/drv/mou/atrxst.mou atr/contiki.mou + cp $(CC65)/atarixl/drv/mou/atrxami.mou atr/ami.mou + cp $(CC65)/atarixl/drv/mou/atrxjoy.mou atr/joy.mou + cp $(CC65)/atarixl/drv/mou/atrxtrk.mou atr/trk.mou + cp $(CC65)/atarixl/drv/mou/atrxtt.mou atr/tt.mou $(DIR2ATR) -b Dos25 1040 $@ atr rm -r atr @@ -217,11 +215,11 @@ contiki-atari-3.atr: atarixl-makes cp ../../examples/telnet-server/telnet-server.atarixl atr/telnetd.com cp ../atarixl/default.cfg atr/contiki.cfg cp ../../cpu/6502/ethconfig/cs8900a.eth atr/cs8900a.eth - cp $(CC65_HOME)/mou/atrxst.mou atr/contiki.mou - cp $(CC65_HOME)/mou/atrxami.mou atr/ami.mou - cp $(CC65_HOME)/mou/atrxjoy.mou atr/joy.mou - cp $(CC65_HOME)/mou/atrxtrk.mou atr/trk.mou - cp $(CC65_HOME)/mou/atrxtt.mou atr/tt.mou + cp $(CC65)/atarixl/drv/mou/atrxst.mou atr/contiki.mou + cp $(CC65)/atarixl/drv/mou/atrxami.mou atr/ami.mou + cp $(CC65)/atarixl/drv/mou/atrxjoy.mou atr/joy.mou + cp $(CC65)/atarixl/drv/mou/atrxtrk.mou atr/trk.mou + cp $(CC65)/atarixl/drv/mou/atrxtt.mou atr/tt.mou cp ../../examples/webserver/httpd-cfs/index.htm atr/index.htm cp ../../examples/webserver/httpd-cfs/backgrnd.gif atr/backgrnd.gif cp ../../examples/webserver/httpd-cfs/contiki.gif atr/contiki.gif @@ -241,11 +239,11 @@ contiki-atari.atr: atarixl-makes cp ../../examples/telnet-server/telnet-server.atarixl atr/telnetd.com cp ../atarixl/default.cfg atr/contiki.cfg cp ../../cpu/6502/ethconfig/cs8900a.eth atr/cs8900a.eth - cp $(CC65_HOME)/mou/atrxst.mou atr/contiki.mou - cp $(CC65_HOME)/mou/atrxami.mou atr/ami.mou - cp $(CC65_HOME)/mou/atrxjoy.mou atr/joy.mou - cp $(CC65_HOME)/mou/atrxtrk.mou atr/trk.mou - cp $(CC65_HOME)/mou/atrxtt.mou atr/tt.mou + cp $(CC65)/atarixl/drv/mou/atrxst.mou atr/contiki.mou + cp $(CC65)/atarixl/drv/mou/atrxami.mou atr/ami.mou + cp $(CC65)/atarixl/drv/mou/atrxjoy.mou atr/joy.mou + cp $(CC65)/atarixl/drv/mou/atrxtrk.mou atr/trk.mou + cp $(CC65)/atarixl/drv/mou/atrxtt.mou atr/tt.mou cp ../../examples/webserver/httpd-cfs/index.htm atr/index.htm cp ../../examples/webserver/httpd-cfs/backgrnd.gif atr/backgrnd.gif cp ../../examples/webserver/httpd-cfs/contiki.gif atr/contiki.gif @@ -261,96 +259,96 @@ contiki-c64.zip: contiki-c64-1.d64 contiki-c64-2.d64 contiki-c64-3.d64 contiki-c contiki-c64-1.d64: c64-makes $(C1541) -format contiki-1,00 d64 $@ - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c64 ethconfig,p - $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c64 ipconfig,p - $(C1541) -attach $@ -write ../../examples/webbrowser/webbrowser.c64 webbrowser,p - $(C1541) -attach $@ -write ../../examples/webbrowser-80col/webbrowser.c64 webbrowser80,p - $(C1541) -attach $@ -write ../../examples/wget/wget.c64 wget,p - $(C1541) -attach $@ -write ../c64/default.cfg contiki.cfg,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-1351.mou contiki.mou,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-inkwell.mou inkwell.mou,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-joy.mou joy.mou,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-pot.mou pot.mou,s + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c64 ethconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c64 ipconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webbrowser/webbrowser.c64 webbrowser,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webbrowser-80col/webbrowser.c64 webbrowser80,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/wget/wget.c64 wget,p >$(NULLDEV) + $(C1541) -attach $@ -write ../c64/default.cfg contiki.cfg,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-1351.mou contiki.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-inkwell.mou inkwell.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-joy.mou joy.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-pot.mou pot.mou,s >$(NULLDEV) contiki-c64-2.d64: c64-makes $(C1541) -format contiki-2,00 d64 $@ - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c64 ethconfig,p - $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c64 ipconfig,p - $(C1541) -attach $@ -write ../../examples/irc/irc-client.c64 irc,p - $(C1541) -attach $@ -write ../../examples/irc-80col/irc-client.c64 irc80,p - $(C1541) -attach $@ -write ../c64/default.cfg contiki.cfg,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-1351.mou contiki.mou,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-inkwell.mou inkwell.mou,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-joy.mou joy.mou,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-pot.mou pot.mou,s + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c64 ethconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c64 ipconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/irc/irc-client.c64 irc,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/irc-80col/irc-client.c64 irc80,p >$(NULLDEV) + $(C1541) -attach $@ -write ../c64/default.cfg contiki.cfg,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-1351.mou contiki.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-inkwell.mou inkwell.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-joy.mou joy.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-pot.mou pot.mou,s >$(NULLDEV) contiki-c64-3.d64: c64-makes $(C1541) -format contiki-3,00 d64 $@ - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c64 ethconfig,p - $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c64 ipconfig,p - $(C1541) -attach $@ -write ../../examples/webserver/webserver-example.c64 webserver,p - $(C1541) -attach $@ -write ../../examples/telnet-server/telnet-server.c64 telnetd,p - $(C1541) -attach $@ -write ../c64/default.cfg contiki.cfg,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-1351.mou contiki.mou,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-inkwell.mou inkwell.mou,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-joy.mou joy.mou,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-pot.mou pot.mou,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/index.htm index.htm,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/backgrnd.gif backgrnd.gif,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/contiki.gif contiki.gif,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/notfound.htm notfound.htm,s + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c64 ethconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c64 ipconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/webserver-example.c64 webserver,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/telnet-server/telnet-server.c64 telnetd,p >$(NULLDEV) + $(C1541) -attach $@ -write ../c64/default.cfg contiki.cfg,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-1351.mou contiki.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-inkwell.mou inkwell.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-joy.mou joy.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-pot.mou pot.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/index.htm index.htm,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/backgrnd.gif backgrnd.gif,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/contiki.gif contiki.gif,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/notfound.htm notfound.htm,s >$(NULLDEV) contiki-c64.d71: c64-makes $(C1541) -format contiki,00 d71 $@ - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c64 ethconfig,p - $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c64 ipconfig,p - $(C1541) -attach $@ -write ../../examples/webbrowser/webbrowser.c64 webbrowser,p - $(C1541) -attach $@ -write ../../examples/webbrowser-80col/webbrowser.c64 webbrowser80,p - $(C1541) -attach $@ -write ../../examples/wget/wget.c64 wget,p - $(C1541) -attach $@ -write ../../examples/irc/irc-client.c64 irc,p - $(C1541) -attach $@ -write ../../examples/irc-80col/irc-client.c64 irc80,p - $(C1541) -attach $@ -write ../../examples/webserver/webserver-example.c64 webserver,p - $(C1541) -attach $@ -write ../../examples/telnet-server/telnet-server.c64 telnetd,p - $(C1541) -attach $@ -write ../c64/default.cfg contiki.cfg,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-1351.mou contiki.mou,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-inkwell.mou inkwell.mou,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-joy.mou joy.mou,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-pot.mou pot.mou,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/index.htm index.htm,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/backgrnd.gif backgrnd.gif,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/contiki.gif contiki.gif,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/notfound.htm notfound.htm,s + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c64 ethconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c64 ipconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webbrowser/webbrowser.c64 webbrowser,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webbrowser-80col/webbrowser.c64 webbrowser80,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/wget/wget.c64 wget,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/irc/irc-client.c64 irc,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/irc-80col/irc-client.c64 irc80,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/webserver-example.c64 webserver,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/telnet-server/telnet-server.c64 telnetd,p >$(NULLDEV) + $(C1541) -attach $@ -write ../c64/default.cfg contiki.cfg,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-1351.mou contiki.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-inkwell.mou inkwell.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-joy.mou joy.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-pot.mou pot.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/index.htm index.htm,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/backgrnd.gif backgrnd.gif,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/contiki.gif contiki.gif,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/notfound.htm notfound.htm,s >$(NULLDEV) contiki-c64.d81: c64-makes $(C1541) -format contiki,00 d81 $@ - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c64 ethconfig,p - $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c64 ipconfig,p - $(C1541) -attach $@ -write ../../examples/webbrowser/webbrowser.c64 webbrowser,p - $(C1541) -attach $@ -write ../../examples/webbrowser-80col/webbrowser.c64 webbrowser80,p - $(C1541) -attach $@ -write ../../examples/wget/wget.c64 wget,p - $(C1541) -attach $@ -write ../../examples/irc/irc-client.c64 irc,p - $(C1541) -attach $@ -write ../../examples/irc-80col/irc-client.c64 irc80,p - $(C1541) -attach $@ -write ../../examples/webserver/webserver-example.c64 webserver,p - $(C1541) -attach $@ -write ../../examples/telnet-server/telnet-server.c64 telnetd,p - $(C1541) -attach $@ -write ../c64/default.cfg contiki.cfg,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-1351.mou contiki.mou,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-inkwell.mou inkwell.mou,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-joy.mou joy.mou,s - $(C1541) -attach $@ -write $(CC65_HOME)/mou/c64-pot.mou pot.mou,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/index.htm index.htm,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/backgrnd.gif backgrnd.gif,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/contiki.gif contiki.gif,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/notfound.htm notfound.htm,s + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c64 ethconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c64 ipconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webbrowser/webbrowser.c64 webbrowser,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webbrowser-80col/webbrowser.c64 webbrowser80,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/wget/wget.c64 wget,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/irc/irc-client.c64 irc,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/irc-80col/irc-client.c64 irc80,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/webserver-example.c64 webserver,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/telnet-server/telnet-server.c64 telnetd,p >$(NULLDEV) + $(C1541) -attach $@ -write ../c64/default.cfg contiki.cfg,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-1351.mou contiki.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-inkwell.mou inkwell.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-joy.mou joy.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write $(CC65)/c64/drv/mou/c64-pot.mou pot.mou,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/index.htm index.htm,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/backgrnd.gif backgrnd.gif,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/contiki.gif contiki.gif,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/notfound.htm notfound.htm,s >$(NULLDEV) $(eval $(call makes,c128)) @@ -360,59 +358,59 @@ contiki-c128.zip: contiki-c128-1.d64 contiki-c128-2.d64 contiki-c128.d71 contiki contiki-c128-1.d64: c128-makes $(C1541) -format contiki-1,00 d64 $@ - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c128 ethconfig,p - $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c128 ipconfig,p - $(C1541) -attach $@ -write ../../examples/webbrowser-80col/webbrowser.c128 webbrowser,p - $(C1541) -attach $@ -write ../../examples/wget/wget.c128 wget,p - $(C1541) -attach $@ -write ../../examples/irc-80col/irc-client.c128 irc,p - $(C1541) -attach $@ -write ../c128/default.cfg contiki.cfg,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c128 ethconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c128 ipconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webbrowser-80col/webbrowser.c128 webbrowser,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/wget/wget.c128 wget,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/irc-80col/irc-client.c128 irc,p >$(NULLDEV) + $(C1541) -attach $@ -write ../c128/default.cfg contiki.cfg,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s >$(NULLDEV) contiki-c128-2.d64: c128-makes $(C1541) -format contiki-3,00 d64 $@ - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c128 ethconfig,p - $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c128 ipconfig,p - $(C1541) -attach $@ -write ../../examples/webserver/webserver-example.c128 webserver,p - $(C1541) -attach $@ -write ../../examples/telnet-server/telnet-server.c128 telnetd,p - $(C1541) -attach $@ -write ../c128/default.cfg contiki.cfg,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/index.htm index.htm,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/backgrnd.gif backgrnd.gif,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/contiki.gif contiki.gif,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/notfound.htm notfound.htm,s + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c128 ethconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c128 ipconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/webserver-example.c128 webserver,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/telnet-server/telnet-server.c128 telnetd,p >$(NULLDEV) + $(C1541) -attach $@ -write ../c128/default.cfg contiki.cfg,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/index.htm index.htm,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/backgrnd.gif backgrnd.gif,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/contiki.gif contiki.gif,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/notfound.htm notfound.htm,s >$(NULLDEV) contiki-c128.d71: c128-makes $(C1541) -format contiki,00 d71 $@ - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c128 ethconfig,p - $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c128 ipconfig,p - $(C1541) -attach $@ -write ../../examples/webbrowser-80col/webbrowser.c128 webbrowser,p - $(C1541) -attach $@ -write ../../examples/wget/wget.c128 wget,p - $(C1541) -attach $@ -write ../../examples/irc-80col/irc-client.c128 irc,p - $(C1541) -attach $@ -write ../../examples/webserver/webserver-example.c128 webserver,p - $(C1541) -attach $@ -write ../../examples/telnet-server/telnet-server.c128 telnetd,p - $(C1541) -attach $@ -write ../c128/default.cfg contiki.cfg,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/index.htm index.htm,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/backgrnd.gif backgrnd.gif,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/contiki.gif contiki.gif,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/notfound.htm notfound.htm,s + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c128 ethconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c128 ipconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webbrowser-80col/webbrowser.c128 webbrowser,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/wget/wget.c128 wget,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/irc-80col/irc-client.c128 irc,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/webserver-example.c128 webserver,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/telnet-server/telnet-server.c128 telnetd,p >$(NULLDEV) + $(C1541) -attach $@ -write ../c128/default.cfg contiki.cfg,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/index.htm index.htm,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/backgrnd.gif backgrnd.gif,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/contiki.gif contiki.gif,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/notfound.htm notfound.htm,s >$(NULLDEV) contiki-c128.d81: c128-makes $(C1541) -format contiki,00 d81 $@ - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c128 ethconfig,p - $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c128 ipconfig,p - $(C1541) -attach $@ -write ../../examples/webbrowser-80col/webbrowser.c128 webbrowser,p - $(C1541) -attach $@ -write ../../examples/wget/wget.c128 wget,p - $(C1541) -attach $@ -write ../../examples/irc-80col/irc-client.c128 irc,p - $(C1541) -attach $@ -write ../../examples/webserver/webserver-example.c128 webserver,p - $(C1541) -attach $@ -write ../../examples/telnet-server/telnet-server.c128 telnetd,p - $(C1541) -attach $@ -write ../c128/default.cfg contiki.cfg,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s - $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/index.htm index.htm,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/backgrnd.gif backgrnd.gif,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/contiki.gif contiki.gif,s - $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/notfound.htm notfound.htm,s + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/ethconfig.c128 ethconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ipconfig/ipconfig.c128 ipconfig,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webbrowser-80col/webbrowser.c128 webbrowser,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/wget/wget.c128 wget,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/irc-80col/irc-client.c128 irc,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/webserver-example.c128 webserver,p >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/telnet-server/telnet-server.c128 telnetd,p >$(NULLDEV) + $(C1541) -attach $@ -write ../c128/default.cfg contiki.cfg,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/cs8900a.eth cs8900a.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../cpu/6502/ethconfig/lan91c96.eth lan91c96.eth,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/index.htm index.htm,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/backgrnd.gif backgrnd.gif,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/contiki.gif contiki.gif,s >$(NULLDEV) + $(C1541) -attach $@ -write ../../examples/webserver/httpd-cfs/notfound.htm notfound.htm,s >$(NULLDEV) diff --git a/tools/cc2538-bsl b/tools/cc2538-bsl index 6185d8b16..c6100a779 160000 --- a/tools/cc2538-bsl +++ b/tools/cc2538-bsl @@ -1 +1 @@ -Subproject commit 6185d8b16f10047053fd57000a552340273d7d85 +Subproject commit c6100a7794c7b530923145c03e37412013a4551e diff --git a/tools/collect-view/src/org/contikios/contiki/collect/MoteFinder.java b/tools/collect-view/src/org/contikios/contiki/collect/MoteFinder.java index 9afcf028b..2c3c86d5b 100644 --- a/tools/collect-view/src/org/contikios/contiki/collect/MoteFinder.java +++ b/tools/collect-view/src/org/contikios/contiki/collect/MoteFinder.java @@ -54,9 +54,11 @@ public class MoteFinder { public static final String MOTELIST_WINDOWS = "./tools/motelist-windows.exe"; public static final String MOTELIST_LINUX = "./tools/motelist-linux"; + public static final String MOTELIST_MACOS = "./tools/motelist-macos"; private final Pattern motePattern; private final boolean isWindows; + private final boolean isMacos; private Process moteListProcess; // private boolean hasVerifiedProcess; private ArrayList comList = new ArrayList(); @@ -65,7 +67,8 @@ public class MoteFinder { public MoteFinder() { String osName = System.getProperty("os.name", "").toLowerCase(); isWindows = osName.startsWith("win"); - motePattern = Pattern.compile("\\s(COM|/dev/[a-zA-Z]+)(\\d+)\\s"); + isMacos = osName.startsWith("mac"); + motePattern = Pattern.compile("\\s(COM|/dev/[a-zA-Z]+|/dev/tty.usbserial-)(\\d+|[A-Z0-9]+)\\s"); } public String[] getMotes() throws IOException { @@ -87,6 +90,8 @@ public class MoteFinder { String fullCommand; if (isWindows) { fullCommand = MOTELIST_WINDOWS; + } else if (isMacos) { + fullCommand = MOTELIST_MACOS; } else { fullCommand = MOTELIST_LINUX; } diff --git a/tools/collect-view/src/org/contikios/contiki/collect/SerialDumpConnection.java b/tools/collect-view/src/org/contikios/contiki/collect/SerialDumpConnection.java index 9669b89f4..c624ea64a 100644 --- a/tools/collect-view/src/org/contikios/contiki/collect/SerialDumpConnection.java +++ b/tools/collect-view/src/org/contikios/contiki/collect/SerialDumpConnection.java @@ -46,6 +46,7 @@ public class SerialDumpConnection extends CommandConnection { public static final String SERIALDUMP_WINDOWS = "./tools/serialdump-windows.exe"; public static final String SERIALDUMP_LINUX = "./tools/serialdump-linux"; + public static final String SERIALDUMP_MACOS = "./tools/serialdump-macos"; public SerialDumpConnection(SerialConnectionListener listener) { super(listener); @@ -72,6 +73,8 @@ public class SerialDumpConnection extends CommandConnection { String fullCommand; if (osName.startsWith("win")) { fullCommand = SERIALDUMP_WINDOWS + " " + "-b115200" + " " + getMappedComPortForWindows(comPort); + } else if (osName.startsWith("mac")) { + fullCommand = SERIALDUMP_MACOS + " " + "-b115200" + " " + comPort; } else { fullCommand = SERIALDUMP_LINUX + " " + "-b115200" + " " + comPort; } diff --git a/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMoteType.java b/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMoteType.java index c1a33b625..9499aafe9 100644 --- a/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMoteType.java +++ b/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMoteType.java @@ -63,7 +63,9 @@ import org.contikios.cooja.avrmote.interfaces.MicaZLED; import org.contikios.cooja.avrmote.interfaces.MicaZRadio; import org.contikios.cooja.dialogs.CompileContiki; import org.contikios.cooja.dialogs.MessageList; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; +import org.contikios.cooja.dialogs.MessageListText; +import org.contikios.cooja.dialogs.MessageListUI; +import org.contikios.cooja.dialogs.MessageContainer; import org.contikios.cooja.interfaces.Mote2MoteRelations; import org.contikios.cooja.interfaces.MoteAttributes; import org.contikios.cooja.interfaces.Position; @@ -364,7 +366,7 @@ public class MicaZMoteType implements MoteType { throw new MoteTypeCreationException("No identifier"); } - final MessageList compilationOutput = new MessageList(); + final MessageList compilationOutput = visAvailable ? new MessageListUI() : new MessageListText(); if (getCompileCommands() != null) { /* Handle multiple compilation commands one by one */ diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/AbstractMspMoteType.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/AbstractMspMoteType.java index ec7feffd3..d03c0dfa1 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/AbstractMspMoteType.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/AbstractMspMoteType.java @@ -45,7 +45,6 @@ import org.apache.log4j.Logger; import org.contikios.cooja.*; import org.contikios.cooja.dialogs.*; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; /** * @@ -119,7 +118,7 @@ public abstract class AbstractMspMoteType extends MspMoteType { throw new MoteTypeCreationException("No identifier"); } - final MessageList compilationOutput = new MessageList(); + final MessageList compilationOutput = visAvailable ? new MessageListUI() : new MessageListText(); if (getCompileCommands() != null) { /* Handle multiple compilation commands one by one */ diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/CC430MoteType.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/CC430MoteType.java index 8be39971f..3a5144197 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/CC430MoteType.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/CC430MoteType.java @@ -50,8 +50,10 @@ import org.contikios.cooja.MoteInterface; import org.contikios.cooja.MoteType; import org.contikios.cooja.Simulation; import org.contikios.cooja.dialogs.CompileContiki; +import org.contikios.cooja.dialogs.MessageContainer; import org.contikios.cooja.dialogs.MessageList; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; +import org.contikios.cooja.dialogs.MessageListText; +import org.contikios.cooja.dialogs.MessageListUI; import org.contikios.cooja.interfaces.IPAddress; import org.contikios.cooja.interfaces.Mote2MoteRelations; import org.contikios.cooja.interfaces.MoteAttributes; @@ -113,7 +115,7 @@ public class CC430MoteType extends MspMoteType { throw new MoteTypeCreationException("No identifier"); } - final MessageList compilationOutput = new MessageList(); + final MessageList compilationOutput = visAvailable ? new MessageListUI() : new MessageListText(); if (getCompileCommands() != null) { /* Handle multiple compilation commands one by one */ diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/ESBMoteType.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/ESBMoteType.java index 41bf80384..13ad2025a 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/ESBMoteType.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/ESBMoteType.java @@ -51,7 +51,9 @@ import org.contikios.cooja.MoteType; import org.contikios.cooja.Simulation; import org.contikios.cooja.dialogs.CompileContiki; import org.contikios.cooja.dialogs.MessageList; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; +import org.contikios.cooja.dialogs.MessageListText; +import org.contikios.cooja.dialogs.MessageListUI; +import org.contikios.cooja.dialogs.MessageContainer; import org.contikios.cooja.interfaces.IPAddress; import org.contikios.cooja.interfaces.Mote2MoteRelations; import org.contikios.cooja.interfaces.MoteAttributes; @@ -149,7 +151,7 @@ public class ESBMoteType extends MspMoteType { throw new MoteTypeCreationException("No identifier"); } - final MessageList compilationOutput = new MessageList(); + final MessageList compilationOutput = visAvailable ? new MessageListUI() : new MessageListText(); if (getCompileCommands() != null) { /* Handle multiple compilation commands one by one */ diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Eth1120MoteType.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Eth1120MoteType.java index 84483d047..c51c29384 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Eth1120MoteType.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Eth1120MoteType.java @@ -11,7 +11,9 @@ import org.contikios.cooja.MoteType; import org.contikios.cooja.Simulation; import org.contikios.cooja.dialogs.CompileContiki; import org.contikios.cooja.dialogs.MessageList; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; +import org.contikios.cooja.dialogs.MessageListText; +import org.contikios.cooja.dialogs.MessageListUI; +import org.contikios.cooja.dialogs.MessageContainer; import org.contikios.cooja.interfaces.IPAddress; import org.contikios.cooja.interfaces.Mote2MoteRelations; import org.contikios.cooja.interfaces.MoteAttributes; @@ -71,7 +73,7 @@ public class Eth1120MoteType extends Exp5438MoteType { throw new MoteTypeCreationException("No identifier"); } - final MessageList compilationOutput = new MessageList(); + final MessageList compilationOutput = visAvailable ? new MessageListUI() : new MessageListText(); if (getCompileCommands() != null) { /* Handle multiple compilation commands one by one */ diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp1101MoteType.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp1101MoteType.java index b46f1c1f0..b36fb30e9 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp1101MoteType.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp1101MoteType.java @@ -11,7 +11,9 @@ import org.contikios.cooja.MoteType; import org.contikios.cooja.Simulation; import org.contikios.cooja.dialogs.CompileContiki; import org.contikios.cooja.dialogs.MessageList; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; +import org.contikios.cooja.dialogs.MessageListText; +import org.contikios.cooja.dialogs.MessageListUI; +import org.contikios.cooja.dialogs.MessageContainer; import org.contikios.cooja.interfaces.IPAddress; import org.contikios.cooja.interfaces.Mote2MoteRelations; import org.contikios.cooja.interfaces.MoteAttributes; @@ -71,7 +73,7 @@ public class Exp1101MoteType extends Exp5438MoteType { throw new MoteTypeCreationException("No identifier"); } - final MessageList compilationOutput = new MessageList(); + final MessageList compilationOutput = visAvailable ? new MessageListUI() : new MessageListText(); if (getCompileCommands() != null) { /* Handle multiple compilation commands one by one */ diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp1120MoteType.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp1120MoteType.java index d745097df..46ad50713 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp1120MoteType.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp1120MoteType.java @@ -11,7 +11,9 @@ import org.contikios.cooja.MoteType; import org.contikios.cooja.Simulation; import org.contikios.cooja.dialogs.CompileContiki; import org.contikios.cooja.dialogs.MessageList; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; +import org.contikios.cooja.dialogs.MessageListText; +import org.contikios.cooja.dialogs.MessageListUI; +import org.contikios.cooja.dialogs.MessageContainer; import org.contikios.cooja.interfaces.IPAddress; import org.contikios.cooja.interfaces.Mote2MoteRelations; import org.contikios.cooja.interfaces.MoteAttributes; @@ -72,7 +74,7 @@ public class Exp1120MoteType extends Exp5438MoteType { throw new MoteTypeCreationException("No identifier"); } - final MessageList compilationOutput = new MessageList(); + final MessageList compilationOutput = visAvailable ? new MessageListUI() : new MessageListText(); if (getCompileCommands() != null) { /* Handle multiple compilation commands one by one */ diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp2420MoteType.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp2420MoteType.java index 8e24ef145..8a63bf527 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp2420MoteType.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp2420MoteType.java @@ -11,7 +11,9 @@ import org.contikios.cooja.MoteType; import org.contikios.cooja.Simulation; import org.contikios.cooja.dialogs.CompileContiki; import org.contikios.cooja.dialogs.MessageList; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; +import org.contikios.cooja.dialogs.MessageListText; +import org.contikios.cooja.dialogs.MessageListUI; +import org.contikios.cooja.dialogs.MessageContainer; import org.contikios.cooja.interfaces.IPAddress; import org.contikios.cooja.interfaces.Mote2MoteRelations; import org.contikios.cooja.interfaces.MoteAttributes; @@ -72,7 +74,7 @@ public class Exp2420MoteType extends Exp5438MoteType { throw new MoteTypeCreationException("No identifier"); } - final MessageList compilationOutput = new MessageList(); + final MessageList compilationOutput = visAvailable ? new MessageListUI() : new MessageListText(); if (getCompileCommands() != null) { /* Handle multiple compilation commands one by one */ diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp5438MoteType.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp5438MoteType.java index f9fc4d813..c5b9b8436 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp5438MoteType.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Exp5438MoteType.java @@ -48,7 +48,9 @@ import org.contikios.cooja.MoteType; import org.contikios.cooja.Simulation; import org.contikios.cooja.dialogs.CompileContiki; import org.contikios.cooja.dialogs.MessageList; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; +import org.contikios.cooja.dialogs.MessageListText; +import org.contikios.cooja.dialogs.MessageListUI; +import org.contikios.cooja.dialogs.MessageContainer; import org.contikios.cooja.interfaces.IPAddress; import org.contikios.cooja.interfaces.Mote2MoteRelations; import org.contikios.cooja.interfaces.MoteAttributes; @@ -113,7 +115,7 @@ public class Exp5438MoteType extends MspMoteType { throw new MoteTypeCreationException("No identifier"); } - final MessageList compilationOutput = new MessageList(); + final MessageList compilationOutput = visAvailable ? new MessageListUI() : new MessageListText(); if (getCompileCommands() != null) { /* Handle multiple compilation commands one by one */ diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/SkyMoteType.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/SkyMoteType.java index 793418969..3ab5854b3 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/SkyMoteType.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/SkyMoteType.java @@ -51,7 +51,9 @@ import org.contikios.cooja.MoteType; import org.contikios.cooja.Simulation; import org.contikios.cooja.dialogs.CompileContiki; import org.contikios.cooja.dialogs.MessageList; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; +import org.contikios.cooja.dialogs.MessageListText; +import org.contikios.cooja.dialogs.MessageListUI; +import org.contikios.cooja.dialogs.MessageContainer; import org.contikios.cooja.interfaces.IPAddress; import org.contikios.cooja.interfaces.Mote2MoteRelations; import org.contikios.cooja.interfaces.MoteAttributes; @@ -135,7 +137,7 @@ public class SkyMoteType extends MspMoteType { throw new MoteTypeCreationException("No identifier"); } - final MessageList compilationOutput = new MessageList(); + final MessageList compilationOutput = visAvailable ? new MessageListUI() : new MessageListText(); if (getCompileCommands() != null) { /* Handle multiple compilation commands one by one */ diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Trxeb1120MoteType.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Trxeb1120MoteType.java index e69daf55f..eac27e122 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Trxeb1120MoteType.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Trxeb1120MoteType.java @@ -11,7 +11,9 @@ import org.contikios.cooja.MoteType; import org.contikios.cooja.Simulation; import org.contikios.cooja.dialogs.CompileContiki; import org.contikios.cooja.dialogs.MessageList; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; +import org.contikios.cooja.dialogs.MessageListText; +import org.contikios.cooja.dialogs.MessageListUI; +import org.contikios.cooja.dialogs.MessageContainer; import org.contikios.cooja.interfaces.IPAddress; import org.contikios.cooja.interfaces.Mote2MoteRelations; import org.contikios.cooja.interfaces.MoteAttributes; @@ -71,7 +73,7 @@ public class Trxeb1120MoteType extends Exp5438MoteType { throw new MoteTypeCreationException("No identifier"); } - final MessageList compilationOutput = new MessageList(); + final MessageList compilationOutput = visAvailable ? new MessageListUI() : new MessageListText(); if (getCompileCommands() != null) { /* Handle multiple compilation commands one by one */ diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Trxeb2520MoteType.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Trxeb2520MoteType.java index bd3190770..939e60fcd 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Trxeb2520MoteType.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/Trxeb2520MoteType.java @@ -11,7 +11,9 @@ import org.contikios.cooja.MoteType; import org.contikios.cooja.Simulation; import org.contikios.cooja.dialogs.CompileContiki; import org.contikios.cooja.dialogs.MessageList; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; +import org.contikios.cooja.dialogs.MessageListText; +import org.contikios.cooja.dialogs.MessageListUI; +import org.contikios.cooja.dialogs.MessageContainer; import org.contikios.cooja.interfaces.IPAddress; import org.contikios.cooja.interfaces.Mote2MoteRelations; import org.contikios.cooja.interfaces.MoteAttributes; @@ -71,7 +73,7 @@ public class Trxeb2520MoteType extends Exp5438MoteType { throw new MoteTypeCreationException("No identifier"); } - final MessageList compilationOutput = new MessageList(); + final MessageList compilationOutput = visAvailable ? new MessageListUI() : new MessageListText(); if (getCompileCommands() != null) { /* Handle multiple compilation commands one by one */ diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/TyndallMoteType.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/TyndallMoteType.java index 4298a67aa..4e6472b11 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/TyndallMoteType.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/TyndallMoteType.java @@ -49,7 +49,9 @@ import org.contikios.cooja.MoteType; import org.contikios.cooja.Simulation; import org.contikios.cooja.dialogs.CompileContiki; import org.contikios.cooja.dialogs.MessageList; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; +import org.contikios.cooja.dialogs.MessageListText; +import org.contikios.cooja.dialogs.MessageListUI; +import org.contikios.cooja.dialogs.MessageContainer; import org.contikios.cooja.interfaces.IPAddress; import org.contikios.cooja.interfaces.Mote2MoteRelations; import org.contikios.cooja.interfaces.MoteAttributes; @@ -112,7 +114,7 @@ public class TyndallMoteType extends MspMoteType { throw new MoteTypeCreationException("No identifier"); } - final MessageList compilationOutput = new MessageList(); + final MessageList compilationOutput = visAvailable ? new MessageListUI() : new MessageListText(); if (getCompileCommands() != null) { /* Handle multiple compilation commands one by one */ diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/Msp802154BitErrorRadio.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/Msp802154BitErrorRadio.java new file mode 100644 index 000000000..53b971755 --- /dev/null +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/Msp802154BitErrorRadio.java @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2014, Uppsala University + * 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. + * + */ + +package org.contikios.cooja.mspmote.interfaces; + +import java.util.Random; + +import org.apache.log4j.Logger; + +import org.contikios.cooja.ClassDescription; +import org.contikios.cooja.Mote; +import org.contikios.cooja.Simulation; +import org.contikios.cooja.radiomediums.AbstractRadioMedium; + +import org.contikios.cooja.mspmote.MspMoteTimeEvent; +import org.contikios.cooja.mspmote.interfaces.Msp802154Radio; + + +/** + * Extension of MSPSim 802.15.4 radio wrapper with bit-level errors. + * + * Only errors due to signal fading are supported (as opposed to errors to interference). + * Interesting modelling effects can obtained if this is used together with a dynamic + * channel fading model. + * + * @author Atis Elsts + */ +@ClassDescription("IEEE 802.15.4 Bit Error Radio") +public class Msp802154BitErrorRadio extends Msp802154Radio { + private static Logger logger = Logger.getLogger(Msp802154Radio.class); + + private static final double NOISE_FLOOR = AbstractRadioMedium.SS_WEAK; + private static final double GOOD_SIGNAL = NOISE_FLOOR + 15.0; + + private Random random = null; + + public Msp802154BitErrorRadio(Mote m) { + super(m); + + random = getMote().getSimulation().getRandomGenerator(); + } + + /* The MSK-transformed symbol-to-codeword table. + * It's used for mapping between symbols and codeword by some popular + * 802.15.4 radios such as CC2420 and CC2520. */ + private static final int[] mskEncodeTable = { + 1618456172, + 1309113062, + 1826650030, + 1724778362, + 778887287, + 2061946375, + 2007919840, + 125494990, + 529027475, + 838370585, + 320833617, + 422705285, + 1368596360, + 85537272, + 139563807, + 2021988657 + }; + + /* Calculates the Hamming distance between two words */ + private int hammingDistance(int x1, int x2) { + return Integer.bitCount(x1 ^ x2); + } + + /* Send a symbol over the air with a specific bit error rate */ + private int transceiveSymbolWithErrors(int txSymbol, double bitErrorRate) { + /* First, transmit (encode and randomly corrupt) it */ + int chipSequence = mskEncodeTable[txSymbol]; + /* Note: loop until 31, not until 32 here, as the highest bit in the codeword + * is irrelevant for MSK encoded data, and therefore should not come into + * the Hamming distance calculations. */ + for (int i = 0; i < 31; ++i) { + double p = random.nextDouble(); + if (p < bitErrorRate) { + chipSequence ^= (1 << i); + } + } + + /* Now receive (decode) it */ + int bestRxSymbol = 0; + int bestHammingDistance = 32; + for (byte i = 0; i < 16; ++i) { + /* Resolve ties in a specific order: + * s7, s6, ... , s0, s15, s14 , ..., s8 */ + int rxSymbol = i < 8 ? 7 - i : 15 - i + 8; + + int hd = hammingDistance(chipSequence, mskEncodeTable[rxSymbol]); + if (hd < bestHammingDistance) { + bestRxSymbol = rxSymbol; + bestHammingDistance = hd; + if (hd == 0) { + break; + } + } + } + return bestRxSymbol; + } + + /* This is the probability that a bit will received incorrectly, for + * -95.0, -94.9, -94.8, ..., -80.0 dBm signal levels. + * It is modelled as Additive White Gaussian Noise (AWGN) channel + * with constellation size = 4, and log2(4) = 2 bits per over-the-air symbol. + * (See "Digital Communications" by Proakis, page 311) + * + * The table was generated with the following Python code: + * + * noise_floor = -95.0 + * good_signal = noise_floor + 15.0 + * + * # chips per second / carrier frequency + * # In this case: + * # 250 kbps * symbols_per_bit / 5 MHz 802.15.4 channel bandwidth + * spectral_efficiency = 250000 * (32 / 4) / 5000000. + * + * def snr_from_rssi(signal): + * return signal - noise_floor + * + * def combinations(n, k): + * return math.factorial(n) / (math.factorial(k) * math.factorial(n - k)) + * + * def chip_error_rate(signal): + * M_sk = 4 # constellation size + * K_b = 2 # bits per symbol + * snr = snr_from_rssi(signal) * spectral_efficiency # signal-noise ratio + * result = 0.0 + * for k in range(1, M_sk): + * result += ((-1)**(k + 1) / (k + 1.0)) * combinations(M_sk - 1, k) * math.exp(- (k / (k + 1.0)) * K_b * snr) + * return result * (M_sk / 2) / (M_sk - 1) + * + * for signal in range(int(noise_floor), int(good_signal + 1)): + * for decimal_part in range(10): + * s = signal + decimal_part / 10.0 + * print("{}: {:.16}".format(s, chip_error_rate(s))) + */ + private static final double[] bitErrorRateTable = { + 0.5000000000000000, + 0.4857075690874351, + 0.4717195981917559, + 0.4580362793082289, + 0.4446572346573086, + 0.4315815642818357, + 0.4188078906959320, + 0.4063344007440545, + 0.3941588848209507, + 0.3822787735959348, + 0.3706911723779558, + 0.3593928932511307, + 0.3483804851041035, + 0.3376502616704103, + 0.3271983276911817, + 0.3170206033059785, + 0.3071128467721474, + 0.2974706756080624, + 0.2880895862507204, + 0.2789649723135144, + 0.2700921415256470, + 0.2614663314303489, + 0.2530827239151328, + 0.2449364586434322, + 0.2370226454533358, + 0.2293363757856961, + 0.2218727332005190, + 0.2146268030374602, + 0.2075936812732179, + 0.2007684826257659, + 0.1941463479526962, + 0.1877224509883067, + 0.1814920044616803, + 0.1754502656356323, + 0.1695925413041991, + 0.1639141922842669, + 0.1584106374348990, + 0.1530773572360710, + 0.1479098969566969, + 0.1429038694401250, + 0.1380549575336883, + 0.1333589161873203, + 0.1288115742448300, + 0.1244088359500270, + 0.1201466821885792, + 0.1160211714852698, + 0.1120284407751141, + 0.1081647059657158, + 0.1044262623071727, + 0.1008094845848469, + 0.0973108271493890, + 0.0939268237974889, + 0.0906540875160106, + 0.0874893101013543, + 0.0844292616651377, + 0.0814707900365929, + 0.0786108200713800, + 0.0758463528759084, + 0.0731744649556428, + 0.0705923072953072, + 0.0680971043783837, + 0.0656861531527741, + 0.0633568219490458, + 0.0611065493572223, + 0.0589328430676567, + 0.0568332786811473, + 0.0548054984930601, + 0.0528472102558939, + 0.0509561859243809, + 0.0491302603869077, + 0.0473673301867607, + 0.0456653522364111, + 0.0440223425278144, + 0.0424363748414465, + 0.0409055794565784, + 0.0394281418650815, + 0.0380023014908522, + 0.0366263504167641, + 0.0352986321208818, + 0.0340175402235017, + 0.0327815172464461, + 0.0315890533858807, + 0.0304386852998058, + 0.0293289949112408, + 0.0282586082280085, + 0.0272261941799208, + 0.0262304634740650, + 0.0252701674687994, + 0.0243440970669807, + 0.0234510816288642, + 0.0225899879050480, + 0.0217597189897583, + 0.0209592132947168, + 0.0201874435437662, + 0.0194434157883799, + 0.0187261684441326, + 0.0180347713481601, + 0.0173683248375987, + 0.0167259588489542, + 0.0161068320383143, + 0.0155101309222909, + 0.0149350690395443, + 0.0143808861327198, + 0.0138468473506013, + 0.0133322424702643, + 0.0128363851389939, + 0.0123586121357148, + 0.0118982826516654, + 0.0114547775900349, + 0.0110274988842702, + 0.0106158688347500, + 0.0102193294635131, + 0.0098373418867231, + 0.0094693857045423, + 0.0091149584080853, + 0.0087735748031163, + 0.0084447664501541, + 0.0081280811206428, + 0.0078230822688482, + 0.0075293485191375, + 0.0072464731683002, + 0.0069740637025694, + 0.0067117413290037, + 0.0064591405208906, + 0.0062159085768378, + 0.0059817051932169, + 0.0057562020496316, + 0.0055390824070828, + 0.0053300407185094, + 0.0051287822513842, + 0.0049350227220528, + 0.0047484879415055, + 0.0045689134722762, + 0.0043960442961698, + 0.0042296344925230, + 0.0040694469267080, + 0.0039152529485966, + 0.0037668321007033, + 0.0036239718357372, + 0.0034864672432910, + 0.0033541207854084, + 0.0032267420407699, + 0.0031041474572487, + 0.0029861601125883, + 0.0028726094829638, + 0.0027633312191911, + 0.0026581669303560, + 0.0025569639746388, + 0.0024595752571165, + 0.0023658590343307, + 0.0022756787254125 + }; + + private double getBitErrorRate(double signal) { + if (signal <= NOISE_FLOOR) { + return 0.5; + } else if (signal >= GOOD_SIGNAL) { + return 0.0; + } else { + long position = Math.round((signal - NOISE_FLOOR) * 10.0); + return bitErrorRateTable[(int)position]; + } + } + + public void receiveCustomData(Object data) { + if (!(data instanceof Byte)) { + logger.fatal("Bad custom data: " + data); + return; + } + lastIncomingByte = (Byte) data; + + final byte inputByte; + if (isInterfered()) { + inputByte = (byte)0xFF; + } else { + double bitErrorRate = getBitErrorRate(currentSignalStrength); + if (bitErrorRate == 0.0) { + inputByte = lastIncomingByte; + } else if (bitErrorRate >= 0.5) { + inputByte = (byte) 0xFF; + } else { + /* convert to an unsigned int in order to prettify subsequent operations with bits */ + int incomingByteAsInt = lastIncomingByte; + if (incomingByteAsInt < 0) incomingByteAsInt += 256; + + /* a byte consists of 2 symbols; independently transceive each of them */ + int firstSymbol = transceiveSymbolWithErrors(incomingByteAsInt >> 4, bitErrorRate); + int secondSymbol = transceiveSymbolWithErrors(incomingByteAsInt & 0xf, bitErrorRate); + + inputByte = (byte)((firstSymbol << 4) + secondSymbol); + } + } + + mote.getSimulation().scheduleEvent(new MspMoteTimeEvent(mote, 0) { + public void execute(long t) { + super.execute(t); + radio.receivedByte(inputByte); + mote.requestImmediateWakeup(); + } + }, mote.getSimulation().getSimulationTime()); + + } +} diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/Msp802154Radio.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/Msp802154Radio.java index 31aa30377..baa9676a9 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/Msp802154Radio.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/Msp802154Radio.java @@ -69,16 +69,16 @@ public class Msp802154Radio extends Radio implements CustomDataRadio { private RadioEvent lastEvent = RadioEvent.UNKNOWN; - private final MspMote mote; - private final Radio802154 radio; + protected final MspMote mote; + protected final Radio802154 radio; private boolean isInterfered = false; private boolean isTransmitting = false; private boolean isReceiving = false; private boolean isSynchronized = false; - private byte lastOutgoingByte; - private byte lastIncomingByte; + protected byte lastOutgoingByte; + protected byte lastIncomingByte; private RadioPacket lastOutgoingPacket = null; private RadioPacket lastIncomingPacket = null; diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/plugins/MspCodeWatcher.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/plugins/MspCodeWatcher.java index 76f57c326..422c08381 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/plugins/MspCodeWatcher.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/plugins/MspCodeWatcher.java @@ -77,6 +77,7 @@ import org.contikios.cooja.Watchpoint; import org.contikios.cooja.WatchpointMote; import org.contikios.cooja.WatchpointMote.WatchpointListener; import org.contikios.cooja.dialogs.MessageList; +import org.contikios.cooja.dialogs.MessageListUI; import org.contikios.cooja.mspmote.MspMote; import org.contikios.cooja.mspmote.MspMoteType; import se.sics.mspsim.core.EmulationException; @@ -468,7 +469,7 @@ public class MspCodeWatcher extends VisPlugin implements MotePlugin { } } - private MessageList rulesDebuggingOutput = new MessageList(); + private MessageListUI rulesDebuggingOutput = new MessageListUI(); private boolean rulesWithDebuggingOutput = false; private int[] rulesMatched = null; private int[] rulesOK = null; diff --git a/tools/cooja/apps/serial_socket/java/org/contikios/cooja/serialsocket/SerialSocketServer.java b/tools/cooja/apps/serial_socket/java/org/contikios/cooja/serialsocket/SerialSocketServer.java index fa55da74b..e73eac513 100644 --- a/tools/cooja/apps/serial_socket/java/org/contikios/cooja/serialsocket/SerialSocketServer.java +++ b/tools/cooja/apps/serial_socket/java/org/contikios/cooja/serialsocket/SerialSocketServer.java @@ -644,6 +644,7 @@ public class SerialSocketServer extends VisPlugin implements MotePlugin { private Timer updateTimer = new Timer(UPDATE_INTERVAL, new ActionListener() { @Override public void actionPerformed(ActionEvent e) { + if (Cooja.isVisualized()) { if (closed) { updateTimer.stop(); return; @@ -652,6 +653,7 @@ public class SerialSocketServer extends VisPlugin implements MotePlugin { socketToMoteLabel.setText(inBytes + " bytes"); moteToSocketLabel.setText(outBytes + " bytes"); } + } }); } diff --git a/tools/cooja/java/org/contikios/cooja/Cooja.java b/tools/cooja/java/org/contikios/cooja/Cooja.java index a4c1be53d..4f0814249 100644 --- a/tools/cooja/java/org/contikios/cooja/Cooja.java +++ b/tools/cooja/java/org/contikios/cooja/Cooja.java @@ -133,6 +133,7 @@ import org.contikios.cooja.dialogs.ConfigurationWizard; import org.contikios.cooja.dialogs.CreateSimDialog; import org.contikios.cooja.dialogs.ExternalToolsDialog; import org.contikios.cooja.dialogs.MessageList; +import org.contikios.cooja.dialogs.MessageListUI; import org.contikios.cooja.dialogs.ProjectDirectoriesDialog; import org.contikios.cooja.plugins.MoteTypeInformation; import org.contikios.cooja.plugins.ScriptRunner; @@ -3834,7 +3835,7 @@ public class Cooja extends Observable { /* Contiki error */ if (exception instanceof ContikiError) { String contikiError = ((ContikiError) exception).getContikiError(); - MessageList list = new MessageList(); + MessageListUI list = new MessageListUI(); for (String l: contikiError.split("\n")) { list.addMessage(l); } @@ -3843,14 +3844,14 @@ public class Cooja extends Observable { } /* Compilation output */ - MessageList compilationOutput = null; + MessageListUI compilationOutput = null; if (exception instanceof MoteTypeCreationException && ((MoteTypeCreationException) exception).hasCompilationOutput()) { - compilationOutput = ((MoteTypeCreationException) exception).getCompilationOutput(); + compilationOutput = (MessageListUI) ((MoteTypeCreationException) exception).getCompilationOutput(); } else if (exception.getCause() != null && exception.getCause() instanceof MoteTypeCreationException && ((MoteTypeCreationException) exception.getCause()).hasCompilationOutput()) { - compilationOutput = ((MoteTypeCreationException) exception.getCause()).getCompilationOutput(); + compilationOutput = (MessageListUI) ((MoteTypeCreationException) exception.getCause()).getCompilationOutput(); } if (compilationOutput != null) { compilationOutput.addPopupMenuItem(null, true); @@ -3858,8 +3859,8 @@ public class Cooja extends Observable { } /* Stack trace */ - MessageList stackTrace = new MessageList(); - PrintStream printStream = stackTrace.getInputStream(MessageList.NORMAL); + MessageListUI stackTrace = new MessageListUI(); + PrintStream printStream = stackTrace.getInputStream(MessageListUI.NORMAL); exception.printStackTrace(printStream); stackTrace.addPopupMenuItem(null, true); tabbedPane.addTab("Java stack trace", new JScrollPane(stackTrace)); @@ -3931,7 +3932,7 @@ public class Cooja extends Observable { Box buttonBox = Box.createHorizontalBox(); /* Warnings message list */ - MessageList compilationOutput = new MessageList(); + MessageListUI compilationOutput = new MessageListUI(); for (String w: warnings) { compilationOutput.addMessage(w, MessageList.ERROR); } @@ -4354,14 +4355,14 @@ public class Cooja extends Observable { private static JProgressBar PROGRESS_BAR = null; private static ArrayList PROGRESS_WARNINGS = new ArrayList(); public static void setProgressMessage(String msg) { - setProgressMessage(msg, MessageList.NORMAL); + setProgressMessage(msg, MessageListUI.NORMAL); } public static void setProgressMessage(String msg, int type) { if (PROGRESS_BAR != null && PROGRESS_BAR.isShowing()) { PROGRESS_BAR.setString(msg); PROGRESS_BAR.setStringPainted(true); } - if (type != MessageList.NORMAL) { + if (type != MessageListUI.NORMAL) { PROGRESS_WARNINGS.add(msg); } } diff --git a/tools/cooja/java/org/contikios/cooja/CoreComm.java b/tools/cooja/java/org/contikios/cooja/CoreComm.java index ca124ad5b..a714eac23 100644 --- a/tools/cooja/java/org/contikios/cooja/CoreComm.java +++ b/tools/cooja/java/org/contikios/cooja/CoreComm.java @@ -36,6 +36,7 @@ import java.util.Vector; import org.contikios.cooja.MoteType.MoteTypeCreationException; import org.contikios.cooja.contikimote.ContikiMoteType; import org.contikios.cooja.dialogs.MessageList; +import org.contikios.cooja.dialogs.MessageListUI; /** * The purpose of corecomm's is communicating with a compiled Contiki system @@ -203,9 +204,9 @@ public abstract class CoreComm { */ public static void compileSourceFile(String className) throws MoteTypeCreationException { - MessageList compilationOutput = new MessageList(); + MessageListUI compilationOutput = new MessageListUI(); OutputStream compilationStandardStream = compilationOutput - .getInputStream(MessageList.NORMAL); + .getInputStream(MessageListUI.NORMAL); OutputStream compilationErrorStream = compilationOutput .getInputStream(MessageList.ERROR); diff --git a/tools/cooja/java/org/contikios/cooja/MoteType.java b/tools/cooja/java/org/contikios/cooja/MoteType.java index c5acb6880..60d9016be 100644 --- a/tools/cooja/java/org/contikios/cooja/MoteType.java +++ b/tools/cooja/java/org/contikios/cooja/MoteType.java @@ -37,6 +37,7 @@ import org.jdom.Element; import org.contikios.cooja.contikimote.ContikiMoteType; import org.contikios.cooja.dialogs.MessageList; +import org.contikios.cooja.dialogs.MessageListUI; /** * The mote type defines properties common for several motes. These properties diff --git a/tools/cooja/java/org/contikios/cooja/Simulation.java b/tools/cooja/java/org/contikios/cooja/Simulation.java index 18dfa7fe8..74f6ed902 100644 --- a/tools/cooja/java/org/contikios/cooja/Simulation.java +++ b/tools/cooja/java/org/contikios/cooja/Simulation.java @@ -847,6 +847,9 @@ public class Simulation extends Observable implements Runnable { } }; + //Add to list of uninitialized motes + motesUninit.add(mote); + if (!isRunning()) { /* Simulation is stopped, add mote immediately */ addMote.run(); @@ -854,8 +857,6 @@ public class Simulation extends Observable implements Runnable { /* Add mote from simulation thread */ invokeSimulationThread(addMote); } - //Add to list of uninitialized motes - motesUninit.add(mote); } diff --git a/tools/cooja/java/org/contikios/cooja/contikimote/ContikiMoteType.java b/tools/cooja/java/org/contikios/cooja/contikimote/ContikiMoteType.java index eef80bbc8..42205b94f 100644 --- a/tools/cooja/java/org/contikios/cooja/contikimote/ContikiMoteType.java +++ b/tools/cooja/java/org/contikios/cooja/contikimote/ContikiMoteType.java @@ -45,13 +45,11 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Random; -import java.util.Vector; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.swing.JComponent; import javax.swing.JLabel; -import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.jdom.Element; @@ -68,8 +66,8 @@ import org.contikios.cooja.mote.memory.SectionMoteMemory; import org.contikios.cooja.Simulation; import org.contikios.cooja.dialogs.CompileContiki; import org.contikios.cooja.dialogs.ContikiMoteCompileDialog; -import org.contikios.cooja.dialogs.MessageList; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; +import org.contikios.cooja.dialogs.MessageListUI; +import org.contikios.cooja.dialogs.MessageContainer; import org.contikios.cooja.mote.memory.ArrayMemory; import org.contikios.cooja.mote.memory.MemoryInterface; import org.contikios.cooja.mote.memory.MemoryInterface.Symbol; @@ -319,7 +317,7 @@ public class ContikiMoteType implements MoteType { if (getCompileCommands() == null) { throw new MoteTypeCreationException("No compile commands specified"); } - final MessageList compilationOutput = new MessageList(); + final MessageListUI compilationOutput = new MessageListUI(); String[] arr = getCompileCommands().split("\n"); for (String cmd : arr) { if (cmd.trim().isEmpty()) { diff --git a/tools/cooja/java/org/contikios/cooja/dialogs/AbstractCompileDialog.java b/tools/cooja/java/org/contikios/cooja/dialogs/AbstractCompileDialog.java index ee4cf486e..7210cb174 100644 --- a/tools/cooja/java/org/contikios/cooja/dialogs/AbstractCompileDialog.java +++ b/tools/cooja/java/org/contikios/cooja/dialogs/AbstractCompileDialog.java @@ -468,7 +468,7 @@ public abstract class AbstractCompileDialog extends JDialog { protected String[] compilationEnvironment = null; /* Default environment: inherit from current process */ public void compileContiki() throws Exception { - final MessageList taskOutput = new MessageList(); + final MessageListUI taskOutput = new MessageListUI(); if (contikiFirmware.exists()) { contikiFirmware.delete(); @@ -861,7 +861,7 @@ public abstract class AbstractCompileDialog extends JDialog { currentCompilationProcess = null; } - private boolean createNewCompilationTab(MessageList output) { + private boolean createNewCompilationTab(MessageListUI output) { abortAnyCompilation(); tabbedPane.remove(currentCompilationOutput); diff --git a/tools/cooja/java/org/contikios/cooja/dialogs/CompileContiki.java b/tools/cooja/java/org/contikios/cooja/dialogs/CompileContiki.java index 8a0deaee8..702024d13 100644 --- a/tools/cooja/java/org/contikios/cooja/dialogs/CompileContiki.java +++ b/tools/cooja/java/org/contikios/cooja/dialogs/CompileContiki.java @@ -127,7 +127,7 @@ public class CompileContiki { /* TODO Fix me */ final MessageList messageDialog; if (compilationOutput == null) { - messageDialog = new MessageList(); + messageDialog = new MessageListUI(); } else { messageDialog = compilationOutput; } @@ -138,8 +138,8 @@ public class CompileContiki { cmd += c + " "; } logger.info("> " + cmd); - messageDialog.addMessage("", MessageList.NORMAL); - messageDialog.addMessage("> " + cmd, MessageList.NORMAL); + messageDialog.addMessage("", MessageListUI.NORMAL); + messageDialog.addMessage("> " + cmd, MessageListUI.NORMAL); } final Process compileProcess; @@ -170,7 +170,7 @@ public class CompileContiki { String readLine; while ((readLine = processNormal.readLine()) != null) { if (messageDialog != null) { - messageDialog.addMessage(readLine, MessageList.NORMAL); + messageDialog.addMessage(readLine, MessageListUI.NORMAL); } } } catch (IOException e) { @@ -203,7 +203,7 @@ public class CompileContiki { compileProcess.waitFor(); } catch (Exception e) { messageDialog.addMessage(e.getMessage(), MessageList.ERROR); - syncException.setCompilationOutput(new MessageList()); + syncException.setCompilationOutput(new MessageListUI()); syncException.fillInStackTrace(); return; } @@ -214,7 +214,7 @@ public class CompileContiki { if (onFailure != null) { onFailure.actionPerformed(null); } - syncException.setCompilationOutput(new MessageList()); + syncException.setCompilationOutput(new MessageListUI()); syncException.fillInStackTrace(); return; } @@ -232,13 +232,13 @@ public class CompileContiki { if (onFailure != null) { onFailure.actionPerformed(null); } - syncException.setCompilationOutput(new MessageList()); + syncException.setCompilationOutput(new MessageListUI()); syncException.fillInStackTrace(); return; } - messageDialog.addMessage("", MessageList.NORMAL); - messageDialog.addMessage("Compilation succeded", MessageList.NORMAL); + messageDialog.addMessage("", MessageListUI.NORMAL); + messageDialog.addMessage("Compilation succeded", MessageListUI.NORMAL); if (onSuccess != null) { onSuccess.actionPerformed(null); } diff --git a/tools/cooja/java/org/contikios/cooja/dialogs/ConfigurationWizard.java b/tools/cooja/java/org/contikios/cooja/dialogs/ConfigurationWizard.java index a677c07a9..cfea6820a 100644 --- a/tools/cooja/java/org/contikios/cooja/dialogs/ConfigurationWizard.java +++ b/tools/cooja/java/org/contikios/cooja/dialogs/ConfigurationWizard.java @@ -150,7 +150,7 @@ public class ConfigurationWizard extends JDialog { private static int relBssSectionAddr; private static int bssSectionSize; - private static MessageList output; + private static MessageListUI output; private static JDialog progressDialog; private static JButton button; private static JProgressBar progressBar; @@ -430,7 +430,7 @@ public class ConfigurationWizard extends JDialog { } private static void prepareShowTestProgress(JFrame parent, String desc) { - output = new MessageList(); + output = new MessageListUI(); output.addPopupMenuItem(null, true); progressDialog = new JDialog(parent, desc); button = new JButton("Close"); @@ -542,7 +542,7 @@ public class ConfigurationWizard extends JDialog { return (String) optionPane.getValue(); } - public static boolean performCompileCTest(MessageList testOutput, PrintStream normalStream, PrintStream errorStream) { + public static boolean performCompileCTest(MessageListUI testOutput, PrintStream normalStream, PrintStream errorStream) { javaLibraryName = "LibTest" + testCounter; cLibraryName = "libtest" + testCounter; cLibrarySourceFile = new File(ContikiMoteType.tempOutputDirectory, cLibraryName + ".c"); @@ -642,8 +642,8 @@ public class ConfigurationWizard extends JDialog { return true; } - public static boolean performLoadTest(MessageList testOutput, PrintStream normalStream, PrintStream errorStream) { - MessageList dummy = new MessageList(); + public static boolean performLoadTest(MessageListUI testOutput, PrintStream normalStream, PrintStream errorStream) { + MessageListUI dummy = new MessageListUI(); PrintStream dummyStream = dummy.getInputStream(MessageList.NORMAL); if (!performCompileCTest(dummy, dummyStream, errorStream)) { return false; @@ -696,8 +696,8 @@ public class ConfigurationWizard extends JDialog { return true; } - public static boolean performAddressTest(MessageList testOutput, PrintStream normalStream, PrintStream errorStream) { - MessageList dummy = new MessageList(); + public static boolean performAddressTest(MessageListUI testOutput, PrintStream normalStream, PrintStream errorStream) { + MessageListUI dummy = new MessageListUI(); PrintStream dummyStream = dummy.getInputStream(MessageList.NORMAL); if (!performCompileCTest(dummy, dummyStream, errorStream)) { return false; @@ -743,7 +743,7 @@ public class ConfigurationWizard extends JDialog { return false; } - private static boolean performMapAddressTest(MessageList testOutput, PrintStream normalStream, PrintStream errorStream) { + private static boolean performMapAddressTest(MessageListUI testOutput, PrintStream normalStream, PrintStream errorStream) { testOutput.addMessage("### Testing map file based address parsing"); File mapFile = new File(ContikiMoteType.tempOutputDirectory, cLibraryName + ContikiMoteType.mapSuffix); @@ -839,7 +839,7 @@ public class ConfigurationWizard extends JDialog { return true; } - private static boolean performCommandAddressTest(MessageList testOutput, PrintStream normalStream, PrintStream errorStream) { + private static boolean performCommandAddressTest(MessageListUI testOutput, PrintStream normalStream, PrintStream errorStream) { testOutput.addMessage("### Testing command based address parsing"); testOutput.addMessage("### Executing command"); @@ -933,8 +933,8 @@ public class ConfigurationWizard extends JDialog { } - public static boolean performMemoryReplacementTest(MessageList testOutput, PrintStream normalStream, PrintStream errorStream) { - MessageList dummy = new MessageList(); + public static boolean performMemoryReplacementTest(MessageListUI testOutput, PrintStream normalStream, PrintStream errorStream) { + MessageListUI dummy = new MessageListUI(); PrintStream dummyStream = dummy.getInputStream(MessageList.NORMAL); if (!performCompileCTest(dummy, dummyStream, errorStream)) { return false; diff --git a/tools/cooja/java/org/contikios/cooja/dialogs/MessageContainer.java b/tools/cooja/java/org/contikios/cooja/dialogs/MessageContainer.java new file mode 100644 index 000000000..89fea5593 --- /dev/null +++ b/tools/cooja/java/org/contikios/cooja/dialogs/MessageContainer.java @@ -0,0 +1,17 @@ +package org.contikios.cooja.dialogs; + +public class MessageContainer { + + public final int type; + public final String message; + + public MessageContainer(String message, int type) { + this.message = message; + this.type = type; + } + + @Override + public String toString() { + return message; + } +} diff --git a/tools/cooja/java/org/contikios/cooja/dialogs/MessageList.java b/tools/cooja/java/org/contikios/cooja/dialogs/MessageList.java index 1921a68ce..f0af5f405 100644 --- a/tools/cooja/java/org/contikios/cooja/dialogs/MessageList.java +++ b/tools/cooja/java/org/contikios/cooja/dialogs/MessageList.java @@ -1,359 +1,17 @@ -/* - * Copyright (c) 2006, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - package org.contikios.cooja.dialogs; -import java.awt.Color; -import java.awt.Component; -import java.awt.Dimension; -import java.awt.Toolkit; -import java.awt.datatransfer.Clipboard; -import java.awt.datatransfer.StringSelection; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PipedInputStream; -import java.io.PipedOutputStream; -import java.io.PrintStream; -import java.util.ArrayList; +public interface MessageList { -import javax.swing.DefaultListCellRenderer; -import javax.swing.DefaultListModel; -import javax.swing.JCheckBoxMenuItem; -import javax.swing.JList; -import javax.swing.JMenuItem; -import javax.swing.JPopupMenu; -import javax.swing.JSeparator; -import javax.swing.ListModel; -import javax.swing.ListSelectionModel; -import org.apache.log4j.Logger; + public static final int NORMAL = 0; + public static final int WARNING = 1; + public static final int ERROR = 2; + + public void addMessage(String string, int normal); -import org.contikios.cooja.Cooja; + public MessageContainer[] getMessages(); -/** - * - * @author Adam Dunkels - * @author Joakim Eriksson - * @author Niclas Finne - * @author Fredrik Osterlind - */ -public class MessageList extends JList { + public void clearMessages(); - private static final Logger logger = Logger.getLogger(MessageList.class); + public void addMessage(String string); - public static final int NORMAL = 0; - public static final int WARNING = 1; - public static final int ERROR = 2; - - private Color[] foregrounds = new Color[] { null, Color.red }; - private Color[] backgrounds = new Color[] { null, null }; - - private JPopupMenu popup = null; - private boolean hideNormal = false; - - private int max = -1; - - public MessageList() { - super.setModel(new MessageModel()); - setCellRenderer(new MessageRenderer()); - setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - } - - /** - * @param max Maximum number of messages - */ - public MessageList(int max) { - this(); - this.max = max; - } - - public Color getForeground(int type) { - Color c = type > 0 && type <= foregrounds.length - ? foregrounds[type - 1] : null; - return c == null ? getForeground() : c; - } - - public void setForeground(int type, Color color) { - if (type > 0 && type <= foregrounds.length) { - foregrounds[type - 1] = color; - } else if (type == NORMAL) { - setForeground(color); - } - } - - public Color getBackground(int type) { - Color c = type > 0 && type <= backgrounds.length - ? backgrounds[type - 1] : null; - return c == null ? getBackground() : c; - } - - public void setBackground(int type, Color color) { - if (type > 0 && type <= backgrounds.length) { - backgrounds[type - 1] = color; - } else if (type == NORMAL) { - setBackground(color); - } - } - - public PrintStream getInputStream(final int type) { - try { - PipedInputStream input = new PipedInputStream(); - PipedOutputStream output = new PipedOutputStream(input); - final BufferedReader stringInput = new BufferedReader(new InputStreamReader(input)); - - Thread readThread = new Thread(new Runnable() { - @Override - public void run() { - String readLine; - try { - while ((readLine = stringInput.readLine()) != null) { - addMessage(readLine, type); - } - } catch (IOException e) { - // Occurs when write end closes pipe - die quietly - } - } - - }); - readThread.start(); - - return new PrintStream(output); - } catch (IOException e) { - logger.error(messages); - return null; - } - } - - public void addMessage(String message) { - addMessage(message, NORMAL); - } - - private ArrayList messages = new ArrayList(); - - public MessageContainer[] getMessages() { - return messages.toArray(new MessageContainer[0]); - } - - private void updateModel() { - boolean scroll = getLastVisibleIndex() >= getModel().getSize() - 2; - - while (messages.size() > getModel().getSize()) { - ((DefaultListModel) getModel()).addElement(messages.get(getModel().getSize())); - } - while (max > 0 && getModel().getSize() > max) { - ((DefaultListModel) getModel()).removeElementAt(0); - messages.remove(0); - } - - if (scroll) { - ensureIndexIsVisible(getModel().getSize() - 1); - } - } - - public void addMessage(final String message, final int type) { - Cooja.setProgressMessage(message, type); - - MessageContainer msg = new MessageContainer(message, type); - messages.add(msg); - - java.awt.EventQueue.invokeLater(new Runnable() { - @Override - public void run() { - updateModel(); - } - }); - } - - public void clearMessages() { - messages.clear(); - ((DefaultListModel) getModel()).clear(); - } - - @Override - public void setModel(ListModel model) { - throw new IllegalArgumentException("changing model not permitted"); - } - - public void addPopupMenuItem(JMenuItem item, boolean withDefaults) { - if (popup == null) { - popup = new JPopupMenu(); - addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - if (e.isPopupTrigger()) { - popup.show(MessageList.this, e.getX(), e.getY()); - } - } - @Override - public void mousePressed(MouseEvent e) { - if (e.isPopupTrigger()) { - popup.show(MessageList.this, e.getX(), e.getY()); - } - } - @Override - public void mouseReleased(MouseEvent e) { - if (e.isPopupTrigger()) { - popup.show(MessageList.this, e.getX(), e.getY()); - } - } - }); - - JMenuItem headerMenuItem = new JMenuItem("Output:"); - headerMenuItem.setEnabled(false); - popup.add(headerMenuItem); - popup.add(new JSeparator()); - - if (withDefaults) { - /* Create default menu items */ - final JMenuItem hideNormalMenuItem = new JCheckBoxMenuItem("Hide normal output"); - hideNormalMenuItem.setEnabled(true); - hideNormalMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - MessageList.this.hideNormal = hideNormalMenuItem.isSelected(); - ((MessageModel)getModel()).updateList(); - } - }); - popup.add(hideNormalMenuItem); - - JMenuItem consoleOutputMenuItem = new JMenuItem("Output to console"); - consoleOutputMenuItem.setEnabled(true); - consoleOutputMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - MessageContainer[] messages = getMessages(); - logger.info("\nCOMPILATION OUTPUT:\n"); - for (MessageContainer msg: messages) { - if (hideNormal && msg.type == NORMAL) { - continue; - } - logger.info(msg); - } - logger.info("\n"); - } - }); - popup.add(consoleOutputMenuItem); - - JMenuItem clipboardMenuItem = new JMenuItem("Copy to clipboard"); - clipboardMenuItem.setEnabled(true); - clipboardMenuItem.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); - - StringBuilder sb = new StringBuilder(); - MessageContainer[] messages = getMessages(); - for (MessageContainer msg: messages) { - if (hideNormal && msg.type == NORMAL) { - continue; - } - sb.append(msg + "\n"); - } - - StringSelection stringSelection = new StringSelection(sb.toString()); - clipboard.setContents(stringSelection, null); - } - }); - popup.add(clipboardMenuItem); - - popup.add(new JSeparator()); - } - } - - if (item == null) { - return; - } - - popup.add(item); - } - - // ------------------------------------------------------------------- - // MessageContainer - // ------------------------------------------------------------------- - - public static class MessageContainer { - public final int type; - public final String message; - - public MessageContainer(String message, int type) { - this.message = message; - this.type = type; - } - - @Override - public String toString() { - return message; - } - - } // end of inner class MessageContainer - - - // ------------------------------------------------------------------- - // Renderer for messages - // ------------------------------------------------------------------- - - private class MessageModel extends DefaultListModel { - public void updateList() { - fireContentsChanged(this, 0, getSize()); - } - } - - private class MessageRenderer extends DefaultListCellRenderer { - private Dimension nullDimension = new Dimension(0,0); - @Override - public Component getListCellRendererComponent( - JList list, - Object value, - int index, - boolean isSelected, - boolean cellHasFocus) - { - super.getListCellRendererComponent(list, value, index, isSelected, - cellHasFocus); - MessageContainer msg = (MessageContainer) value; - - if (hideNormal && msg.type == NORMAL && index != MessageList.this.getModel().getSize()-1) { - setPreferredSize(nullDimension); - return this; - } - - setPreferredSize(null); - setForeground(((MessageList) list).getForeground(msg.type)); - setBackground(((MessageList) list).getBackground(msg.type)); - return this; - } - - } // end of inner class MessageRenderer - -} // end of MessagList +} diff --git a/tools/cooja/java/org/contikios/cooja/dialogs/MessageListText.java b/tools/cooja/java/org/contikios/cooja/dialogs/MessageListText.java new file mode 100644 index 000000000..bd24c3485 --- /dev/null +++ b/tools/cooja/java/org/contikios/cooja/dialogs/MessageListText.java @@ -0,0 +1,27 @@ +package org.contikios.cooja.dialogs; + +public class MessageListText implements MessageList { + + @Override + public void addMessage(String string, int type) { + System.out.println("Message:" + string); + } + + @Override + public MessageContainer[] getMessages() { + // TODO Auto-generated method stub + return new MessageContainer[0]; + } + + @Override + public void clearMessages() { + // TODO Auto-generated method stub + } + + @Override + public void addMessage(String string) { + // TODO Auto-generated method stub + addMessage(string, MessageList.NORMAL); + } + +} diff --git a/tools/cooja/java/org/contikios/cooja/dialogs/MessageListUI.java b/tools/cooja/java/org/contikios/cooja/dialogs/MessageListUI.java new file mode 100644 index 000000000..11449b7ef --- /dev/null +++ b/tools/cooja/java/org/contikios/cooja/dialogs/MessageListUI.java @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2006, Swedish Institute of Computer Science. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +package org.contikios.cooja.dialogs; + +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.io.PrintStream; +import java.util.ArrayList; + +import javax.swing.DefaultListCellRenderer; +import javax.swing.DefaultListModel; +import javax.swing.JCheckBoxMenuItem; +import javax.swing.JList; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JSeparator; +import javax.swing.ListModel; +import javax.swing.ListSelectionModel; +import org.apache.log4j.Logger; + +import org.contikios.cooja.Cooja; + +/** + * + * @author Adam Dunkels + * @author Joakim Eriksson + * @author Niclas Finne + * @author Fredrik Osterlind + */ +public class MessageListUI extends JList implements MessageList { + + private static final Logger logger = Logger.getLogger(MessageListUI.class); + + private Color[] foregrounds = new Color[] { null, Color.red }; + private Color[] backgrounds = new Color[] { null, null }; + + private JPopupMenu popup = null; + private boolean hideNormal = false; + + private int max = -1; + + public MessageListUI() { + super.setModel(new MessageModel()); + setCellRenderer(new MessageRenderer()); + setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + } + + /** + * @param max Maximum number of messages + */ + public MessageListUI(int max) { + this(); + this.max = max; + } + + public Color getForeground(int type) { + Color c = type > 0 && type <= foregrounds.length + ? foregrounds[type - 1] : null; + return c == null ? getForeground() : c; + } + + public void setForeground(int type, Color color) { + if (type > 0 && type <= foregrounds.length) { + foregrounds[type - 1] = color; + } else if (type == NORMAL) { + setForeground(color); + } + } + + public Color getBackground(int type) { + Color c = type > 0 && type <= backgrounds.length + ? backgrounds[type - 1] : null; + return c == null ? getBackground() : c; + } + + public void setBackground(int type, Color color) { + if (type > 0 && type <= backgrounds.length) { + backgrounds[type - 1] = color; + } else if (type == NORMAL) { + setBackground(color); + } + } + + public PrintStream getInputStream(final int type) { + try { + PipedInputStream input = new PipedInputStream(); + PipedOutputStream output = new PipedOutputStream(input); + final BufferedReader stringInput = new BufferedReader(new InputStreamReader(input)); + + Thread readThread = new Thread(new Runnable() { + @Override + public void run() { + String readLine; + try { + while ((readLine = stringInput.readLine()) != null) { + addMessage(readLine, type); + } + } catch (IOException e) { + // Occurs when write end closes pipe - die quietly + } + } + + }); + readThread.start(); + + return new PrintStream(output); + } catch (IOException e) { + logger.error(messages); + return null; + } + } + + public void addMessage(String message) { + addMessage(message, NORMAL); + } + + private ArrayList messages = new ArrayList(); + + public MessageContainer[] getMessages() { + return messages.toArray(new MessageContainer[0]); + } + + private void updateModel() { + boolean scroll = getLastVisibleIndex() >= getModel().getSize() - 2; + + while (messages.size() > getModel().getSize()) { + ((DefaultListModel) getModel()).addElement(messages.get(getModel().getSize())); + } + while (max > 0 && getModel().getSize() > max) { + ((DefaultListModel) getModel()).removeElementAt(0); + messages.remove(0); + } + + if (scroll) { + ensureIndexIsVisible(getModel().getSize() - 1); + } + } + + public void addMessage(final String message, final int type) { + Cooja.setProgressMessage(message, type); + + MessageContainer msg = new MessageContainer(message, type); + messages.add(msg); + + java.awt.EventQueue.invokeLater(new Runnable() { + @Override + public void run() { + updateModel(); + } + }); + } + + public void clearMessages() { + messages.clear(); + ((DefaultListModel) getModel()).clear(); + } + + @Override + public void setModel(ListModel model) { + throw new IllegalArgumentException("changing model not permitted"); + } + + public void addPopupMenuItem(JMenuItem item, boolean withDefaults) { + if (popup == null) { + popup = new JPopupMenu(); + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if (e.isPopupTrigger()) { + popup.show(MessageListUI.this, e.getX(), e.getY()); + } + } + @Override + public void mousePressed(MouseEvent e) { + if (e.isPopupTrigger()) { + popup.show(MessageListUI.this, e.getX(), e.getY()); + } + } + @Override + public void mouseReleased(MouseEvent e) { + if (e.isPopupTrigger()) { + popup.show(MessageListUI.this, e.getX(), e.getY()); + } + } + }); + + JMenuItem headerMenuItem = new JMenuItem("Output:"); + headerMenuItem.setEnabled(false); + popup.add(headerMenuItem); + popup.add(new JSeparator()); + + if (withDefaults) { + /* Create default menu items */ + final JMenuItem hideNormalMenuItem = new JCheckBoxMenuItem("Hide normal output"); + hideNormalMenuItem.setEnabled(true); + hideNormalMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + MessageListUI.this.hideNormal = hideNormalMenuItem.isSelected(); + ((MessageModel)getModel()).updateList(); + } + }); + popup.add(hideNormalMenuItem); + + JMenuItem consoleOutputMenuItem = new JMenuItem("Output to console"); + consoleOutputMenuItem.setEnabled(true); + consoleOutputMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + MessageContainer[] messages = getMessages(); + logger.info("\nCOMPILATION OUTPUT:\n"); + for (MessageContainer msg: messages) { + if (hideNormal && msg.type == NORMAL) { + continue; + } + logger.info(msg); + } + logger.info("\n"); + } + }); + popup.add(consoleOutputMenuItem); + + JMenuItem clipboardMenuItem = new JMenuItem("Copy to clipboard"); + clipboardMenuItem.setEnabled(true); + clipboardMenuItem.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + + StringBuilder sb = new StringBuilder(); + MessageContainer[] messages = getMessages(); + for (MessageContainer msg: messages) { + if (hideNormal && msg.type == NORMAL) { + continue; + } + sb.append(msg + "\n"); + } + + StringSelection stringSelection = new StringSelection(sb.toString()); + clipboard.setContents(stringSelection, null); + } + }); + popup.add(clipboardMenuItem); + + popup.add(new JSeparator()); + } + } + + if (item == null) { + return; + } + + popup.add(item); + } + + // ------------------------------------------------------------------- + // Renderer for messages + // ------------------------------------------------------------------- + + private class MessageModel extends DefaultListModel { + public void updateList() { + fireContentsChanged(this, 0, getSize()); + } + } + + private class MessageRenderer extends DefaultListCellRenderer { + private Dimension nullDimension = new Dimension(0,0); + @Override + public Component getListCellRendererComponent( + JList list, + Object value, + int index, + boolean isSelected, + boolean cellHasFocus) + { + super.getListCellRendererComponent(list, value, index, isSelected, + cellHasFocus); + MessageContainer msg = (MessageContainer) value; + + if (hideNormal && msg.type == NORMAL && index != MessageListUI.this.getModel().getSize()-1) { + setPreferredSize(nullDimension); + return this; + } + + setPreferredSize(null); + setForeground(((MessageListUI) list).getForeground(msg.type)); + setBackground(((MessageListUI) list).getBackground(msg.type)); + return this; + } + + } // end of inner class MessageRenderer + +} // end of MessagList diff --git a/tools/cooja/java/org/contikios/cooja/plugins/ScriptRunner.java b/tools/cooja/java/org/contikios/cooja/plugins/ScriptRunner.java index bce5764e6..2df863a25 100644 --- a/tools/cooja/java/org/contikios/cooja/plugins/ScriptRunner.java +++ b/tools/cooja/java/org/contikios/cooja/plugins/ScriptRunner.java @@ -85,6 +85,7 @@ import org.contikios.cooja.PluginType; import org.contikios.cooja.Simulation; import org.contikios.cooja.VisPlugin; import org.contikios.cooja.dialogs.MessageList; +import org.contikios.cooja.dialogs.MessageListUI; import org.contikios.cooja.util.StringUtils; @ClassDescription("Simulation script editor") @@ -503,7 +504,7 @@ public class ScriptRunner extends VisPlugin { final BufferedReader err = new BufferedReader(new InputStreamReader(process.getErrorStream())); /* GUI components */ - final MessageList testOutput = new MessageList(); + final MessageListUI testOutput = new MessageListUI(); final AbstractAction abort = new AbstractAction() { public void actionPerformed(ActionEvent e) { process.destroy(); @@ -538,14 +539,14 @@ public class ScriptRunner extends VisPlugin { String line; try { while ((line = input.readLine()) != null) { - testOutput.addMessage(line, MessageList.NORMAL); + testOutput.addMessage(line, MessageListUI.NORMAL); } } catch (IOException e) { } - testOutput.addMessage("", MessageList.NORMAL); - testOutput.addMessage("", MessageList.NORMAL); - testOutput.addMessage("", MessageList.NORMAL); + testOutput.addMessage("", MessageListUI.NORMAL); + testOutput.addMessage("", MessageListUI.NORMAL); + testOutput.addMessage("", MessageListUI.NORMAL); /* Parse log file, check if test succeeded */ try { @@ -559,7 +560,7 @@ public class ScriptRunner extends VisPlugin { if (l == null) { line = ""; } - testOutput.addMessage(l, MessageList.NORMAL); + testOutput.addMessage(l, MessageListUI.NORMAL); if (l.contains("TEST OK")) { testSucceeded = true; break; diff --git a/tools/cooja/java/org/contikios/cooja/plugins/skins/AddressVisualizerSkin.java b/tools/cooja/java/org/contikios/cooja/plugins/skins/AddressVisualizerSkin.java index 44a77fc6a..609b2e771 100644 --- a/tools/cooja/java/org/contikios/cooja/plugins/skins/AddressVisualizerSkin.java +++ b/tools/cooja/java/org/contikios/cooja/plugins/skins/AddressVisualizerSkin.java @@ -46,7 +46,6 @@ import org.contikios.cooja.ClassDescription; import org.contikios.cooja.Mote; import org.contikios.cooja.Simulation; import org.contikios.cooja.SimEventCentral.MoteCountListener; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; import org.contikios.cooja.interfaces.IPAddress; import org.contikios.cooja.interfaces.Position; import org.contikios.cooja.interfaces.RimeAddress; diff --git a/tools/cooja/java/org/contikios/cooja/util/ExecuteJAR.java b/tools/cooja/java/org/contikios/cooja/util/ExecuteJAR.java index 66bbbd193..57d1fb4f6 100644 --- a/tools/cooja/java/org/contikios/cooja/util/ExecuteJAR.java +++ b/tools/cooja/java/org/contikios/cooja/util/ExecuteJAR.java @@ -54,8 +54,8 @@ import org.contikios.cooja.Plugin; import org.contikios.cooja.ProjectConfig; import org.contikios.cooja.Simulation; import org.contikios.cooja.dialogs.CompileContiki; -import org.contikios.cooja.dialogs.MessageList; -import org.contikios.cooja.dialogs.MessageList.MessageContainer; +import org.contikios.cooja.dialogs.MessageContainer; +import org.contikios.cooja.dialogs.MessageListUI; import org.contikios.cooja.plugins.ScriptRunner; import org.contikios.cooja.PluginType; @@ -415,7 +415,7 @@ public class ExecuteJAR { } logger.info("Building executable JAR: " + outputFile); - MessageList errors = new MessageList(); + MessageListUI errors = new MessageListUI(); try { CompileContiki.compile( "jar cfm " + outputFile.getAbsolutePath() + " manifest.tmp .", diff --git a/tools/sky/msp430-bsl-linux b/tools/sky/msp430-bsl-linux index 133f1bd35..c78e18640 100755 --- a/tools/sky/msp430-bsl-linux +++ b/tools/sky/msp430-bsl-linux @@ -1162,8 +1162,9 @@ class BootStrapLoader(LowLevel): sys.stderr.flush() self.bslTxRx(self.BSL_CHANGEBAUD, #Command: change baudrate a, l) #args are coded in adr and len + self.serialport.flush() time.sleep(0.010) #recomended delay - self.serialport.setBaudrate(baudrate) + self.serialport.baudrate = baudrate def actionReadBSLVersion(self): """informational output of BSL version number. diff --git a/tools/sky/uip6-bridge/Makefile b/tools/sky/uip6-bridge/Makefile index 492dc9b77..11fa74356 100644 --- a/tools/sky/uip6-bridge/Makefile +++ b/tools/sky/uip6-bridge/Makefile @@ -36,5 +36,5 @@ connect: ../../tapslip6 bridge: @sudo service radvd restart || echo radvd could not be restarted - sudo route add -6 aaaa::/64 tap0 - sudo ip -6 address add aaaa::1/64 dev tap0 + sudo route add -6 fd00::/64 tap0 + sudo ip -6 address add fd00::1/64 dev tap0 diff --git a/tools/stm32w/wpcapslip6/README.md b/tools/stm32w/wpcapslip6/README.md index f3c277efb..63bb6dccd 100644 --- a/tools/stm32w/wpcapslip6/README.md +++ b/tools/stm32w/wpcapslip6/README.md @@ -14,9 +14,9 @@ rpl-border-router (the latter on Windows Vista and later only). An example of usage with the RPL border router: - wpcapslip6 -s COMXX -b aaaa:: -a aaaa:1::1/128 02-00-00-00-00-01 + wpcapslip6 -s COMXX -b fd00:: -a fd00:1::1/128 02-00-00-00-00-01 where 02-00-00-00-00-01 is the MAC address of the local network adapter. --a aaaa:1::1/128 can be omitted if an IP address is already set to the network +-a fd00:1::1/128 can be omitted if an IP address is already set to the network adapter. diff --git a/tools/tunslip6.c b/tools/tunslip6.c index 0f10a72bf..49019a66b 100644 --- a/tools/tunslip6.c +++ b/tools/tunslip6.c @@ -837,7 +837,7 @@ main(int argc, char **argv) case 'h': default: fprintf(stderr,"usage: %s [options] ipaddress\n", prog); -fprintf(stderr,"example: tunslip6 -L -v2 -s ttyUSB1 aaaa::1/64\n"); +fprintf(stderr,"example: tunslip6 -L -v2 -s ttyUSB1 fd00::1/64\n"); fprintf(stderr,"Options are:\n"); #ifndef __APPLE__ fprintf(stderr," -B baudrate 9600,19200,38400,57600,115200 (default),230400,460800,921600\n"); @@ -884,14 +884,6 @@ exit(1); } } - if(*tundev == '\0') { - /* Use default. */ - if(tap) { - strcpy(tundev, "tap0"); - } else { - strcpy(tundev, "tun0"); - } - } if(host != NULL) { struct addrinfo hints, *servinfo, *p; int rv; diff --git a/tools/zolertia/z1-bsl b/tools/zolertia/z1-bsl index 7c0584337..31d58d1df 100755 --- a/tools/zolertia/z1-bsl +++ b/tools/zolertia/z1-bsl @@ -1350,8 +1350,9 @@ class BootStrapLoader(LowLevel): sys.stderr.flush() self.bslTxRx(self.BSL_CHANGEBAUD, #Command: change baudrate a, l) #args are coded in adr and len + self.serialport.flush() time.sleep(0.010) #recomended delay - self.serialport.setBaudrate(baudrate) + self.serialport.baudrate = baudrate def actionReadBSLVersion(self): """informational output of BSL version number. diff --git a/tools/zolertia/z1-bsl-nopic b/tools/zolertia/z1-bsl-nopic index 802c84642..8b5edd8f5 100755 --- a/tools/zolertia/z1-bsl-nopic +++ b/tools/zolertia/z1-bsl-nopic @@ -1364,8 +1364,9 @@ class BootStrapLoader(LowLevel): sys.stderr.flush() self.bslTxRx(self.BSL_CHANGEBAUD, #Command: change baudrate a, l) #args are coded in adr and len + self.serialport.flush() time.sleep(0.010) #recomended delay - self.serialport.setBaudrate(baudrate) + self.serialport.baudrate = baudrate def actionReadBSLVersion(self): """informational output of BSL version number.