diff --git a/.gitignore b/.gitignore index d8874dffb..c8e57f080 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ *.c128 *.c64 *.cc2538dk +*.remote *.srf06-cc26xx *.ev-aducrf101mkxz *.report diff --git a/.gitmodules b/.gitmodules index 7391a785b..48be5ceaa 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "tools/cc2538-bsl"] path = tools/cc2538-bsl url = https://github.com/JelmerT/cc2538-bsl.git +[submodule "cpu/cc26xx/lib/cc26xxware"] + path = cpu/cc26xx/lib/cc26xxware + url = https://github.com/g-oikonomou/cc26xxware.git diff --git a/.travis.yml b/.travis.yml index 03559d8a5..9fb8295c5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ before_script: - sudo apt-get -qq install libc6:i386 libgcc1:i386 gcc-4.6-base:i386 libstdc++5:i386 libstdc++6:i386 - ## Install old APCS ARM toolchain for mc1233x, cc2538 and mbxxx + ## Install old APCS ARM toolchain for mc1233x and mbxxx - if [ ${BUILD_ARCH:-0} = arm-apcs ] ; then $WGET https://raw.githubusercontent.com/wiki/malvira/libmc1322x/files/arm-2008q3-66-arm-none-eabi-i686-pc-linux-gnu.tar.bz2 && tar xjf arm-2008q3*.tar.bz2 -C /tmp/ && @@ -41,20 +41,14 @@ before_script: ## Install mainline ARM toolchain. gcc-arm-none-eabi is available ## in Ubuntu >= 14.04, but this external PPA is needed for 12.04. - - if [ ${BUILD_ARCH:-0} = arm ] ; then + ## Install srecord + - if [ ${BUILD_ARCH:-0} = arm-aapcs ] ; then sudo add-apt-repository -y ppa:terry.guo/gcc-arm-embedded && sudo apt-get -qq update && - sudo apt-get -qq install gcc-arm-none-eabi && + sudo apt-get -qq install gcc-arm-none-eabi srecord && arm-none-eabi-gcc --version ; fi - ## Download and extract cc26xxware - - if [ ${BUILD_ARCH:-0} = arm ] ; then - wget http://www.ti.com/lit/sw/swrc296/swrc296.zip && - unzip swrc296.zip && - export TI_CC26XXWARE=cc26xxware_2_20_06_14829 ; - fi - ## Install RL78 GCC toolchain - sudo apt-get install libncurses5:i386 zlib1g:i386 - $WGET http://adamdunkels.github.io/contiki-fork/gnurl78-v13.02-elf_1-2_i386.deb && @@ -105,11 +99,13 @@ env: ## of environment variable defined below - BUILD_TYPE='doxygen' BUILD_CATEGORY='doxygen' - BUILD_TYPE='compile-base' BUILD_CATEGORY='compile' + - BUILD_TYPE='compile-tools' BUILD_CATEGORY='compile' - BUILD_TYPE='collect' - BUILD_TYPE='collect-lossy' - BUILD_TYPE='rpl' - BUILD_TYPE='rime' - BUILD_TYPE='ipv6' + - BUILD_TYPE='ip64' MAKE_TARGETS='cooja' - BUILD_TYPE='hello-world' - BUILD_TYPE='base' # XXX: netperf disabled b/c it's flaky @@ -122,6 +118,6 @@ env: - BUILD_TYPE='compile-8051-ports' BUILD_CATEGORY='compile' BUILD_ARCH='8051' - BUILD_TYPE='compile-arm-apcs-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm-apcs' - BUILD_TYPE='compile-6502-ports' BUILD_CATEGORY='compile' BUILD_ARCH='6502' - - BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm' + - BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm-aapcs' - BUILD_TYPE='slip-radio' MAKE_TARGETS='cooja' - BUILD_TYPE='llsec' MAKE_TARGETS='cooja' diff --git a/Makefile.include b/Makefile.include index bc3d14668..36b5e06ca 100644 --- a/Makefile.include +++ b/Makefile.include @@ -147,7 +147,6 @@ endif ifdef MODULES UNIQUEMODULES = $(call uniq,$(MODULES)) - MODULESSUBST = ${subst /,-,$(UNIQUEMODULES)} MODULEDIRS = ${wildcard ${addprefix $(CONTIKI)/, $(UNIQUEMODULES)}} MODULES_SOURCES = ${foreach d, $(MODULEDIRS), ${subst ${d}/,,${wildcard $(d)/*.c}}} CONTIKI_SOURCEFILES += $(MODULES_SOURCES) diff --git a/apps/er-coap/er-coap-engine.c b/apps/er-coap/er-coap-engine.c index 76a230545..4871368b4 100644 --- a/apps/er-coap/er-coap-engine.c +++ b/apps/er-coap/er-coap-engine.c @@ -36,6 +36,7 @@ * Matthias Kovatsch */ +#include "sys/cc.h" #include #include #include diff --git a/apps/er-coap/er-coap-separate.c b/apps/er-coap/er-coap-separate.c index d35566d79..5e2242b9c 100644 --- a/apps/er-coap/er-coap-separate.c +++ b/apps/er-coap/er-coap-separate.c @@ -36,6 +36,7 @@ * Matthias Kovatsch */ +#include "sys/cc.h" #include #include #include "er-coap-separate.h" diff --git a/apps/er-coap/er-coap.c b/apps/er-coap/er-coap.c index f73b04186..34c671623 100644 --- a/apps/er-coap/er-coap.c +++ b/apps/er-coap/er-coap.c @@ -39,6 +39,7 @@ #include #include #include "contiki.h" +#include "sys/cc.h" #include "contiki-net.h" #include "er-coap.h" diff --git a/apps/er-coap/er-coap.h b/apps/er-coap/er-coap.h index 48f6e4b4a..69ea8b363 100644 --- a/apps/er-coap/er-coap.h +++ b/apps/er-coap/er-coap.h @@ -79,10 +79,6 @@ enum { OPTION_MAP_SIZE = sizeof(uint8_t) * 8 }; #define SET_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] |= 1 << (opt % OPTION_MAP_SIZE)) #define IS_OPTION(packet, opt) ((packet)->options[opt / OPTION_MAP_SIZE] & (1 << (opt % OPTION_MAP_SIZE))) -#ifndef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif /* MIN */ - /* parsed message struct */ typedef struct { uint8_t *buffer; /* pointer to CoAP header / incoming packet buffer / memory to serialize packet */ diff --git a/apps/mqtt/mqtt.c b/apps/mqtt/mqtt.c index 112c584cb..f56df3a16 100644 --- a/apps/mqtt/mqtt.c +++ b/apps/mqtt/mqtt.c @@ -57,13 +57,12 @@ #include "lib/assert.h" #include "lib/list.h" +#include "sys/cc.h" #include #include #include /*---------------------------------------------------------------------------*/ -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -/*---------------------------------------------------------------------------*/ #define DEBUG 0 #if DEBUG #define PRINTF(...) PRINTF(__VA_ARGS__) diff --git a/apps/rest-coap/Makefile.rest-coap b/apps/rest-coap/Makefile.rest-coap deleted file mode 100644 index cd6e332cd..000000000 --- a/apps/rest-coap/Makefile.rest-coap +++ /dev/null @@ -1,4 +0,0 @@ -rest-coap_src = coap-common.c coap-server.c - -APPS += rest-common -include $(CONTIKI)/apps/rest-common/Makefile.rest-common diff --git a/apps/rest-coap/coap-common.c b/apps/rest-coap/coap-common.c deleted file mode 100644 index 0ddff495d..000000000 --- a/apps/rest-coap/coap-common.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * coap-common.c - * - * Created on: Aug 30, 2010 - * Author: dogan - */ - -#ifdef CONTIKI_TARGET_NETSIM - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include - #include -#else - #include "contiki.h" - #include "contiki-net.h" - #include -#endif - -#include "coap-common.h" - -#define DEBUG 0 -#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 - -void init_packet(coap_packet_t* packet) -{ - packet->ver = 1; - packet->type = 0; - packet->option_count = 0; - packet->code = 0; - packet->tid = 0; - packet->options = NULL; - packet->url = NULL; - packet->url_len = 0; - packet->query = NULL; - packet->query_len = 0; - packet->payload = NULL; - packet->payload_len = 0; -} - -int serialize_packet(coap_packet_t* packet, uint8_t* buffer) -{ - int index = 0; - header_option_t* option = NULL; - uint16_t option_delta = 0; - - buffer[0] = (packet->ver) << COAP_HEADER_VERSION_POSITION; - buffer[0] |= (packet->type) << COAP_HEADER_TYPE_POSITION; - buffer[0] |= packet->option_count; - buffer[1] = packet->code; - uint16_t temp = uip_htons(packet->tid); - memcpy( - (void*)&buffer[2], - (void*)(&temp), - sizeof(packet->tid)); - - index += 4; - - PRINTF("serialize option_count %u\n", packet->option_count); - - /*Options should be sorted beforehand*/ - for (option = packet->options ; option ; option = option->next){ - uint16_t delta = option->option - option_delta; - if ( !delta ){ - PRINTF("WARNING: Delta==Zero\n"); - } - buffer[index] = (delta) << COAP_HEADER_OPTION_DELTA_POSITION; - - PRINTF("option %u len %u option diff %u option_value addr %x option addr %x next option addr %x", option->option, option->len, option->option - option_delta, (unsigned int) option->value, (unsigned int)option, (unsigned int)option->next); - - int i = 0; - for ( ; i < option->len ; i++ ){ - PRINTF(" (%u)", option->value[i]); - } - PRINTF("\n"); - - if (option->len < 0xF){ - buffer[index] |= option->len; - index++; - } else{ - buffer[index] |= (0xF); //1111 - buffer[index + 1] = option->len - (0xF); - index += 2; - } - - memcpy((char*)&buffer[index], option->value, option->len); - index += option->len; - option_delta = option->option; - } - - if(packet->payload){ - memcpy(&buffer[index], packet->payload, packet->payload_len); - index += packet->payload_len; - } - - return index; -} diff --git a/apps/rest-coap/coap-common.h b/apps/rest-coap/coap-common.h deleted file mode 100644 index 835d123f3..000000000 --- a/apps/rest-coap/coap-common.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * coap.h - * - * Created on: Aug 25, 2010 - * Author: dogan - */ - -#ifndef COAP_COMMON_H_ -#define COAP_COMMON_H_ - -#include "contiki-net.h" - -/*COAP method types*/ -typedef enum { - COAP_GET = 1, - COAP_POST, - COAP_PUT, - COAP_DELETE -} coap_method_t; - -typedef enum { - MESSAGE_TYPE_CON, - MESSAGE_TYPE_NON, - MESSAGE_TYPE_ACK, - MESSAGE_TYPE_RST -} message_type; - -typedef enum { - OK_200 = 80, - CREATED_201 = 81, - NOT_MODIFIED_304 = 124, - BAD_REQUEST_400 = 160, - NOT_FOUND_404 = 164, - METHOD_NOT_ALLOWED_405 = 165, - UNSUPPORTED_MADIA_TYPE_415 = 175, - INTERNAL_SERVER_ERROR_500 = 200, - BAD_GATEWAY_502 = 202, - GATEWAY_TIMEOUT_504 = 204 -} status_code_t; - -typedef enum { - Option_Type_Content_Type = 1, - Option_Type_Max_Age = 2, - Option_Type_Etag = 4, - Option_Type_Uri_Authority = 5, - Option_Type_Location = 6, - Option_Type_Uri_Path = 9, - Option_Type_Subscription_Lifetime = 10, - Option_Type_Token = 11, - Option_Type_Block = 13, - Option_Type_Uri_Query = 15 -} option_type; - -typedef enum { - TEXT_PLAIN = 0, - TEXT_XML = 1, - TEXT_CSV = 2, - TEXT_HTML = 3, - IMAGE_GIF = 21, - IMAGE_JPEG = 22, - IMAGE_PNG = 23, - IMAGE_TIFF = 24, - AUDIO_RAW = 25, - VIDEO_RAW = 26, - APPLICATION_LINK_FORMAT = 40, - APPLICATION_XML = 41, - APPLICATION_OCTET_STREAM = 42, - APPLICATION_RDF_XML = 43, - APPLICATION_SOAP_XML = 44, - APPLICATION_ATOM_XML = 45, - APPLICATION_XMPP_XML = 46, - APPLICATION_EXI = 47, - APPLICATION_X_BXML = 48, - APPLICATION_FASTINFOSET = 49, - APPLICATION_SOAP_FASTINFOSET = 50, - APPLICATION_JSON = 51 -} content_type_t; - -#define COAP_HEADER_VERSION_MASK 0xC0 -#define COAP_HEADER_TYPE_MASK 0x30 -#define COAP_HEADER_OPTION_COUNT_MASK 0x0F -#define COAP_HEADER_OPTION_DELTA_MASK 0xF0 -#define COAP_HEADER_OPTION_SHORT_LENGTH_MASK 0x0F - -#define COAP_HEADER_VERSION_POSITION 6 -#define COAP_HEADER_TYPE_POSITION 4 -#define COAP_HEADER_OPTION_DELTA_POSITION 4 - -#define REQUEST_BUFFER_SIZE 200 - -#define DEFAULT_CONTENT_TYPE 0 -#define DEFAULT_MAX_AGE 60 -#define DEFAULT_URI_AUTHORITY "" -#define DEFAULT_URI_PATH "" - -//keep open requests and their xactid - -struct header_option_t -{ - struct header_option_t* next; - uint16_t option; - uint16_t len; - uint8_t* value; -}; -typedef struct header_option_t header_option_t; - -struct block_option_t { - uint32_t number; - uint8_t more; - uint8_t size; -}; -typedef struct block_option_t block_option_t; - -typedef struct -{ - uint8_t ver; //2-bits currently set to 1. - uint8_t type; //2-bits Confirmable (0), Non-Confirmable (1), Acknowledgment (2) or Reset (3) - uint8_t option_count; //4-bits - uint8_t code; //8-bits Method or response code - uint16_t tid; //16-bit unsigned integer - header_option_t* options; - char* url; //put it just as a shortcut or else need to parse options everytime to access it. - uint16_t url_len; - char* query; - uint16_t query_len; - uint16_t payload_len; - uint8_t* payload; - uip_ipaddr_t addr; -} coap_packet_t; - -/*error definitions*/ -typedef enum -{ - NO_ERROR, - - /*Memory errors*/ - MEMORY_ALLOC_ERR, - MEMORY_BOUNDARY_EXCEEDED -} error_t; - -int serialize_packet(coap_packet_t* request, uint8_t* buffer); -void init_packet(coap_packet_t* packet); - -#endif /* COAP_COMMON_H_ */ diff --git a/apps/rest-coap/coap-server.c b/apps/rest-coap/coap-server.c deleted file mode 100644 index 6f20e364c..000000000 --- a/apps/rest-coap/coap-server.c +++ /dev/null @@ -1,545 +0,0 @@ -#include -#include -#include -#include /*for isxdigit*/ -#include "contiki.h" -#include "contiki-net.h" - -#include "buffer.h" -#include "coap-server.h" -#include "rest-util.h" -#include "rest.h" /*added for periodic_resource*/ - -#include "dev/leds.h" - -#if !UIP_CONF_IPV6_RPL && !defined (CONTIKI_TARGET_MINIMAL_NET) -#include "static-routing.h" -#endif - -#define DEBUG 0 -#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 MAX_PAYLOAD_LEN 120 -#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) -#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) -static struct uip_udp_conn *server_conn; - -static uint16_t current_tid; - -static service_callback service_cbk = NULL; - -void -coap_set_service_callback(service_callback callback) -{ - service_cbk = callback; -} - -void -parse_message(coap_packet_t* packet, uint8_t* buf, uint16_t size) -{ - int processed = 0; - int i = 0; - PRINTF("parse_message size %d-->\n",size); - - init_packet(packet); - - packet->ver = (buf[0] & COAP_HEADER_VERSION_MASK) >> COAP_HEADER_VERSION_POSITION; - packet->type = (buf[0] & COAP_HEADER_TYPE_MASK) >> COAP_HEADER_TYPE_POSITION; - packet->option_count = buf[0] & COAP_HEADER_OPTION_COUNT_MASK; - packet->code = buf[1]; - packet->tid = (buf[2] << 8) + buf[3]; - - processed += 4; - - if (packet->option_count) { - int option_index = 0; - uint8_t option_delta; - uint16_t option_len; - uint8_t* option_buf = buf + processed; - packet->options = (header_option_t*)allocate_buffer(sizeof(header_option_t) * packet->option_count); - - if (packet->options) { - header_option_t* current_option = packet->options; - header_option_t* prev_option = NULL; - while(option_index < packet->option_count) { - /*FIXME : put boundary controls*/ - option_delta = (option_buf[i] & COAP_HEADER_OPTION_DELTA_MASK) >> COAP_HEADER_OPTION_DELTA_POSITION; - option_len = (option_buf[i] & COAP_HEADER_OPTION_SHORT_LENGTH_MASK); - i++; - if (option_len == 0xf) { - option_len += option_buf[i]; - i++; - } - - current_option->option = option_delta; - current_option->len = option_len; - current_option->value = option_buf + i; - if (option_index) { - prev_option->next = current_option; - /*This field defines the difference between the option Type of - * this option and the previous option (or zero for the first option)*/ - current_option->option += prev_option->option; - } - - if (current_option->option == Option_Type_Uri_Path) { - packet->url = (char*)current_option->value; - packet->url_len = current_option->len; - } else if (current_option->option == Option_Type_Uri_Query){ - packet->query = (char*)current_option->value; - packet->query_len = current_option->len; - } - - PRINTF("OPTION %d %u %s \n", current_option->option, current_option->len, current_option->value); - - i += option_len; - option_index++; - prev_option = current_option++; - } - current_option->next = NULL; - } else { - PRINTF("MEMORY ERROR\n"); /*FIXME : add control here*/ - return; - } - } - processed += i; - - /**/ - if (processed < size) { - packet->payload = &buf[processed]; - packet->payload_len = size - processed; - } - - /*FIXME url is not decoded - is necessary?*/ - - /*If query is not already provided via Uri_Query option then check URL*/ - if (packet->url && !packet->query) { - if ((packet->query = strchr(packet->url, '?'))) { - uint16_t total_url_len = packet->url_len; - /*set query len and update url len so that it does not include query part now*/ - packet->url_len = packet->query - packet->url; - packet->query++; - packet->query_len = packet->url + total_url_len - packet->query; - - PRINTF("url %s, url_len %u, query %s, query_len %u\n", packet->url, packet->url_len, packet->query, packet->query_len); - } - } - - PRINTF("PACKET ver:%d type:%d oc:%d \ncode:%d tid:%u url:%s len:%u payload:%s pay_len %u\n", (int)packet->ver, (int)packet->type, (int)packet->option_count, (int)packet->code, packet->tid, packet->url, packet->url_len, packet->payload, packet->payload_len); -} - -int -coap_get_query_variable(coap_packet_t* packet, const char *name, char* output, uint16_t output_size) -{ - if (packet->query) { - return get_variable(name, packet->query, packet->query_len, output, output_size, 0); - } - - return 0; -} - -int -coap_get_post_variable(coap_packet_t* packet, const char *name, char* output, uint16_t output_size) -{ - if (packet->payload) { - return get_variable(name, packet->payload, packet->payload_len, output, output_size, 1); - } - - return 0; -} - -static header_option_t* -allocate_header_option(uint16_t variable_len) -{ - PRINTF("sizeof header_option_t %u variable size %u\n", sizeof(header_option_t), variable_len); - uint8_t* buffer = allocate_buffer(sizeof(header_option_t) + variable_len); - if (buffer){ - header_option_t* option = (header_option_t*) buffer; - option->next = NULL; - option->len = 0; - option->value = buffer + sizeof(header_option_t); - return option; - } - - return NULL; -} - -/*FIXME : does not overwrite the same option yet.*/ -int -coap_set_option(coap_packet_t* packet, option_type option_type, uint16_t len, uint8_t* value) -{ - PRINTF("coap_set_option len %u\n", len); - header_option_t* option = allocate_header_option(len); - if (option){ - option->next = NULL; - option->len = len; - option->option = option_type; - memcpy(option->value, value, len); - header_option_t* option_current = packet->options; - header_option_t* prev = NULL; - while (option_current){ - if (option_current->option > option->option){ - break; - } - prev = option_current; - option_current = option_current->next; - } - - if (!prev){ - if (option_current){ - option->next = option_current; - } - packet->options = option; - } else{ - option->next = option_current; - prev->next = option; - } - - packet->option_count++; - - PRINTF("option->len %u option->option %u option->value %x next %x\n", option->len, option->option, (unsigned int) option->value, (unsigned int)option->next); - - int i = 0; - for ( ; i < option->len ; i++ ){ - PRINTF(" (%u)", option->value[i]); - } - PRINTF("\n"); - - return 1; - } - - return 0; -} - -header_option_t* -coap_get_option(coap_packet_t* packet, option_type option_type) -{ - PRINTF("coap_get_option count: %u--> \n", packet->option_count); - int i = 0; - - header_option_t* current_option = packet->options; - for (; i < packet->option_count; current_option = current_option->next, i++) { - PRINTF("Current option: %u\n", current_option->option); - if (current_option->option == option_type){ - return current_option; - } - } - - return NULL; -} - -static void -fill_error_packet(coap_packet_t* packet, int error, uint16_t tid) -{ - packet->ver=1; - packet->option_count=0; - packet->url=NULL; - packet->options=NULL; - switch (error){ - case MEMORY_ALLOC_ERR: - packet->code=INTERNAL_SERVER_ERROR_500; - packet->tid=tid; - packet->type=MESSAGE_TYPE_ACK; - break; - default: - break; - } -} - -static void -init_response(coap_packet_t* request, coap_packet_t* response) -{ - init_packet(response); - if(request->type == MESSAGE_TYPE_CON) { - response->code = OK_200; - response->tid = request->tid; - response->type = MESSAGE_TYPE_ACK; - } -} - -uint16_t -coap_get_payload(coap_packet_t* packet, uint8_t** payload) -{ - if (packet->payload) { - *payload = packet->payload; - return packet->payload_len; - } else { - *payload = NULL; - return 0; - } -} - -int -coap_set_payload(coap_packet_t* packet, uint8_t* payload, uint16_t size) -{ - packet->payload = copy_to_buffer(payload, size); - if (packet->payload) { - packet->payload_len = size; - return 1; - } - - return 0; -} - -int -coap_set_header_content_type(coap_packet_t* packet, content_type_t content_type) -{ - uint16_t len = 1; - - return coap_set_option(packet, Option_Type_Content_Type, len, (uint8_t*) &content_type); -} - -content_type_t -coap_get_header_content_type(coap_packet_t* packet) -{ - header_option_t* option = coap_get_option(packet, Option_Type_Content_Type); - if (option){ - return (uint8_t)(*(option->value)); - } - - return DEFAULT_CONTENT_TYPE; -} - -int -coap_get_header_subscription_lifetime(coap_packet_t* packet, uint32_t* lifetime) -{ - PRINTF("coap_get_header_subscription_lifetime --> \n"); - header_option_t* option = coap_get_option(packet, Option_Type_Subscription_Lifetime); - if (option){ - PRINTF("Subs Found len %u (first byte %u)\n", option->len, (uint16_t)option->value[0]); - - *lifetime = read_int(option->value, option->len); - return 1; - } - - return 0; -} - -int -coap_set_header_subscription_lifetime(coap_packet_t* packet, uint32_t lifetime) -{ - uint8_t temp[4]; - uint16_t len = write_variable_int(temp, lifetime); - - return coap_set_option(packet, Option_Type_Subscription_Lifetime, len, temp); -} - -int -coap_get_header_block(coap_packet_t* packet, block_option_t* block) -{ - uint32_t all_block; - PRINTF("coap_get_header_block --> \n"); - header_option_t* option = coap_get_option(packet, Option_Type_Block); - if (option){ - PRINTF("Block Found len %u (first byte %u)\n", option->len, (uint16_t)option->value[0]); - - all_block = read_int(option->value, option->len); - block->number = all_block >> 4; - block->more = (all_block & 0x8) >> 3; - block->size = (all_block & 0x7); - return 1; - } - - return 0; -} - -int -coap_set_header_block(coap_packet_t* packet, uint32_t number, uint8_t more, uint8_t size) -{ - uint8_t temp[4]; - size = log_2(size/16); - number = number << 4; - number |= (more << 3) & 0x8; - number |= size & 0x7; - - uint16_t len = write_variable_int(temp, number); - PRINTF("number %lu, more %u, size %u block[0] %u block[1] %u block[2] %u block[3] %u\n", - number, (uint16_t)more, (uint16_t)size, (uint16_t)temp[0], (uint16_t)temp[1], (uint16_t)temp[2], (uint16_t)temp[3]); - return coap_set_option(packet, Option_Type_Block, len, temp); -} - - -int -coap_set_header_uri(coap_packet_t* packet, char* uri) -{ - return coap_set_option(packet, Option_Type_Uri_Path, strlen(uri), (uint8_t*) uri); -} - -int -coap_set_header_etag(coap_packet_t* packet, uint8_t* etag, uint8_t size) -{ - return coap_set_option(packet, Option_Type_Etag, size, etag); -} - -void -coap_set_code(coap_packet_t* packet, status_code_t code) -{ - packet->code = (uint8_t)code; -} - -coap_method_t -coap_get_method(coap_packet_t* packet) -{ - return (coap_method_t)packet->code; -} - -void -coap_set_method(coap_packet_t* packet, coap_method_t method) -{ - packet->code = (uint8_t)method; -} - -static void send_request(coap_packet_t* request, struct uip_udp_conn *client_conn) -{ - char buf[MAX_PAYLOAD_LEN]; - int data_size = 0; - - data_size = serialize_packet(request, buf); - - 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)); - - PRINTF("Sending to: "); - PRINT6ADDR(&client_conn->ripaddr); - uip_udp_packet_send(client_conn, buf, data_size); -} - -static int -handle_incoming_data(void) -{ - int error=NO_ERROR; - char buf[MAX_PAYLOAD_LEN]; - - PRINTF("uip_datalen received %u \n",(uint16_t)uip_datalen()); - - char* data = (char *)uip_appdata + uip_ext_len; - uint16_t datalen = uip_datalen() - uip_ext_len; - - int data_size = 0; - - if (uip_newdata()) { - ((char *)data)[datalen] = 0; - PRINTF("Server received: '%s' (port:%u) from ", (char *)data, uip_htons(UIP_UDP_BUF->srcport)); - PRINT6ADDR(&UIP_IP_BUF->srcipaddr); - PRINTF("\n"); - - if (init_buffer(COAP_DATA_BUFF_SIZE)) { - coap_packet_t* request = (coap_packet_t*)allocate_buffer(sizeof(coap_packet_t)); - parse_message(request, (uint8_t*)data, datalen); - - uip_ipaddr_copy(&request->addr, &UIP_IP_BUF->srcipaddr); - - if (request->type != MESSAGE_TYPE_ACK) { - coap_packet_t* response = (coap_packet_t*)allocate_buffer(sizeof(coap_packet_t)); - init_response(request, response); - - if (service_cbk) { - service_cbk(request, response); - } - - data_size = serialize_packet(response, buf); - - } - delete_buffer(); - } else { - PRINTF("Memory Alloc Error\n"); - error = MEMORY_ALLOC_ERR; - /*FIXME : Crappy way of accessing TID of the incoming packet, fix it!*/ - coap_packet_t error_packet; - fill_error_packet(&error_packet,error, (data[2] << 8) + data[3]); - data_size = serialize_packet(&error_packet, buf); - } - - uip_ipaddr_copy(&server_conn->ripaddr, &UIP_IP_BUF->srcipaddr); - server_conn->rport = UIP_UDP_BUF->srcport; - - PRINTF("Responding with message size: %d\n",data_size); - uip_udp_packet_send(server_conn, buf, data_size); - /* Restore server connection to allow data from any node */ - memset(&server_conn->ripaddr, 0, sizeof(server_conn->ripaddr)); - server_conn->rport = 0; - } - - return error; -} - -process_event_t resource_changed_event; - -void -resource_changed(struct periodic_resource_t* resource) -{ - process_post(&coap_server, resource_changed_event, (process_data_t)resource); -} - - -/*---------------------------------------------------------------------------*/ - -PROCESS(coap_server, "Coap Server"); -PROCESS_THREAD(coap_server, ev, data) -{ - PROCESS_BEGIN(); - PRINTF("COAP SERVER\n"); - -/* if static routes are used rather than RPL */ -#if !UIP_CONF_IPV6_RPL && !defined (CONTIKI_TARGET_MINIMAL_NET) - set_global_address(); - configure_routing(); -#endif - - current_tid = random_rand(); - - resource_changed_event = process_alloc_event(); - - /* new connection with remote host */ - server_conn = udp_new(NULL, uip_htons(0), NULL); - udp_bind(server_conn, uip_htons(MOTE_SERVER_LISTEN_PORT)); - 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) { - handle_incoming_data(); - } else if (ev == resource_changed_event) { - periodic_resource_t* resource = (periodic_resource_t*)data; - PRINTF("resource_changed_event \n"); - - if (init_buffer(COAP_DATA_BUFF_SIZE)) { - coap_packet_t* request = (coap_packet_t*)allocate_buffer(sizeof(coap_packet_t)); - init_packet(request); - coap_set_code(request, COAP_GET); - request->tid = current_tid++; - coap_set_header_subscription_lifetime(request, resource->lifetime); - coap_set_header_uri(request, (char *)resource->resource->url); - if (resource->periodic_request_generator) { - resource->periodic_request_generator(request); - } - - if (!resource->client_conn) { - /*FIXME send port is fixed for now to 61616*/ - resource->client_conn = udp_new(&resource->addr, uip_htons(61616), NULL); - udp_bind(resource->client_conn, uip_htons(MOTE_CLIENT_LISTEN_PORT)); - } - - if (resource->client_conn) { - send_request(request, resource->client_conn); - } - - delete_buffer(); - } - } - } - - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ diff --git a/apps/rest-coap/coap-server.h b/apps/rest-coap/coap-server.h deleted file mode 100644 index 888d08721..000000000 --- a/apps/rest-coap/coap-server.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef COAPSERVER_H_ -#define COAPSERVER_H_ - -#define COAP_DATA_BUFF_SIZE 300 - -#include "contiki.h" -#include "coap-common.h" - -/*Declare process*/ -PROCESS_NAME(coap_server); - -#define MOTE_SERVER_LISTEN_PORT 61616 -#define MOTE_CLIENT_LISTEN_PORT 61617 - -void parse_message(coap_packet_t* packet, uint8_t* buf, uint16_t size); - -uint16_t coap_get_payload(coap_packet_t* packet, uint8_t** payload); -int coap_set_payload(coap_packet_t* packet, uint8_t* payload, uint16_t size); - -content_type_t coap_get_header_content_type(coap_packet_t* packet); -int coap_set_header_content_type(coap_packet_t* packet, content_type_t content_type); - -int coap_get_header_subscription_lifetime(coap_packet_t* packet, uint32_t* lifetime); -int coap_set_header_subscription_lifetime(coap_packet_t* packet, uint32_t lifetime); - -int coap_get_header_block(coap_packet_t* packet, block_option_t* block); -int coap_set_header_block(coap_packet_t* packet, uint32_t number, uint8_t more, uint8_t size); - -int coap_set_header_uri(coap_packet_t* packet, char* uri); -int coap_set_header_etag(coap_packet_t* packet, uint8_t* etag, uint8_t size); - -void coap_set_code(coap_packet_t* packet, status_code_t code); - -coap_method_t coap_get_method(coap_packet_t* packet); -void coap_set_method(coap_packet_t* packet, coap_method_t method); - -int coap_get_query_variable(coap_packet_t* packet, const char *name, char* output, uint16_t output_size); -int coap_get_post_variable(coap_packet_t* packet, const char *name, char* output, uint16_t output_size); - -header_option_t* coap_get_option(coap_packet_t* packet, option_type option_type); -int coap_set_option(coap_packet_t* packet, option_type option_type, uint16_t len, uint8_t* value); - -/*Type definition of the service callback*/ -typedef int (*service_callback) (coap_packet_t* request, coap_packet_t* response); - -/* - *Setter of the service callback, this callback will be called in case of HTTP request. - */ -void coap_set_service_callback(service_callback callback); - -struct periodic_resource_t; -void resource_changed(struct periodic_resource_t* resource); - -#endif /* COAPSERVER_H_ */ diff --git a/apps/rest-common/Makefile.rest-common b/apps/rest-common/Makefile.rest-common deleted file mode 100644 index 4ce0e5ac3..000000000 --- a/apps/rest-common/Makefile.rest-common +++ /dev/null @@ -1 +0,0 @@ -rest-common_src = rest.c rest-util.c buffer.c static-routing.c diff --git a/apps/rest-common/buffer.c b/apps/rest-common/buffer.c deleted file mode 100644 index df5f616a1..000000000 --- a/apps/rest-common/buffer.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * buffer.c - * - * Created on: Oct 19, 2010 - * Author: dogan - */ - -#include -#include -#include -#include "buffer.h" - -uint8_t* data_buffer; -uint16_t buffer_size; -uint16_t buffer_index; - -void -delete_buffer(void) -{ - if (data_buffer) { - free(data_buffer); - data_buffer = NULL; - buffer_index = 0; - buffer_size = 0; - } -} - -uint8_t* -init_buffer(uint16_t size) -{ - delete_buffer(); - data_buffer = (uint8_t*)malloc(size); - if (data_buffer) { - buffer_size = size; - } - buffer_index = 0; - - return data_buffer; -} - -uint8_t* -allocate_buffer(uint16_t size) -{ - uint8_t* buffer = NULL; - int rem = 0; - /*To get rid of alignment problems, always allocate even size*/ - rem = size % 4; - if (rem) { - size+=(4-rem); - } - if (buffer_index + size < buffer_size) { - buffer = data_buffer + buffer_index; - buffer_index += size; - } - - return buffer; -} - -uint8_t* -copy_to_buffer(void* data, uint16_t len) -{ - uint8_t* buffer = allocate_buffer(len); - if (buffer) { - memcpy(buffer, data, len); - } - - return buffer; -} - -uint8_t* -copy_text_to_buffer(char* text) -{ - uint8_t* buffer = allocate_buffer(strlen(text) + 1); - if (buffer) { - strcpy(buffer, text); - } - - return buffer; -} diff --git a/apps/rest-common/buffer.h b/apps/rest-common/buffer.h deleted file mode 100644 index dd72ac2cf..000000000 --- a/apps/rest-common/buffer.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * buffer.h - * - * Created on: Oct 19, 2010 - * Author: dogan - */ - -#ifndef BUFFER_H_ -#define BUFFER_H_ - -void delete_buffer(void); -uint8_t* init_buffer(uint16_t size); -uint8_t* allocate_buffer(uint16_t size); -uint8_t* copy_to_buffer(void* data, uint16_t len); -uint8_t* copy_text_to_buffer(char* text); - -#endif /* BUFFER_H_ */ diff --git a/apps/rest-common/rest-util.c b/apps/rest-common/rest-util.c deleted file mode 100644 index b7e7f118e..000000000 --- a/apps/rest-common/rest-util.c +++ /dev/null @@ -1,118 +0,0 @@ -#include /*for size_t*/ -#include /*for isxdigit*/ -#include - -#include "contiki-net.h" - -/*Copied from mangoose http server*/ -size_t -decode(const char *src, size_t srclen, char *dst, size_t dstlen, int is_form) -{ - size_t i, j; - int a, b; -#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W') - - for (i = j = 0; i < srclen && j < dstlen - 1; i++, j++) { - if (src[i] == '%' && - isxdigit(* (unsigned char *) (src + i + 1)) && - isxdigit(* (unsigned char *) (src + i + 2))) { - a = tolower(* (unsigned char *) (src + i + 1)); - b = tolower(* (unsigned char *) (src + i + 2)); - dst[j] = ((HEXTOI(a) << 4) | HEXTOI(b)) & 0xff; - i += 2; - } else if (is_form && src[i] == '+') { - dst[j] = ' '; - } else { - dst[j] = src[i]; - } - } - - dst[j] = '\0'; /* Null-terminate the destination */ - - return ( i == srclen ); -} - -/*Copied from mangoose http server*/ -int -get_variable(const char *name, const char *buffer, size_t buflen, char* output, size_t output_len, int decode_type) -{ - const char *start = NULL, *end = NULL, *end_of_value; - size_t var_len = 0; - - /*initialize the output buffer first*/ - *output = 0; - - var_len = strlen(name); - end = buffer + buflen; - - for (start = buffer; start + var_len < end; start++){ - if ((start == buffer || start[-1] == '&') && start[var_len] == '=' && - ! strncmp(name, start, var_len)) { - /* Point p to variable value */ - start += var_len + 1; - - /* Point s to the end of the value */ - end_of_value = (const char *) memchr(start, '&', end - start); - if (end_of_value == NULL) { - end_of_value = end; - } - - return decode(start, end_of_value - start, output, output_len, decode_type); - } - } - - return 0; -} - -uint32_t -read_int(uint8_t *buf, uint8_t size) -{ - uint32_t data = 0; - - if (size >= 1 && size <= 4) { - uint8_t *p = (uint8_t *)&data; - memcpy(p + 4 - size, buf, size); - } - - return uip_ntohl(data); -} - - -int -write_int(uint8_t *buf, uint32_t data, uint8_t size) -{ - int success = 0; - - if (size >= 1 && size <= 4) { - data = uip_htonl(data); - memcpy(buf, ((char*)(&data)) + 4 - size, size); - success = size; - } - - return success; -} - -int -write_variable_int(uint8_t *buf, uint32_t data) -{ - uint8_t size = 4; - if (data <= 0xFF) { - size = 1; - } else if (data <= 0xFFFF) { - size = 2; - } else if (data <= 0xFFFFFF) { - size = 3; - } - return write_int(buf, data, size); -} - -uint16_t log_2(uint16_t value) -{ - uint16_t result = 0; - do { - value = value >> 1; - result++; - } while (value); - - return result ? result - 1 : result; -} diff --git a/apps/rest-common/rest-util.h b/apps/rest-common/rest-util.h deleted file mode 100644 index 421c8b3ea..000000000 --- a/apps/rest-common/rest-util.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * rest-util.h - * - * Created on: Oct 26, 2010 - * Author: dogan - */ - -#ifndef RESTUTIL_H_ -#define RESTUTIL_H_ - -size_t decode(const char *src, size_t srclen, char *dst, size_t dstlen, int is_form); -int get_variable(const char *name, const char *buffer, size_t buflen, char* output, size_t output_len, int decode_type); - -uint32_t read_int(uint8_t *buf, uint8_t size); -int write_int(uint8_t *buf, uint32_t data, uint8_t size); -int write_variable_int(uint8_t *buf, uint32_t data); - -uint16_t log_2(uint16_t value); - -#endif /* RESTUTIL_H_ */ diff --git a/apps/rest-common/rest.c b/apps/rest-common/rest.c deleted file mode 100644 index b28ae1bd5..000000000 --- a/apps/rest-common/rest.c +++ /dev/null @@ -1,333 +0,0 @@ -#include "contiki.h" -#include /*for string operations in match_addresses*/ -#include "rest.h" -#include "buffer.h" - -#define DEBUG 0 -#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 it is possible to define some of the rest functions as MACROs rather than functions full of ifdefs.*/ - -PROCESS_NAME(rest_manager_process); - -LIST(restful_services); -LIST(restful_periodic_services); - -void -rest_init(void) -{ - list_init(restful_services); - -#ifdef WITH_COAP - coap_set_service_callback(rest_invoke_restful_service); -#else /*WITH_COAP*/ - http_set_service_callback(rest_invoke_restful_service); -#endif /*WITH_COAP*/ - - /*Start rest framework process*/ - process_start(&rest_manager_process, NULL); -} - -void -rest_activate_resource(resource_t* resource) -{ - /*add it to the restful web service link list*/ - list_add(restful_services, resource); -} - -void -rest_activate_periodic_resource(periodic_resource_t* periodic_resource) -{ - list_add(restful_periodic_services, periodic_resource); - rest_activate_resource(periodic_resource->resource); -} - -void -rest_set_user_data(resource_t* resource, void* user_data) -{ - resource->user_data = user_data; -} - -void* -rest_get_user_data(resource_t* resource) -{ - return resource->user_data; -} - -void -rest_set_pre_handler(resource_t* resource, restful_pre_handler pre_handler) -{ - resource->pre_handler = pre_handler; -} - -void -rest_set_post_handler(resource_t* resource, restful_post_handler post_handler) -{ - resource->post_handler = post_handler; -} - -list_t -rest_get_resources(void) -{ - return restful_services; -} - -void -rest_set_response_status(RESPONSE* response, status_code_t status) -{ -#ifdef WITH_COAP - coap_set_code(response, status); -#else /*WITH_COAP*/ - http_set_status(response, status); -#endif /*WITH_COAP*/ -} - -#ifdef WITH_COAP -static method_t coap_to_rest_method(coap_method_t method) -{ - return (method_t)(1 << (method - 1)); -} - -static coap_method_t rest_to_coap_method(method_t method) -{ - coap_method_t coap_method = COAP_GET; - switch (method) { - case METHOD_GET: - coap_method = COAP_GET; - break; - case METHOD_POST: - coap_method = COAP_POST; - break; - case METHOD_PUT: - coap_method = COAP_PUT; - break; - case METHOD_DELETE: - coap_method = COAP_DELETE; - break; - default: - break; - } - return coap_method; -} -#endif /*WITH_COAP*/ - -method_t -rest_get_method_type(REQUEST* request) -{ -#ifdef WITH_COAP - return coap_to_rest_method(coap_get_method(request)); -#else - return (method_t)(request->request_type); -#endif -} - -/*Only defined for COAP for now.*/ -#ifdef WITH_COAP -void -rest_set_method_type(REQUEST* request, method_t method) -{ - coap_set_method(request, rest_to_coap_method(method)); -} -#endif /*WITH_COAP*/ - -void -rest_set_response_payload(RESPONSE* response, uint8_t* payload, uint16_t size) -{ -#ifdef WITH_COAP - coap_set_payload(response, payload, size); -#else - http_set_res_payload(response, payload, size); -#endif /*WITH_COAP*/ -} - -/*Only defined for COAP for now.*/ -#ifdef WITH_COAP -void -rest_set_request_payload(REQUEST* request, uint8_t* payload, uint16_t size) -{ - coap_set_payload(request, payload, size); -} -#endif /*WITH_COAP*/ - -int -rest_get_query_variable(REQUEST* request, const char *name, char* output, uint16_t output_size) -{ -#ifdef WITH_COAP - return coap_get_query_variable(request, name, output, output_size); -#else - return http_get_query_variable(request, name, output, output_size); -#endif /*WITH_COAP*/ -} - -int -rest_get_post_variable(REQUEST* request, const char *name, char* output, uint16_t output_size) -{ -#ifdef WITH_COAP - return coap_get_post_variable(request, name, output, output_size); -#else - return http_get_post_variable(request, name, output, output_size); -#endif /*WITH_COAP*/ -} - -content_type_t -rest_get_header_content_type(REQUEST* request) -{ -#ifdef WITH_COAP - return coap_get_header_content_type(request); -#else - return http_get_header_content_type(request); -#endif /*WITH_COAP*/ -} - -int -rest_set_header_content_type(RESPONSE* response, content_type_t content_type) -{ -#ifdef WITH_COAP - return coap_set_header_content_type(response, content_type); -#else - return http_set_res_header(response, HTTP_HEADER_NAME_CONTENT_TYPE, http_get_content_type_string(content_type), 1); -#endif /*WITH_COAP*/ - -} - -int -rest_set_header_etag(RESPONSE* response, uint8_t* etag, uint8_t size) -{ -#ifdef WITH_COAP - return coap_set_header_etag(response, etag, size); -#else - /*FIXME for now etag should be a "/0" ending string for http part*/ - char temp_etag[10]; - memcpy(temp_etag, etag, size); - temp_etag[size] = 0; - return http_set_res_header(response, HTTP_HEADER_NAME_ETAG, temp_etag, 1); -#endif /*WITH_COAP*/ -} - -int -rest_invoke_restful_service(REQUEST* request, RESPONSE* response) -{ - int found = 0; - const char* url = request->url; - uint16_t url_len = request->url_len; - - PRINTF("rest_invoke_restful_service url %s url_len %d -->\n", url, url_len); - - resource_t* resource = NULL; - - for (resource = (resource_t*)list_head(restful_services); resource; resource = resource->next) { - /*if the web service handles that kind of requests and urls matches*/ - if (url && strlen(resource->url) == url_len && strncmp(resource->url, url, url_len) == 0){ - found = 1; - method_t method = rest_get_method_type(request); - - PRINTF("method %u, resource->methods_to_handle %u\n", (uint16_t)method, resource->methods_to_handle); - - if (resource->methods_to_handle & method) { - - /*FIXME Need to move somewhere else*/ - #ifdef WITH_COAP - uint32_t lifetime = 0; - if (coap_get_header_subscription_lifetime(request, &lifetime)) { - PRINTF("Lifetime %lu\n", lifetime); - - periodic_resource_t* periodic_resource = NULL; - for (periodic_resource = (periodic_resource_t*)list_head(restful_periodic_services); - periodic_resource; - periodic_resource = periodic_resource->next) { - if (periodic_resource->resource == resource) { - PRINTF("Periodic Resource Found\n"); - PRINT6ADDR(&request->addr); - periodic_resource->lifetime = lifetime; - stimer_set(periodic_resource->lifetime_timer, lifetime); - uip_ipaddr_copy(&periodic_resource->addr, &request->addr); - } - } - } - #endif /*WITH_COAP*/ - - /*call pre handler if it exists*/ - if (!resource->pre_handler || resource->pre_handler(request, response)) { - /* call handler function*/ - resource->handler(request, response); - - /*call post handler if it exists*/ - if (resource->post_handler) { - resource->post_handler(request, response); - } - } - } else { - rest_set_response_status(response, METHOD_NOT_ALLOWED_405); - } - break; - } - } - - if (!found) { - rest_set_response_status(response, NOT_FOUND_404); - } - - return found; -} - -PROCESS(rest_manager_process, "Rest Process"); - -PROCESS_THREAD(rest_manager_process, ev, data) -{ - PROCESS_BEGIN(); - - /*start the coap or http server*/ - process_start(SERVER_PROCESS, NULL); - - PROCESS_PAUSE(); - - /*Periodic resources are only available to COAP implementation*/ -#if 0 -#ifdef WITH_COAP - periodic_resource_t* periodic_resource = NULL; - for (periodic_resource = (periodic_resource_t*)list_head(restful_periodic_services); periodic_resource; periodic_resource = periodic_resource->next) { - if (periodic_resource->period) { - PRINTF("Set timer for Res: %s to %lu\n", periodic_resource->resource->url, periodic_resource->period); - etimer_set(periodic_resource->handler_cb_timer, periodic_resource->period); - } - } - - while(1) { - PROCESS_WAIT_EVENT(); - if (ev == PROCESS_EVENT_TIMER) { - for (periodic_resource = (periodic_resource_t*)list_head(restful_periodic_services);periodic_resource;periodic_resource = periodic_resource->next) { - if (periodic_resource->period && etimer_expired(periodic_resource->handler_cb_timer)) { - PRINTF("Etimer expired for %s (period:%lu life:%lu)\n", periodic_resource->resource->url, periodic_resource->period, periodic_resource->lifetime); - /*call the periodic handler function if exists*/ - if (periodic_resource->periodic_handler) { - if ((periodic_resource->periodic_handler)(periodic_resource->resource)) { - PRINTF("RES CHANGE\n"); - if (!stimer_expired(periodic_resource->lifetime_timer)) { - PRINTF("TIMER NOT EXPIRED\n"); - resource_changed(periodic_resource); - periodic_resource->lifetime = stimer_remaining(periodic_resource->lifetime_timer); - } else { - periodic_resource->lifetime = 0; - } - } - - PRINTF("%s lifetime %lu (%lu) expired %d\n", periodic_resource->resource->url, stimer_remaining(periodic_resource->lifetime_timer), periodic_resource->lifetime, stimer_expired(periodic_resource->lifetime_timer)); - } - etimer_reset(periodic_resource->handler_cb_timer); - } - } - } - } -#endif /*WITH_COAP*/ -#endif - PROCESS_END(); -} diff --git a/apps/rest-common/rest.h b/apps/rest-common/rest.h deleted file mode 100644 index 2cf2ca7f1..000000000 --- a/apps/rest-common/rest.h +++ /dev/null @@ -1,179 +0,0 @@ -#ifndef REST_H_ -#define REST_H_ - -/*includes*/ -#include "contiki.h" -#include "contiki-lib.h" - -#ifdef WITH_COAP - #include "coap-common.h" -#include "coap-server.h" - #define REQUEST coap_packet_t - #define RESPONSE coap_packet_t - #define SERVER_PROCESS (&coap_server) -#else /*WITH_COAP*/ - /*WITH_HTTP*/ - #include "http-common.h" - #include "http-server.h" - #define REQUEST http_request_t - #define RESPONSE http_response_t - #define SERVER_PROCESS (&http_server) -#endif /*WITH_COAP*/ - -struct resource_t; - -/*REST method types*/ -typedef enum { - METHOD_GET = (1 << 0), - METHOD_POST = (1 << 1), - METHOD_PUT = (1 << 2), - METHOD_DELETE = (1 << 3) -} method_t; - -/*Signature of handler functions*/ -typedef void (*restful_handler) (REQUEST* request, RESPONSE* response); -typedef int (*restful_pre_handler) (REQUEST* request, RESPONSE* response); -typedef void (*restful_post_handler) (REQUEST* request, RESPONSE* response); - -typedef int (*restful_periodic_handler) (struct resource_t* resource); -typedef void (*restful_periodic_request_generator) (REQUEST* request); - -/* - * Data structure representing a resource in REST. - */ -struct resource_t { - struct resource_t *next; /*points to next resource defined*/ - method_t methods_to_handle; /*handled HTTP methods*/ - const char* url; /*handled URL*/ - restful_handler handler; /*handler function*/ - restful_pre_handler pre_handler; /*to be called before handler, may perform initializations*/ - restful_post_handler post_handler; /*to be called after handler, may perform finalizations (cleanup, etc)*/ - void* user_data; /*pointer to user specific data*/ -}; -typedef struct resource_t resource_t; - -struct periodic_resource_t { - struct periodic_resource_t *next; - resource_t *resource; - uint32_t period; - struct etimer* handler_cb_timer; - struct stimer* lifetime_timer; - restful_periodic_handler periodic_handler; - restful_periodic_request_generator periodic_request_generator; - uint32_t lifetime; - uip_ipaddr_t addr; - struct uip_udp_conn *client_conn; -}; -typedef struct periodic_resource_t periodic_resource_t; - -/* - * Macro to define a Resource - * Resources are statically defined for the sake of efficiency and better memory management. - */ -#define RESOURCE(name, methods_to_handle, url) \ -void name##_handler(REQUEST*, RESPONSE*); \ -resource_t resource_##name = {NULL, methods_to_handle, url, name##_handler, NULL, NULL, NULL} - -/* - * Macro to define a Periodic Resource - */ -#define PERIODIC_RESOURCE(name, methods_to_handle, url, period) \ -RESOURCE(name, methods_to_handle, url); \ -int name##_periodic_handler(resource_t*); \ -void name##_periodic_request_generator(REQUEST*); \ -struct etimer handler_cb_timer_##name; \ -struct stimer lifetime_timer_##name; \ -periodic_resource_t periodic_resource_##name = {NULL, &resource_##name, period, &handler_cb_timer_##name, &lifetime_timer_##name, name##_periodic_handler, name##_periodic_request_generator, 0} - - -/* - * Initializes REST framework and starts HTTP or COAP process - */ -void rest_init(void); - -/* - * Resources wanted to be accessible should be activated with the following code. - */ -void rest_activate_resource(resource_t* resource); - -void rest_activate_periodic_resource(periodic_resource_t* periodic_resource); - -/* - * To be called by HTTP/COAP server as a callback function when a new service request appears. - * This function dispatches the corresponding RESTful service. - */ -int rest_invoke_restful_service(REQUEST* request, RESPONSE* response); - -/* - * Returns the resource list - */ -list_t rest_get_resources(void); - -/* - * Returns query variable in the URL. - * Returns true if the variable found, false otherwise. - * Variable is put in the buffer provided. - */ -int rest_get_query_variable(REQUEST* request, const char *name, char* output, uint16_t output_size); - -/* - * Returns variable in the Post Data/Payload. - * Returns true if the variable found, false otherwise. - * Variable is put in the buffer provided. - */ -int rest_get_post_variable(REQUEST* request, const char *name, char* output, uint16_t output_size); - -method_t rest_get_method_type(REQUEST* request); -void rest_set_method_type(REQUEST* request, method_t method); - -/* - * Getter for the request content type - */ -content_type_t rest_get_header_content_type(REQUEST* request); - -/* - * Setter for the response content type - */ -int rest_set_header_content_type(RESPONSE* response, content_type_t content_type); - -/* - * Setter for the response etag header - */ -int rest_set_header_etag(RESPONSE* response, uint8_t* etag, uint8_t size); - -/* - * Setter for the status code (200, 201, etc) of the response. - */ -void rest_set_response_status(RESPONSE* response, status_code_t status); - -/* - * Setter for the payload of the request and response - */ -void rest_set_request_payload(RESPONSE* response, uint8_t* payload, uint16_t size); -void rest_set_response_payload(RESPONSE* response, uint8_t* payload, uint16_t size); - -/* - * Getter method for user specific data. - */ -void* rest_get_user_data(resource_t* resource); - -/* - * Setter method for user specific data. - */ -void rest_set_user_data(resource_t* resource, void* user_data); - -/* - * Sets the pre handler function of the Resource. - * If set, this function will be called just before the original handler function. - * Can be used to setup work before resource handling. - */ -void rest_set_pre_handler(resource_t* resource, restful_pre_handler pre_handler); - -/* - * Sets the post handler function of the Resource. - * If set, this function will be called just after the original handler function. - * Can be used to do cleanup (deallocate memory, etc) after resource handling. - */ -void rest_set_post_handler(resource_t* resource, restful_post_handler post_handler); - -#endif /*REST_H_*/ diff --git a/apps/rest-common/static-routing.c b/apps/rest-common/static-routing.c deleted file mode 100644 index 1d297b2db..000000000 --- a/apps/rest-common/static-routing.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * static-routing.c - * - * Created on: Oct 12, 2010 - * Author: dogan - */ - -#include "static-routing.h" - -#if !defined (CONTIKI_TARGET_MINIMAL_NET) /* Any other targets will be added here (&& ! defined (OTHER))*/ - -#define DEBUG 0 -#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 - - -#if !UIP_CONF_IPV6_RPL -#include "contiki-net.h" -#include "sys/node-id.h" - -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); -} - -void configure_routing(void) -{ - PRINTF("configure_routing\n"); - - if (node_id < 10) { /*COOJA*/ - /*Go to desktop machine over border router*/ - ADD_ROUTE(DESKTOP_MACHINE_ID, COOJA_BORDER_ROUTER_ID); - } else { /*SKY*/ - if (node_id < 20) { /*First hops (ids between 10-20)*/ - /*Go to desktop machine over border router*/ - ADD_ROUTE(DESKTOP_MACHINE_ID, BORDER_ROUTER_ID); - } - - switch(node_id) { - case 12: - ADD_ROUTE(22, 22); /*Go to next hop over the local address of next hop*/ - break; - case 13: - ADD_ROUTE(23, 23); /*Go to next hop over the local address of next hop*/ - break; - - case 22: - ADD_ROUTE(0, 12); /*Go to desktop machine over the corresponding first hop*/ - break; - case 23: - ADD_ROUTE(0, 13); /*Go to desktop machine over the corresponding first hop*/ - break; - default: - break; - } - } -} -#endif /*!UIP_CONF_IPV6_RPL*/ -#endif /*CONTIKI_TARGET_MINIMAL_NET*/ diff --git a/apps/rest-common/static-routing.h b/apps/rest-common/static-routing.h deleted file mode 100644 index c4b757893..000000000 --- a/apps/rest-common/static-routing.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * static-routing.h - * - * Created on: Oct 12, 2010 - * Author: dogan - */ - -#ifndef STATICROUTING_H_ -#define STATICROUTING_H_ - -#if !defined (CONTIKI_TARGET_MINIMAL_NET) -#define NODE_IP(nodeid,type,ipaddr) NODE_##nodeid##_##type(ipaddr) - -/*desktop machine*/ -#define DESKTOP_MACHINE_ID 0 -#define NODE_0_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0x0001) - -/*Cooja Nodes*/ -#define COOJA_BORDER_ROUTER_ID 1 -#define NODE_1_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7401, 0x0001, 0x0101) -#define NODE_1_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7401, 0x0001, 0x0101) - -#define NODE_2_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7402, 0x0002, 0x0202) -#define NODE_2_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7402, 0x0002, 0x0202) - -#define NODE_3_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7403, 0x0003, 0x0303) -#define NODE_3_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7403, 0x0003, 0x0303) - -#define NODE_6_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7406, 0x0006, 0x0606) -#define NODE_6_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7406, 0x0006, 0x0606) - -/*real nodes*/ -#define BORDER_ROUTER_ID 11 -#define NODE_11_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7400, 0x116e, 0xd5f1) -#define NODE_11_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7400, 0x116e, 0xd5f1) - -#define NODE_12_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7400, 0x1160, 0xf95a) -#define NODE_12_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7400, 0x1160, 0xf95a) - -#define NODE_13_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7400, 0x117d, 0x3575) -#define NODE_13_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7400, 0x117d, 0x3575) - -#define NODE_22_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7400, 0x116e, 0xc0f6) -#define NODE_22_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7400, 0x116e, 0xc0f6) - -#define NODE_23_GLOBAL(ipaddr) uip_ip6addr(ipaddr, 0xaaaa, 0, 0, 0, 0x0212, 0x7400, 0x117d, 0x0d5a) -#define NODE_23_LOCAL(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7400, 0x117d, 0x0d5a) - -#define ADD_ROUTE(node_global,node_local)\ -do{\ - uip_ipaddr_t ipaddr_local, ipaddr_global;\ - NODE_IP(node_global, GLOBAL, &ipaddr_global);\ - NODE_IP(node_local, LOCAL, &ipaddr_local);\ - uip_ds6_route_add(&ipaddr_global, 128, &ipaddr_local);\ -}while(0) - -void set_global_address(void); -void configure_routing(void); - -#endif /*CONTIKI_TARGET_MINIMAL_NET*/ -#endif /* STATICROUTING_H_ */ diff --git a/apps/rest-engine/rest-engine.h b/apps/rest-engine/rest-engine.h index 3a2848f58..41e181c33 100644 --- a/apps/rest-engine/rest-engine.h +++ b/apps/rest-engine/rest-engine.h @@ -62,10 +62,6 @@ #define REST_MAX_CHUNK_SIZE 64 #endif -#ifndef MIN -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif /* MIN */ - struct resource_s; struct periodic_resource_s; diff --git a/apps/rest-http/Makefile.rest-http b/apps/rest-http/Makefile.rest-http deleted file mode 100644 index 3d946d2d9..000000000 --- a/apps/rest-http/Makefile.rest-http +++ /dev/null @@ -1,4 +0,0 @@ -rest-http_src = http-common.c http-server.c - -APPS += rest-common -include $(CONTIKI)/apps/rest-common/Makefile.rest-common diff --git a/apps/rest-http/http-common.c b/apps/rest-http/http-common.c deleted file mode 100644 index 0d3deefa3..000000000 --- a/apps/rest-http/http-common.c +++ /dev/null @@ -1,29 +0,0 @@ -#include "http-common.h" - -/*needed for web services giving all path (http://172.16.79.0/services/light1) - * instead relative (/services/light1) in HTTP request. Ex: Restlet lib.*/ -const char* http_string = "http"; - -/*HTTP method strings*/ -const char* http_get_string = "GET"; -const char* http_head_string = "HEAD"; -const char* http_post_string = "POST"; -const char* http_put_string = "PUT"; -const char* http_delete_string = "DELETE"; - -const char* httpv1_1 = "HTTP/1.1"; -const char* line_end = "\r\n"; -const char* contiki = "Contiki"; -const char* close = "close"; - -/*header names*/ -const char* HTTP_HEADER_NAME_CONTENT_TYPE = "Content-Type"; -const char* HTTP_HEADER_NAME_CONTENT_LENGTH = "Content-Length"; -const char* HTTP_HEADER_NAME_LOCATION = "Location"; -const char* HTTP_HEADER_NAME_CONNECTION = "Connection"; -const char* HTTP_HEADER_NAME_SERVER = "Server"; -const char* HTTP_HEADER_NAME_HOST = "Host"; -const char* HTTP_HEADER_NAME_IF_NONE_MATCH = "If-None-Match"; -const char* HTTP_HEADER_NAME_ETAG = "ETag"; - -const char* header_delimiter = ": "; diff --git a/apps/rest-http/http-common.h b/apps/rest-http/http-common.h deleted file mode 100644 index e70115c2b..000000000 --- a/apps/rest-http/http-common.h +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef HTTPCOMMON_H_ -#define HTTPCOMMON_H_ - -/*includes*/ -#include "contiki.h" -#include "contiki-net.h" - -/*current state of the request, waiting: handling request, output: sending response*/ -#define STATE_WAITING 0 -#define STATE_OUTPUT 1 - -/*definitions of the line ending characters*/ -#define LINE_FEED_CHAR '\n' -#define CARRIAGE_RETURN_CHAR '\r' - -/*needed for web services giving all path (http://172.16.79.0/services/light1) - * instead relative (/services/light1) in HTTP request. Ex: Restlet lib. does it*/ -extern const char* http_string; - -/*HTTP method strings*/ -extern const char* http_get_string; -extern const char* http_head_string; -extern const char* http_post_string; -extern const char* http_put_string; -extern const char* http_delete_string; - -extern const char* httpv1_1; -extern const char* line_end; -extern const char* contiki; -extern const char* close; - -/*header names*/ -extern const char* HTTP_HEADER_NAME_CONTENT_TYPE; -extern const char* HTTP_HEADER_NAME_CONTENT_LENGTH; -extern const char* HTTP_HEADER_NAME_LOCATION; -extern const char* HTTP_HEADER_NAME_CONNECTION; -extern const char* HTTP_HEADER_NAME_SERVER; -extern const char* HTTP_HEADER_NAME_HOST; -extern const char* HTTP_HEADER_NAME_IF_NONE_MATCH; -extern const char* HTTP_HEADER_NAME_ETAG; - -extern const char* header_delimiter; - - -/*Configuration parameters*/ -#define HTTP_PORT 8080 -#define HTTP_DATA_BUFF_SIZE 600 -#define INCOMING_DATA_BUFF_SIZE 102 /*100+2, 100 = max url len, 2 = space char+'\0'*/ - -/*HTTP method types*/ -typedef enum { - HTTP_METHOD_GET = (1 << 0), - HTTP_METHOD_POST = (1 << 1), - HTTP_METHOD_PUT = (1 << 2), - HTTP_METHOD_DELETE = (1 << 3) -} http_method_t; - -//DY : FIXME right now same enum names with COAP with different values. Will this work fine? -typedef enum { - OK_200 = 200, - CREATED_201 = 201, - NOT_MODIFIED_304 = 304, - BAD_REQUEST_400 = 400, - NOT_FOUND_404 = 404, - METHOD_NOT_ALLOWED_405 = 405, - REQUEST_URI_TOO_LONG_414 = 414, - UNSUPPORTED_MADIA_TYPE_415 = 415, - INTERNAL_SERVER_ERROR_500 = 500, - BAD_GATEWAY_502 = 502, - SERVICE_UNAVAILABLE_503 = 503, - GATEWAY_TIMEOUT_504 = 504 -} status_code_t; - -typedef enum { - TEXT_PLAIN, - TEXT_XML, - TEXT_CSV, - TEXT_HTML, - APPLICATION_XML, - APPLICATION_EXI, - APPLICATION_JSON, - APPLICATION_LINK_FORMAT, - APPLICATION_WWW_FORM, - UNKNOWN_CONTENT_TYPE -} content_type_t; - -/*Header type*/ -struct http_header_t { - struct http_header_t* next; - char* name; - char* value; -}; -typedef struct http_header_t http_header_t; - -/*This structure contains information about the HTTP request.*/ -struct http_request_t { - char* url; - uint16_t url_len; - http_method_t request_type; /* GET, POST, etc */ - char* query; - uint16_t query_len; - http_header_t* headers; - uint16_t payload_len; - uint8_t* payload; -}; -typedef struct http_request_t http_request_t; - -/*This structure contains information about the HTTP response.*/ -struct http_response_t { - status_code_t status_code; - char* status_string; - http_header_t* headers; - uint16_t payload_len; - uint8_t* payload; -}; -typedef struct http_response_t http_response_t; - -/*This structure contains information about the TCP Connection.*/ -typedef struct { - struct psock sin, sout; /*Protosockets for incoming and outgoing communication*/ - struct pt outputpt; - char inputbuf[INCOMING_DATA_BUFF_SIZE]; /*to put incoming data in*/ - uint8_t state; - http_request_t request; - http_response_t response; -} connection_state_t; - -/*error definitions*/ -typedef enum { - HTTP_NO_ERROR, - - /*Memory errors*/ - HTTP_MEMORY_ALLOC_ERR, - HTTP_MEMORY_BOUNDARY_EXCEEDED, - - /*specific errors*/ - HTTP_XML_NOT_VALID, - HTTP_SOAP_MESSAGE_NOT_VALID, - HTTP_URL_TOO_LONG, - HTTP_URL_INVALID -} http_error_t; - -#endif /*HTTPCOMMON_H_*/ diff --git a/apps/rest-http/http-server.c b/apps/rest-http/http-server.c deleted file mode 100644 index 256e37904..000000000 --- a/apps/rest-http/http-server.c +++ /dev/null @@ -1,653 +0,0 @@ -#include -#include /*for atoi*/ -#include -#include "contiki.h" - -#include "http-server.h" -#include "buffer.h" -#include "rest-util.h" - -#if !UIP_CONF_IPV6_RPL && !defined (CONTIKI_TARGET_MINIMAL_NET) -#include "static-routing.h" -#endif - -#define DEBUG 0 -#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 - -static void -init_response(http_response_t* response) -{ - response->status_code = OK_200; - response->status_string = NULL; - response->headers = NULL; - response->payload = NULL; - response->payload_len = 0; -} - -static void -init_request(http_request_t* request) -{ - request->request_type = 0; - request->url = NULL; - request->url_len = 0; - request->query = NULL; - request->query_len = 0; - request->headers = NULL; - request->payload = NULL; - request->payload_len = 0; -} - -/** - * Initializes the connection state by clearing out the data structures - */ -static void -init_connection(connection_state_t* conn_state) -{ - conn_state->state = STATE_WAITING; - - init_request(&conn_state->request); - init_response(&conn_state->response); -} - -void -http_set_status(http_response_t* response, status_code_t status) -{ - response->status_code = status; -} - -static http_header_t* -allocate_header(uint16_t variable_len) -{ - PRINTF("sizeof http_header_t %u variable size %u\n", sizeof(http_header_t), variable_len); - uint8_t* buffer = allocate_buffer(sizeof(http_header_t) + variable_len); - if (buffer) { - http_header_t* option = (http_header_t*) buffer; - option->next = NULL; - option->name = NULL; - option->value = buffer + sizeof(http_header_t); - return option; - } - - return NULL; -} - -int -http_set_res_header(http_response_t* response, const char* name, const char* value, int copy) -{ - PRINTF("http_set_res_header (copy:%d) %s:%s\n", copy, name, value); - uint16_t size = 0; - http_header_t* current_header = NULL; - http_header_t* head = NULL; - - if (copy) { - size += strlen(value) + 1; - } - - current_header = allocate_header(size); - - if (current_header) { - current_header->name = (char*)name; - if (copy) { - strcpy(current_header->value, value); - } else { - current_header->value = (char*)value; - } - - head = response->headers; - response->headers = current_header; - if (head) { - current_header->next = head; - } - - return 1; - } - - return 0; -} - -static const char* is_request_hdr_needed(const char* header_name) -{ - const char* header = NULL; - /*FIXME add needed headers here*/ - if (strcmp(header_name, HTTP_HEADER_NAME_CONTENT_LENGTH) == 0) { - header = HTTP_HEADER_NAME_CONTENT_LENGTH; - } else if (strcmp(header_name, HTTP_HEADER_NAME_CONTENT_TYPE) == 0) { - header = HTTP_HEADER_NAME_CONTENT_TYPE; - } - - return header; -} - -static service_callback service_cbk = NULL; - -void -http_set_service_callback(service_callback callback) -{ - service_cbk = callback; -} - -const char* content_types[] = { - "text/plain", - "text/xml", - "text/csv", - "text/html", - "application/xml", - "application/exi", - "application/json", - "application/link-format", - "application/x-www-form-urlencoded", -}; - -const char* -http_get_content_type_string(content_type_t content_type) -{ - return content_types[content_type]; -} - -char* -get_default_status_string(status_code_t status_code) -{ - char* value = NULL; - switch(status_code) { - case 200: - value = "OK"; - break; - case 201: - value = "Created"; - break; - case 202: - value = "Accepted"; - break; - case 204: - value = "No Content"; - break; - case 304: - value = "Not Modified"; - break; - case 400: - value = "Bad Request" ; - break; - case 404: - value = "Not Found" ; - break; - case 405: - value = "Method Not Allowed" ; - break; - case 406: - value = "Not Acceptable" ; - break; - case 414: - value = "Request-URI Too Long" ; - break; - case 415: - value = "Unsupported Media Type" ; - break; - case 500: - value = "Internal Server Error" ; - break; - case 501: - value = "Not Implemented" ; - break; - case 503: - value = "Service Unavailable" ; - break; - /*FIXME : will be removed later, put to catch the unhandled statuses.*/ - default: - value = "$$BUG$$"; - break; - } - - return value; -} - -int -http_get_query_variable(http_request_t* request, const char *name, char* output, uint16_t output_size) -{ - if (request->query) { - return get_variable(name, request->query, request->query_len, output, output_size, 0); - } - - return 0; -} - -int -http_get_post_variable(http_request_t* request, const char *name, char* output, uint16_t output_size) -{ - if (request->payload) { - return get_variable(name, request->payload, request->payload_len, output, output_size, 1); - } - - return 0; -} - -static int -is_method_handled(connection_state_t* conn_state, const char* method) -{ - /*other method types can be added here if needed*/ - if(strncmp(method, http_get_string, 3) == 0) { - conn_state->request.request_type = HTTP_METHOD_GET; - } else if (strncmp(method, http_post_string, 4) == 0) { - conn_state->request.request_type = HTTP_METHOD_POST; - } else if (strncmp(method, http_put_string, 3) == 0) { - conn_state->request.request_type = HTTP_METHOD_PUT; - } else if (strncmp(method, http_delete_string, 3) == 0) { - conn_state->request.request_type = HTTP_METHOD_DELETE; - } else { - PRINTF("No Method supported : %s\nstate : %d\n", conn_state->inputbuf, conn_state->state); - return 0; - } - - return 1; -} - -static int -parse_url(connection_state_t* conn_state, char* url) -{ - int error = HTTP_NO_ERROR; - int full_url_path = 0; - /*even for default index.html there is / Ex: GET / HTTP/1.1*/ - if (url[0] != '/') { - /*if url is complete (http://...) rather than relative*/ - if (strncmp(url, http_string, 4) != 0 ) { - PRINTF("Url not valid : %s \n",url); - error = HTTP_URL_INVALID; - } else { - full_url_path = 1; - } - } - - if (error == HTTP_NO_ERROR) { - char* url_buffer = url; - if (full_url_path) { - unsigned char num_of_slash = 0; - do { - url_buffer = strchr( ++url_buffer, '/' ); - - PRINTF("Buffer : %s %d\n", url_buffer, num_of_slash); - - } while (url_buffer && ++num_of_slash < 3); - } - - PRINTF("Url found :%s\n", url_buffer); - - /*Get rid of the first slash*/ - if (url_buffer && ++url_buffer) { - conn_state->request.url = (char*) copy_text_to_buffer(url_buffer); - conn_state->request.url_len = strlen(url_buffer); - - if ((conn_state->request.query = strchr(conn_state->request.url, '?'))) { - *(conn_state->request.query++) = 0; - /*update url len - decrease the size of query*/ - conn_state->request.url_len = strlen(conn_state->request.url); - conn_state->request.query_len = strlen(conn_state->request.query); - } - - PRINTF("url %s, url_len %u, query %s, query_len %u\n", conn_state->request.url, conn_state->request.url_len, conn_state->request.query, conn_state->request.query_len); - - /*FIXME url is not decoded - should be done here*/ - } else { - error = HTTP_URL_INVALID; - } - } - - return error; -} - -static int -parse_header(connection_state_t* conn_state, char* inputbuf) -{ - PRINTF("parse_header --->\n"); - const char* header_name = NULL; - - char* delimiter = strchr(inputbuf, ':'); - if (delimiter) { - *delimiter++ = 0; /*after increment delimiter will point space char*/ - - header_name = is_request_hdr_needed(inputbuf); - if (header_name && delimiter) { - char* buffer = delimiter; - - if (buffer[0] == ' ') { - buffer++; - } - - http_header_t* current_header = NULL; - http_header_t* head = NULL; - - current_header = allocate_header(strlen(buffer)); - - if (current_header) { - current_header->name = (char*)header_name; - strcpy(current_header->value, buffer); - } - - head = conn_state->request.headers; - conn_state->request.headers = current_header; - if (head) { - current_header->next = head; - } - - return 1; - } - } - - return 0; -} - -int -http_set_res_payload(http_response_t* response, uint8_t* payload, uint16_t size) -{ - response->payload = copy_to_buffer(payload, size); - if (response->payload) { - response->payload_len = size; - return 1; - } - - return 0; -} - -static const char* -get_header(http_header_t* headers, const char* hdr_name) -{ - for (;headers; headers = headers->next) { - if (strcmp(headers->name, hdr_name) == 0) { - return headers->value; - } - } - - return NULL; -} - -const char* http_get_req_header(http_request_t* request, const char* name) -{ - return get_header(request->headers, name); -} - -content_type_t http_get_header_content_type(http_request_t* request) -{ - const char* content_type_string = http_get_req_header(request, HTTP_HEADER_NAME_CONTENT_TYPE); - if (content_type_string) { - int i = 0; - for(; i < sizeof(content_types)/sizeof(const char*) ; i++) { - if (strcmp(content_types[i], content_type_string)) { - return (content_type_t)i; - } - } - } - - return UNKNOWN_CONTENT_TYPE; -} - -static -PT_THREAD(handle_request(connection_state_t* conn_state)) -{ - static int error; - const char* content_len; - - PSOCK_BEGIN(&(conn_state->sin)); - - content_len = NULL; - - error = HTTP_NO_ERROR; /*always reinit static variables due to protothreads*/ - - PRINTF("Request--->\n"); - - //read method - PSOCK_READTO(&(conn_state->sin), ' '); - - if (!is_method_handled(conn_state, conn_state->inputbuf)) { - /*method not handled*/ - http_set_status(&conn_state->response, SERVICE_UNAVAILABLE_503); - conn_state->state = STATE_OUTPUT; - } else { - /*read until the end of url*/ - PSOCK_READTO(&(conn_state->sin), ' '); - - /*-1 is needed since it also includes space char*/ - if (conn_state->inputbuf[PSOCK_DATALEN(&(conn_state->sin)) - 1] != ' ' ) { - error = HTTP_URL_TOO_LONG; - } - - conn_state->inputbuf[PSOCK_DATALEN(&(conn_state->sin)) - 1] = 0; - - PRINTF("Read URL:%s\n", conn_state->inputbuf); - - if (error == HTTP_NO_ERROR) { - error = parse_url(conn_state, conn_state->inputbuf); - } - - if (error != HTTP_NO_ERROR) { - if (error == HTTP_URL_TOO_LONG) { - http_set_status(&conn_state->response, REQUEST_URI_TOO_LONG_414); - } else { - http_set_status(&conn_state->response, BAD_REQUEST_400); - } - - conn_state->state = STATE_OUTPUT; - } else { - /*read until the end of HTTP version - not used yet*/ - PSOCK_READTO(&(conn_state->sin), LINE_FEED_CHAR); - - PRINTF("After URL:%s\n", conn_state->inputbuf); - - /*FIXME : PSOCK_READTO takes just a single delimiter so I read till the end of line - but now it may not fit in the buffer. If PSOCK_READTO would take two delimiters, - we would have read until : and so it would not be blocked.*/ - - /*Read the headers and store the necessary ones*/ - do { - /*read the next line*/ - PSOCK_READTO(&(conn_state->sin), LINE_FEED_CHAR); - conn_state->inputbuf[ PSOCK_DATALEN(&(conn_state->sin)) - 1] = 0; - - /*if headers finished then stop the infinite loop*/ - if (conn_state->inputbuf[0] == CARRIAGE_RETURN_CHAR || conn_state->inputbuf[0] == 0) { - PRINTF("Finished Headers!\n\n"); - break; - } - - parse_header(conn_state, conn_state->inputbuf); - } - while(1); - - content_len = get_header(conn_state->request.headers, HTTP_HEADER_NAME_CONTENT_LENGTH); - if (content_len) { - conn_state->request.payload_len = atoi(content_len); - - PRINTF("Post Data Size string: %s int: %d\n", content_len, conn_state->request.payload_len); - } - - if (conn_state->request.payload_len) { - static uint16_t read_bytes = 0; - /*init the static variable again*/ - read_bytes = 0; - - conn_state->request.payload = allocate_buffer(conn_state->request.payload_len + 1); - - if (conn_state->request.payload) { - do { - PSOCK_READBUF(&(conn_state->sin)); - /*null terminate the buffer in case it is a string.*/ - conn_state->inputbuf[PSOCK_DATALEN(&(conn_state->sin))] = 0; - - memcpy(conn_state->request.payload + read_bytes, conn_state->inputbuf, PSOCK_DATALEN(&(conn_state->sin))); - - read_bytes += PSOCK_DATALEN(&(conn_state->sin)); - - } while (read_bytes < conn_state->request.payload_len); - - conn_state->request.payload[read_bytes++] = 0; - - PRINTF("PostData => %s \n", conn_state->request.payload); - } else { - error = HTTP_MEMORY_ALLOC_ERR; - } - } - - if (error == HTTP_NO_ERROR) { - if (service_cbk) { - service_cbk(&conn_state->request, &conn_state->response); - } - } else { - PRINTF("Error:%d\n",error); - http_set_status(&conn_state->response, INTERNAL_SERVER_ERROR_500); - } - - conn_state->state = STATE_OUTPUT; - } - } - - PSOCK_END(&(conn_state->sin)); -} - -static -PT_THREAD(send_data(connection_state_t* conn_state)) -{ - uint16_t index; - http_response_t* response; - http_header_t* header; - uint8_t* buffer; - - PSOCK_BEGIN(&(conn_state->sout)); - - PRINTF("send_data -> \n"); - - index = 0; - response = &conn_state->response; - header = response->headers; - buffer = allocate_buffer(200); - - /*FIXME: what is the best solution here to send the data. Right now, if buffer is not allocated, no data is sent!*/ - if (buffer) { - index += sprintf(buffer + index, "%s %d %s%s", httpv1_1, response->status_code, response->status_string, line_end); - for (;header;header = header->next) { - PRINTF("header %u \n", (uint16_t)header); - index += sprintf(buffer + index, "%s%s%s%s", header->name, header_delimiter, header->value, line_end); - } - index += sprintf(buffer + index, "%s", line_end); - - memcpy(buffer + index, response->payload, response->payload_len); - index += response->payload_len; - - PRINTF("Sending Data(size %d): %s \n", index, buffer); - - PSOCK_SEND(&(conn_state->sout), buffer, index); - } else { - PRINTF("BUFF ERROR: send_data!\n"); - } - - PSOCK_END(&(conn_state->sout)); -} - -static -PT_THREAD(handle_response(connection_state_t* conn_state)) -{ - PT_BEGIN(&(conn_state->outputpt)); - - PRINTF("handle_response ->\n"); - - http_set_res_header(&conn_state->response, HTTP_HEADER_NAME_CONNECTION, close, 0); - http_set_res_header(&conn_state->response, HTTP_HEADER_NAME_SERVER, contiki, 0); - - if (!(conn_state->response.status_string)) { - conn_state->response.status_string = - get_default_status_string(conn_state->response.status_code); - } - - PT_WAIT_THREAD(&(conn_state->outputpt), send_data(conn_state)); - - PRINTF("<-- handle_response\n\n\n"); - - PSOCK_CLOSE(&(conn_state->sout)); - - PT_END(&(conn_state->outputpt)); -} - -static void -handle_connection(connection_state_t* conn_state) -{ - if (conn_state->state == STATE_WAITING) { - handle_request(conn_state); - } - - if (conn_state->state == STATE_OUTPUT) { - handle_response(conn_state); - } -} - -PROCESS(http_server, "Httpd Process"); - -PROCESS_THREAD(http_server, ev, data) -{ - connection_state_t *conn_state; - - PROCESS_BEGIN(); - - /* if static routes are used rather than RPL */ -#if !UIP_CONF_IPV6_RPL && !defined (CONTIKI_TARGET_MINIMAL_NET) - set_global_address(); - configure_routing(); -#endif /*!UIP_CONF_IPV6_RPL*/ - - #ifdef CONTIKI_TARGET_SKY - PRINTF("##RF CHANNEL : %d##\n",RF_CHANNEL); - #endif //CONTIKI_TARGET_SKY - - tcp_listen(uip_htons(HTTP_PORT)); - - /* - * We loop for ever, accepting new connections. - */ - while(1) { - PROCESS_WAIT_EVENT_UNTIL(ev == tcpip_event); - - conn_state = (connection_state_t *)data; - - if(uip_connected()) { - PRINTF("##Connected##\n"); - - if(init_buffer(HTTP_DATA_BUFF_SIZE)) { - conn_state = (connection_state_t*)allocate_buffer(sizeof(connection_state_t)); - - if (conn_state) { - tcp_markconn(uip_conn, conn_state); - - /*initialize connection state*/ - init_connection(conn_state); - - /*-1 is needed to be able to null terminate the strings in the buffer, especially good for debugging (to have null terminated strings)*/ - PSOCK_INIT(&(conn_state->sin), (uint8_t*)conn_state->inputbuf, sizeof(conn_state->inputbuf) - 1); - PSOCK_INIT(&(conn_state->sout), (uint8_t*)conn_state->inputbuf, sizeof(conn_state->inputbuf) - 1); - PT_INIT(&(conn_state->outputpt)); - - handle_connection(conn_state); - } else { - PRINTF("Memory Alloc Error. Aborting!\n"); - uip_abort(); - } - } - } else if (uip_aborted() || uip_closed() || uip_timedout()) { - if (conn_state) { - delete_buffer(); - - /*Following 2 lines are needed since this part of code is somehow executed twice so it tries to free the same region twice. - Potential bug in uip*/ - conn_state = NULL; - tcp_markconn(uip_conn, conn_state); - } - } else { - handle_connection(conn_state); - } - } - - PROCESS_END(); -} diff --git a/apps/rest-http/http-server.h b/apps/rest-http/http-server.h deleted file mode 100644 index f28fee0ea..000000000 --- a/apps/rest-http/http-server.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef HTTPSERVER_H_ -#define HTTPSERVER_H_ - -#include "http-common.h" -#include "rest.h" - -/*Declare process*/ -PROCESS_NAME(http_server); - -/*Type definition of the service callback*/ -typedef int (*service_callback) (http_request_t* request, http_response_t* response); - -/* - *Setter of the service callback, this callback will be called in case of HTTP request. - */ -void http_set_service_callback(service_callback callback); - -/* - * Setter for the status code (200, 201, etc) of the response. - */ -void http_set_status(http_response_t* response, status_code_t status); - -/* - * Adds the header name and value provided to the response. - * Name of the header should be hardcoded since it is accessed from code segment - * (not copied to buffer) whereas value of the header can be copied - * depending on the relevant parameter. This is needed since some values may be - * generated dynamically (ex: e-tag value) - */ -int http_set_res_header(http_response_t* response, const char* name, const char* value, int copy); - -/* - * Returns the value of the header name provided. Return NULL if header does not exist. - */ -const char* http_get_req_header(http_request_t* request, const char* name); - -int http_set_res_payload(http_response_t* response, uint8_t* payload, uint16_t size); - -/* - * Returns query variable in the URL. - * Returns true if the variable found, false otherwise. - * Variable is put in the buffer provided. - */ -int http_get_query_variable(http_request_t* request, const char *name, char* output, uint16_t output_size); - -/* - * Returns variable in the Post Data. - * Returns true if the variable found, false otherwise. - * Variable is put in the buffer provided. - */ -int http_get_post_variable(http_request_t* request, const char *name, char* output, uint16_t output_size); - -/* - * Get the header "Content-Type". - */ -const char* http_get_content_type_string(content_type_t content_type); -content_type_t http_get_header_content_type(http_request_t* request); - -#endif /*HTTPSERVER_H_*/ diff --git a/apps/shell/Makefile.shell b/apps/shell/Makefile.shell index 39d444781..db1de4d6a 100644 --- a/apps/shell/Makefile.shell +++ b/apps/shell/Makefile.shell @@ -9,7 +9,7 @@ shell_src = shell.c shell-reboot.c shell-vars.c shell-ps.c \ shell_dsc = shell-dsc.c ifeq ($(CONTIKI_WITH_RIME),1) -shell_src += shell-rime.c shell-sendtest.c shell-netfile.c \ +shell_src += shell-rime.c shell-sendtest.c \ shell-rime-ping.c shell-rime-sniff.c shell-rime-netcmd.c \ shell-rime-debug.c shell-rime-debug-runicast.c \ shell-rime-sendcmd.c shell-download.c shell-rime-neighbors.c \ diff --git a/apps/shell/shell-netfile.c b/apps/shell/shell-netfile.c deleted file mode 100644 index 45c303974..000000000 --- a/apps/shell/shell-netfile.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2008, 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 brief description of what this file is. - * \author - * Adam Dunkels - */ - -#include "contiki.h" -#include "shell-netfile.h" -#include "net/rime/rime.h" -#include "net/rime/rudolph0.h" -#include "dev/leds.h" - -#include "cfs/cfs.h" - -#include -#include - -#define FILENAME_LEN 20 - -static struct rudolph0_conn rudolph0_conn; -static char filename[FILENAME_LEN]; -static int receiving_file; -static struct pt recvnetfilept; -/*---------------------------------------------------------------------------*/ -PROCESS(shell_netfile_process, "netfile"); -SHELL_COMMAND(netfile_command, - "netfile", - "netfile: send file to entire network", - &shell_netfile_process); -PROCESS(shell_recvnetfile_process, "recvnetfile"); -SHELL_COMMAND(recvnetfile_command, - "recvnetfile", - "recvnetfile: receive file from network and print to output", - &shell_recvnetfile_process); -/*---------------------------------------------------------------------------*/ -static int -write_chunk_pt(struct rudolph0_conn *c, int offset, int flag, - uint8_t *data, int datalen) -{ - PT_BEGIN(&recvnetfilept); - - PT_WAIT_UNTIL(&recvnetfilept, receiving_file); - leds_on(LEDS_YELLOW); - leds_on(LEDS_RED); - PT_WAIT_UNTIL(&recvnetfilept, flag == RUDOLPH0_FLAG_NEWFILE); - leds_off(LEDS_RED); - - do { - if(datalen > 0) { - shell_output(&recvnetfile_command, data, datalen, "", 0); - /* printf("write_chunk wrote %d bytes at %d\n", datalen, offset);*/ - } - PT_YIELD(&recvnetfilept); - } while(flag != RUDOLPH0_FLAG_LASTCHUNK); - - shell_output(&recvnetfile_command, data, datalen, "", 0); - /* printf("write_chunk wrote %d bytes at %d\n", datalen, offset);*/ - shell_output(&recvnetfile_command, "", 0, "", 0); - leds_off(LEDS_YELLOW); - receiving_file = 0; - process_post(&shell_recvnetfile_process, PROCESS_EVENT_CONTINUE, NULL); - - PT_END(&recvnetfilept); -} -static void -write_chunk(struct rudolph0_conn *c, int offset, int flag, - uint8_t *data, int datalen) -{ - write_chunk_pt(c, offset, flag, data, datalen); -} - -static int -read_chunk(struct rudolph0_conn *c, int offset, uint8_t *to, int maxsize) -{ - int ret; - int fd; - - fd = cfs_open(filename, CFS_READ); - - cfs_seek(fd, offset, CFS_SEEK_SET); - ret = cfs_read(fd, to, maxsize); - /* printf("read_chunk %d bytes at %d, %d\n", ret, offset, (unsigned char)to[0]);*/ - cfs_close(fd); - return ret; -} -CC_CONST_FUNCTION static struct rudolph0_callbacks rudolph0_callbacks = - {/*(void (*)(struct rudolph0_conn *, int, int, uint8_t *, int))*/ - write_chunk, - read_chunk}; -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(shell_netfile_process, ev, data) -{ - int fd; - - PROCESS_BEGIN(); - - if(data != NULL) { - rudolph0_send(&rudolph0_conn, CLOCK_SECOND); - - strncpy(filename, data, FILENAME_LEN); - fd = cfs_open(filename, CFS_READ); - if(fd < 0) { - shell_output_str(&netfile_command, "netfile: could not open file ", filename); - } else { - cfs_close(fd); - } - } - - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(shell_recvnetfile_process, ev, data) -{ - PROCESS_BEGIN(); - - PT_INIT(&recvnetfilept); - receiving_file = 1; - while(1) { - struct shell_input *input; - - PROCESS_WAIT_EVENT(); - - if(ev == shell_event_input) { - input = data; - if(input->len1 + input->len2 == 0) { - receiving_file = 0; - PROCESS_EXIT(); - } - } else if(receiving_file == 0) { - PROCESS_EXIT(); - } - } - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ -void -shell_netfile_init(void) -{ - receiving_file = 0; - shell_register_command(&netfile_command); - shell_register_command(&recvnetfile_command); - - rudolph0_open(&rudolph0_conn, SHELL_RIME_CHANNEL_NETFILE, - &rudolph0_callbacks); -} -/*---------------------------------------------------------------------------*/ diff --git a/apps/shell/shell-power.c b/apps/shell/shell-power.c index c4414c9a1..0e5cb0aed 100644 --- a/apps/shell/shell-power.c +++ b/apps/shell/shell-power.c @@ -42,6 +42,7 @@ #include "sys/energest.h" #include +#include "sys/cc.h" struct power_msg { uint16_t len; diff --git a/apps/shell/shell-sky.c b/apps/shell/shell-sky.c index 65c4859ed..a25b15957 100644 --- a/apps/shell/shell-sky.c +++ b/apps/shell/shell-sky.c @@ -38,6 +38,7 @@ */ #include "contiki.h" +#include "sys/cc.h" #include "shell-sky.h" #include "dev/watchdog.h" @@ -84,8 +85,6 @@ SHELL_COMMAND(rfchannel_command, "rfchannel : change CC2420 radio channel (11 - 26)", &shell_rfchannel_process); /*---------------------------------------------------------------------------*/ -#define MAX(a, b) ((a) > (b)? (a): (b)) -#define MIN(a, b) ((a) < (b)? (a): (b)) struct spectrum { int channel[16]; }; diff --git a/apps/shell/shell-tcpsend.c b/apps/shell/shell-tcpsend.c index 923cda181..7ef93b671 100644 --- a/apps/shell/shell-tcpsend.c +++ b/apps/shell/shell-tcpsend.c @@ -36,13 +36,10 @@ #include #include "contiki.h" +#include "sys/cc.h" #include "shell.h" #include "telnet.h" -#ifndef MIN -#define MIN(a, b) ((a) < (b)? (a) : (b)) -#endif /* MIN */ - /*---------------------------------------------------------------------------*/ PROCESS(shell_tcpsend_process, "tcpsend"); SHELL_COMMAND(tcpsend_command, diff --git a/apps/shell/shell-time.c b/apps/shell/shell-time.c index 0c3ac03c1..fb2b7e7f1 100644 --- a/apps/shell/shell-time.c +++ b/apps/shell/shell-time.c @@ -38,6 +38,7 @@ */ #include "contiki.h" +#include "sys/cc.h" #include "shell-time.h" #include "sys/clock.h" @@ -51,11 +52,6 @@ #define MAX_COMMANDLENGTH 64 #define PERIOD_INTERVAL 60 -#ifndef MIN -#define MIN(a, b) ((a) < (b)? (a) : (b)) -#endif /* MIN */ - - /*---------------------------------------------------------------------------*/ PROCESS(shell_time_process, "time"); SHELL_COMMAND(time_command, diff --git a/apps/shell/shell.h b/apps/shell/shell.h index ea383deb8..f6e4e1b8d 100644 --- a/apps/shell/shell.h +++ b/apps/shell/shell.h @@ -382,7 +382,6 @@ struct shell_input { #include "shell-httpd.h" #include "shell-irc.h" #include "shell-memdebug.h" -#include "shell-netfile.h" #include "shell-netperf.h" #include "shell-netstat.h" #include "shell-ping.h" diff --git a/apps/telnetd/telnetd.c b/apps/telnetd/telnetd.c index 95786442b..c168b19b8 100644 --- a/apps/telnetd/telnetd.c +++ b/apps/telnetd/telnetd.c @@ -33,6 +33,7 @@ #include +#include "sys/cc.h" #include "contiki-lib.h" #include "contiki-net.h" #include "lib/petsciiconv.h" @@ -103,7 +104,6 @@ static uint8_t connected; #define MAX_SILENCE_TIME (CLOCK_SECOND * 30) -#define MIN(a, b) ((a) < (b)? (a): (b)) /*---------------------------------------------------------------------------*/ static void buf_init(struct telnetd_buf *buf) diff --git a/core/cfs/cfs-coffee.c b/core/cfs/cfs-coffee.c index d7f55a7c2..4b08d4544 100644 --- a/core/cfs/cfs-coffee.c +++ b/core/cfs/cfs-coffee.c @@ -1125,8 +1125,6 @@ cfs_read(int fd, void *buf, unsigned size) * ordinary file if the page has no log record. */ for(bytes_left = size; bytes_left > 0; bytes_left -= r) { - r = -1; - lp.offset = fdp->offset; lp.buf = buf; lp.size = bytes_left; diff --git a/core/dev/spi.h b/core/dev/spi.h index 1ccbe2bc0..5960c411b 100644 --- a/core/dev/spi.h +++ b/core/dev/spi.h @@ -57,36 +57,36 @@ extern unsigned char spi_busy; void spi_init(void); /* Write one character to SPI */ -#define SPI_WRITE(data) \ - do { \ - SPI_WAITFORTx_BEFORE(); \ - SPI_TXBUF = data; \ - SPI_WAITFOREOTx(); \ +#define SPI_WRITE(data) \ + do { \ + SPI_WAITFORTx_BEFORE(); \ + SPI_TXBUF = data; \ + SPI_WAITFOREOTx(); \ } while(0) /* Write one character to SPI - will not wait for end useful for multiple writes with wait after final */ -#define SPI_WRITE_FAST(data) \ - do { \ - SPI_WAITFORTx_BEFORE(); \ - SPI_TXBUF = data; \ - SPI_WAITFORTx_AFTER(); \ +#define SPI_WRITE_FAST(data) \ + do { \ + SPI_WAITFORTx_BEFORE(); \ + SPI_TXBUF = data; \ + SPI_WAITFORTx_AFTER(); \ } while(0) /* Read one character from SPI */ -#define SPI_READ(data) \ - do { \ - SPI_TXBUF = 0; \ - SPI_WAITFOREORx(); \ - data = SPI_RXBUF; \ +#define SPI_READ(data) \ + do { \ + SPI_TXBUF = 0; \ + SPI_WAITFOREORx(); \ + data = SPI_RXBUF; \ } while(0) /* Flush the SPI read register */ #ifndef SPI_FLUSH #define SPI_FLUSH() \ - do { \ - SPI_RXBUF; \ - } while(0); + do { \ + SPI_RXBUF; \ + } while(0) #endif #endif /* SPI_H_ */ diff --git a/core/lib/petsciiconv.c b/core/lib/petsciiconv.c index 873c7c2c7..a6eda5979 100644 --- a/core/lib/petsciiconv.c +++ b/core/lib/petsciiconv.c @@ -72,14 +72,13 @@ static unsigned char ascii2petscii[128] = { 0x58,0x59,0x5a,0xdb,0xdd,0xdd,0x5e,0xdf, }; -static unsigned int i; -static unsigned char *ptr; - /*-----------------------------------------------------------------------------------*/ void petsciiconv_toascii(char *buf, unsigned int len) { - static char c; + unsigned int i; + char *ptr; + char c; ptr = buf; for(i = len; i > 0; --i) { @@ -108,6 +107,9 @@ petsciiconv_toascii(char *buf, unsigned int len) void petsciiconv_topetscii(char *buf, unsigned int len) { + unsigned int i; + char *ptr; + ptr = buf; for(i = len; i > 0; --i) { *ptr = ascii2petscii[*ptr & 0x7f]; diff --git a/core/lib/settings.c b/core/lib/settings.c index b085f7219..1b97b28b5 100644 --- a/core/lib/settings.c +++ b/core/lib/settings.c @@ -65,10 +65,6 @@ #define SETTINGS_BOTTOM_ADDR (SETTINGS_TOP_ADDR + 1 - SETTINGS_MAX_SIZE) #endif -#ifndef MIN -#define MIN(a,b) ((a)<(b)?a:b) -#endif - typedef struct { #if SETTINGS_CONF_SUPPORT_LARGE_VALUES uint8_t size_extra; diff --git a/core/net/http-socket/http-socket.c b/core/net/http-socket/http-socket.c new file mode 100644 index 000000000..758c1473e --- /dev/null +++ b/core/net/http-socket/http-socket.c @@ -0,0 +1,682 @@ +/* + * Copyright (c) 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-net.h" +#include "ip64-addr.h" +#include "http-socket.h" + +#include +#include + +#define MAX_PATHLEN 80 +#define MAX_HOSTLEN 40 +PROCESS(http_socket_process, "HTTP socket process"); +LIST(socketlist); + +static void removesocket(struct http_socket *s); +/*---------------------------------------------------------------------------*/ +static void +call_callback(struct http_socket *s, http_socket_event_t e, + const uint8_t *data, uint16_t datalen) +{ + if(s->callback != NULL) { + s->callback(s, s->callbackptr, e, + data, datalen); + } +} +/*---------------------------------------------------------------------------*/ +static void +parse_header_init(struct http_socket *s) +{ + PT_INIT(&s->headerpt); +} +/*---------------------------------------------------------------------------*/ +static int +parse_header_byte(struct http_socket *s, char c) +{ + PT_BEGIN(&s->headerpt); + + memset(&s->header, -1, sizeof(s->header)); + + /* Skip the HTTP response */ + while(c != ' ') { + PT_YIELD(&s->headerpt); + } + + /* Skip the space */ + PT_YIELD(&s->headerpt); + /* Read three characters of HTTP status and convert to BCD */ + s->header.status_code = 0; + for(s->header_chars = 0; s->header_chars < 3; s->header_chars++) { + s->header.status_code = s->header.status_code << 4 | (c - '0'); + PT_YIELD(&s->headerpt); + } + + if(s->header.status_code == 0x200 || s->header.status_code == 0x206) { + /* Read headers until data */ + + while(1) { + /* Skip characters until end of line */ + do { + while(c != '\r') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + s->header_chars++; + PT_YIELD(&s->headerpt); + } while(c != '\n'); + s->header_chars--; + PT_YIELD(&s->headerpt); + + if(s->header_chars == 0) { + /* This was an empty line, i.e. the end of headers */ + break; + } + + /* Start of line */ + s->header_chars = 0; + + /* Read header field */ + while(c != ' ' && c != '\t' && c != ':' && c != '\r' && + s->header_chars < sizeof(s->header_field) - 1) { + s->header_field[s->header_chars++] = c; + PT_YIELD(&s->headerpt); + } + s->header_field[s->header_chars] = '\0'; + /* Skip linear white spaces */ + while(c == ' ' || c == '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + if(c == ':') { + /* Skip the colon */ + s->header_chars++; + PT_YIELD(&s->headerpt); + /* Skip linear white spaces */ + while(c == ' ' || c == '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + if(!strcmp(s->header_field, "Content-Length")) { + s->header.content_length = 0; + while(isdigit((int)c)) { + s->header.content_length = s->header.content_length * 10 + c - '0'; + s->header_chars++; + PT_YIELD(&s->headerpt); + } + } else if(!strcmp(s->header_field, "Content-Range")) { + /* Skip the bytes-unit token */ + while(c != ' ' && c != '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + /* Skip linear white spaces */ + while(c == ' ' || c == '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + s->header.content_range.first_byte_pos = 0; + while(isdigit((int)c)) { + s->header.content_range.first_byte_pos = + s->header.content_range.first_byte_pos * 10 + c - '0'; + s->header_chars++; + PT_YIELD(&s->headerpt); + } + /* Skip linear white spaces */ + while(c == ' ' || c == '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + if(c == '-') { + /* Skip the dash */ + s->header_chars++; + PT_YIELD(&s->headerpt); + /* Skip linear white spaces */ + while(c == ' ' || c == '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + s->header.content_range.last_byte_pos = 0; + while(isdigit((int)c)) { + s->header.content_range.last_byte_pos = + s->header.content_range.last_byte_pos * 10 + c - '0'; + s->header_chars++; + PT_YIELD(&s->headerpt); + } + /* Skip linear white spaces */ + while(c == ' ' || c == '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + if(c == '/') { + /* Skip the slash */ + s->header_chars++; + PT_YIELD(&s->headerpt); + /* Skip linear white spaces */ + while(c == ' ' || c == '\t') { + s->header_chars++; + PT_YIELD(&s->headerpt); + } + if(c != '*') { + s->header.content_range.instance_length = 0; + while(isdigit((int)c)) { + s->header.content_range.instance_length = + s->header.content_range.instance_length * 10 + c - '0'; + s->header_chars++; + PT_YIELD(&s->headerpt); + } + } + } + } + } + } + } + + /* All headers read, now read data */ + call_callback(s, HTTP_SOCKET_HEADER, (void *)&s->header, sizeof(s->header)); + + /* Should exit the pt here to indicate that all headers have been + read */ + PT_EXIT(&s->headerpt); + } else { + if(s->header.status_code == 0x404) { + printf("File not found\n"); + } else if(s->header.status_code == 0x301 || s->header.status_code == 0x302) { + printf("File moved (not handled)\n"); + } + + call_callback(s, HTTP_SOCKET_ERR, (void *)&s->header, sizeof(s->header)); + tcp_socket_close(&s->s); + removesocket(s); + PT_EXIT(&s->headerpt); + } + + + PT_END(&s->headerpt); +} +/*---------------------------------------------------------------------------*/ +static int +input_pt(struct http_socket *s, + const uint8_t *inputptr, int inputdatalen) +{ + int i; + PT_BEGIN(&s->pt); + + /* Parse the header */ + s->header_received = 0; + do { + for(i = 0; i < inputdatalen; i++) { + if(!PT_SCHEDULE(parse_header_byte(s, inputptr[i]))) { + s->header_received = 1; + break; + } + } + inputdatalen -= i; + inputptr += i; + + if(s->header_received == 0) { + /* If we have not yet received the full header, we wait for the + next packet to arrive. */ + PT_YIELD(&s->pt); + } + } while(s->header_received == 0); + + s->bodylen = 0; + do { + /* Receive the data */ + call_callback(s, HTTP_SOCKET_DATA, inputptr, inputdatalen); + + /* Close the connection if the expected content length has been received */ + if(s->header.content_length >= 0 && s->bodylen < s->header.content_length) { + s->bodylen += inputdatalen; + if(s->bodylen >= s->header.content_length) { + tcp_socket_close(&s->s); + } + } + + PT_YIELD(&s->pt); + } while(inputdatalen > 0); + + PT_END(&s->pt); +} +/*---------------------------------------------------------------------------*/ +static void +start_timeout_timer(struct http_socket *s) +{ + PROCESS_CONTEXT_BEGIN(&http_socket_process); + etimer_set(&s->timeout_timer, HTTP_SOCKET_TIMEOUT); + PROCESS_CONTEXT_END(&http_socket_process); + s->timeout_timer_started = 1; +} +/*---------------------------------------------------------------------------*/ +static int +input(struct tcp_socket *tcps, void *ptr, + const uint8_t *inputptr, int inputdatalen) +{ + struct http_socket *s = ptr; + + input_pt(s, inputptr, inputdatalen); + start_timeout_timer(s); + + return 0; /* all data consumed */ +} +/*---------------------------------------------------------------------------*/ +static int +parse_url(const char *url, char *host, uint16_t *portptr, char *path) +{ + const char *urlptr; + int i; + const char *file; + uint16_t port; + + if(url == NULL) { + printf("null url\n"); + return 0; + } + + /* Don't even try to go further if the URL is empty. */ + if(strlen(url) == 0) { + printf("empty url\n"); + return 0; + } + + /* See if the URL starts with http:// and remove it. Otherwise, we + assume it is an implicit http://. */ + if(strncmp(url, "http://", strlen("http://")) == 0) { + urlptr = url + strlen("http://"); + } else { + urlptr = url; + } + + /* Find host part of the URL. */ + if(*urlptr == '[') { + /* Handle IPv6 addresses - scan for matching ']' */ + urlptr++; + for(i = 0; i < MAX_HOSTLEN; ++i) { + if(*urlptr == ']') { + if(host != NULL) { + host[i] = 0; + } + break; + } + if(host != NULL) { + host[i] = *urlptr; + } + ++urlptr; + } + } else { + for(i = 0; i < MAX_HOSTLEN; ++i) { + if(*urlptr == 0 || + *urlptr == '/' || + *urlptr == ' ' || + *urlptr == ':') { + if(host != NULL) { + host[i] = 0; + } + break; + } + if(host != NULL) { + host[i] = *urlptr; + } + ++urlptr; + } + } + + /* Find the port. Default is 80. */ + port = 80; + if(*urlptr == ':') { + port = 0; + do { + ++urlptr; + if(*urlptr >= '0' && *urlptr <= '9') { + port = (10 * port) + (*urlptr - '0'); + } + } while(*urlptr >= '0' && + *urlptr <= '9'); + } + if(portptr != NULL) { + *portptr = port; + } + /* Find file part of the URL. */ + while(*urlptr != '/' && *urlptr != 0) { + ++urlptr; + } + if(*urlptr == '/') { + file = urlptr; + } else { + file = "/"; + } + if(path != NULL) { + strncpy(path, file, MAX_PATHLEN); + } + return 1; +} +/*---------------------------------------------------------------------------*/ +static void +removesocket(struct http_socket *s) +{ + etimer_stop(&s->timeout_timer); + s->timeout_timer_started = 0; + list_remove(socketlist, s); +} +/*---------------------------------------------------------------------------*/ +static void +event(struct tcp_socket *tcps, void *ptr, + tcp_socket_event_t e) +{ + struct http_socket *s = ptr; + char host[MAX_HOSTLEN]; + char path[MAX_PATHLEN]; + uint16_t port; + char str[42]; + int len; + + if(e == TCP_SOCKET_CONNECTED) { + printf("Connected\n"); + if(parse_url(s->url, host, &port, path)) { + tcp_socket_send_str(tcps, s->postdata != NULL ? "POST " : "GET "); + if(s->proxy_port != 0) { + /* If we are configured to route through a proxy, we should + provide the full URL as the path. */ + tcp_socket_send_str(tcps, s->url); + } else { + tcp_socket_send_str(tcps, path); + } + 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: "); + tcp_socket_send_str(tcps, host); + tcp_socket_send_str(tcps, "\r\n"); + if(s->postdata != NULL) { + if(s->content_type) { + tcp_socket_send_str(tcps, "Content-Type: "); + tcp_socket_send_str(tcps, s->content_type); + tcp_socket_send_str(tcps, "\r\n"); + } + tcp_socket_send_str(tcps, "Content-Length: "); + sprintf(str, "%u", s->postdatalen); + tcp_socket_send_str(tcps, str); + tcp_socket_send_str(tcps, "\r\n"); + } else if(s->length || s->pos > 0) { + tcp_socket_send_str(tcps, "Range: bytes="); + if(s->length) { + if(s->pos >= 0) { + sprintf(str, "%llu-%llu", s->pos, s->pos + s->length - 1); + } else { + sprintf(str, "-%llu", s->length); + } + } else { + sprintf(str, "%llu-", s->pos); + } + tcp_socket_send_str(tcps, str); + tcp_socket_send_str(tcps, "\r\n"); + } + tcp_socket_send_str(tcps, "\r\n"); + if(s->postdata != NULL && s->postdatalen) { + len = tcp_socket_send(tcps, s->postdata, s->postdatalen); + s->postdata += len; + s->postdatalen -= len; + } + } + parse_header_init(s); + } else if(e == TCP_SOCKET_CLOSED) { + call_callback(s, HTTP_SOCKET_CLOSED, NULL, 0); + removesocket(s); + printf("Closed\n"); + } else if(e == TCP_SOCKET_TIMEDOUT) { + call_callback(s, HTTP_SOCKET_TIMEDOUT, NULL, 0); + removesocket(s); + printf("Timedout\n"); + } else if(e == TCP_SOCKET_ABORTED) { + call_callback(s, HTTP_SOCKET_ABORTED, NULL, 0); + removesocket(s); + printf("Aborted\n"); + } else if(e == TCP_SOCKET_DATA_SENT) { + if(s->postdata != NULL && s->postdatalen) { + len = tcp_socket_send(tcps, s->postdata, s->postdatalen); + s->postdata += len; + s->postdatalen -= len; + } else { + start_timeout_timer(s); + } + } +} +/*---------------------------------------------------------------------------*/ +static int +start_request(struct http_socket *s) +{ + uip_ip4addr_t ip4addr; + uip_ip6addr_t ip6addr; + uip_ip6addr_t *addr; + char host[MAX_HOSTLEN]; + char path[MAX_PATHLEN]; + uint16_t port; + int ret; + + if(parse_url(s->url, host, &port, path)) { + + printf("url %s host %s port %d path %s\n", + s->url, host, port, path); + + /* Check if we are to route the request through a proxy. */ + if(s->proxy_port != 0) { + /* The proxy address should be an IPv6 address. */ + uip_ip6addr_copy(&ip6addr, &s->proxy_addr); + port = s->proxy_port; + } else if(uiplib_ip6addrconv(host, &ip6addr) == 0) { + /* First check if the host is an IP address. */ + if(uiplib_ip4addrconv(host, &ip4addr) != 0) { + ip64_addr_4to6(&ip4addr, &ip6addr); + } else { + /* Try to lookup the hostname. If it fails, we initiate a hostname + lookup. */ + ret = resolv_lookup(host, &addr); + if(ret == RESOLV_STATUS_UNCACHED || + ret == RESOLV_STATUS_EXPIRED) { + resolv_query(host); + puts("Resolving host..."); + return HTTP_SOCKET_OK; + } + if(addr != NULL) { + s->did_tcp_connect = 1; + tcp_socket_connect(&s->s, addr, port); + return HTTP_SOCKET_OK; + } else { + return HTTP_SOCKET_ERR; + } + } + } + tcp_socket_connect(&s->s, &ip6addr, port); + return HTTP_SOCKET_OK; + } else { + return HTTP_SOCKET_ERR; + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(http_socket_process, ev, data) +{ + PROCESS_BEGIN(); + + while(1) { + + PROCESS_WAIT_EVENT(); + + if(ev == resolv_event_found && data != NULL) { + struct http_socket *s; + const char *name = data; + /* Either found a hostname, or not. We need to go through the + list of http sockets and figure out to which connection this + reply corresponds, then either restart the HTTP get, or kill + it (if no hostname was found). */ + for(s = list_head(socketlist); + s != NULL; + s = list_item_next(s)) { + char host[MAX_HOSTLEN]; + if(s->did_tcp_connect) { + /* We already connected, ignored */ + } else if(parse_url(s->url, host, NULL, NULL) && + strcmp(name, host) == 0) { + if(resolv_lookup(name, NULL) == RESOLV_STATUS_CACHED) { + /* Hostname found, restart get. */ + start_request(s); + } else { + /* Hostname not found, kill connection. */ + call_callback(s, HTTP_SOCKET_HOSTNAME_NOT_FOUND, NULL, 0); + removesocket(s); + } + } + } + } else if(ev == PROCESS_EVENT_TIMER) { + struct http_socket *s; + struct etimer *timeout_timer = data; + /* + * A socket time-out has occurred. We need to go through the list of HTTP + * sockets and figure out to which socket this timer event corresponds, + * then close this socket. + */ + for(s = list_head(socketlist); + s != NULL; + s = list_item_next(s)) { + if(timeout_timer == &s->timeout_timer && s->timeout_timer_started) { + tcp_socket_close(&s->s); + break; + } + } + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ + static uint8_t inited = 0; + if(inited == 0) { + process_start(&http_socket_process, NULL); + list_init(socketlist); + inited = 1; + } +} +/*---------------------------------------------------------------------------*/ +void +http_socket_init(struct http_socket *s) +{ + init(); + uip_create_unspecified(&s->proxy_addr); + s->proxy_port = 0; +} +/*---------------------------------------------------------------------------*/ +static void +initialize_socket(struct http_socket *s) +{ + s->pos = 0; + s->length = 0; + s->postdata = NULL; + s->postdatalen = 0; + s->timeout_timer_started = 0; + PT_INIT(&s->pt); + tcp_socket_register(&s->s, s, + s->inputbuf, sizeof(s->inputbuf), + s->outputbuf, sizeof(s->outputbuf), + input, event); +} +/*---------------------------------------------------------------------------*/ +int +http_socket_get(struct http_socket *s, + const char *url, + int64_t pos, + uint64_t length, + http_socket_callback_t callback, + void *callbackptr) +{ + initialize_socket(s); + strncpy(s->url, url, sizeof(s->url)); + s->pos = pos; + s->length = length; + s->callback = callback; + s->callbackptr = callbackptr; + + s->did_tcp_connect = 0; + + list_add(socketlist, s); + + return start_request(s); +} +/*---------------------------------------------------------------------------*/ +int +http_socket_post(struct http_socket *s, + const char *url, + const void *postdata, + uint16_t postdatalen, + const char *content_type, + http_socket_callback_t callback, + void *callbackptr) +{ + initialize_socket(s); + strncpy(s->url, url, sizeof(s->url)); + s->postdata = postdata; + s->postdatalen = postdatalen; + s->content_type = content_type; + + s->callback = callback; + s->callbackptr = callbackptr; + + s->did_tcp_connect = 0; + + list_add(socketlist, s); + + return start_request(s); +} +/*---------------------------------------------------------------------------*/ +int +http_socket_close(struct http_socket *socket) +{ + struct http_socket *s; + for(s = list_head(socketlist); + s != NULL; + s = list_item_next(s)) { + if(s == socket) { + tcp_socket_close(&s->s); + removesocket(s); + return 1; + } + } + return 0; +} +/*---------------------------------------------------------------------------*/ +void +http_socket_set_proxy(struct http_socket *s, + const uip_ipaddr_t *addr, uint16_t port) +{ + uip_ipaddr_copy(&s->proxy_addr, addr); + s->proxy_port = port; +} +/*---------------------------------------------------------------------------*/ diff --git a/core/net/http-socket/http-socket.h b/core/net/http-socket/http-socket.h new file mode 100644 index 000000000..5b683e10b --- /dev/null +++ b/core/net/http-socket/http-socket.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 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 HTTP_SOCKET_H +#define HTTP_SOCKET_H + +#include "tcp-socket.h" + +struct http_socket; + +typedef enum { + HTTP_SOCKET_ERR, + HTTP_SOCKET_OK, + HTTP_SOCKET_HEADER, + HTTP_SOCKET_DATA, + HTTP_SOCKET_CLOSED, + HTTP_SOCKET_TIMEDOUT, + HTTP_SOCKET_ABORTED, + HTTP_SOCKET_HOSTNAME_NOT_FOUND, +} http_socket_event_t; + +struct http_socket_header { + uint16_t status_code; + int64_t content_length; + struct { + int64_t first_byte_pos; + int64_t last_byte_pos; + int64_t instance_length; + } content_range; +}; + +typedef void (* http_socket_callback_t)(struct http_socket *s, + void *ptr, + http_socket_event_t ev, + const uint8_t *data, + uint16_t datalen); + +#define MAX(n, m) (((n) < (m)) ? (m) : (n)) + +#define HTTP_SOCKET_INPUTBUFSIZE UIP_TCP_MSS +#define HTTP_SOCKET_OUTPUTBUFSIZE MAX(UIP_TCP_MSS, 128) + +#define HTTP_SOCKET_URLLEN 128 + +#define HTTP_SOCKET_TIMEOUT ((2 * 60 + 30) * CLOCK_SECOND) + +struct http_socket { + struct http_socket *next; + struct tcp_socket s; + uip_ipaddr_t proxy_addr; + uint16_t proxy_port; + int64_t pos; + uint64_t length; + const uint8_t *postdata; + uint16_t postdatalen; + http_socket_callback_t callback; + void *callbackptr; + int did_tcp_connect; + char url[HTTP_SOCKET_URLLEN]; + uint8_t inputbuf[HTTP_SOCKET_INPUTBUFSIZE]; + uint8_t outputbuf[HTTP_SOCKET_OUTPUTBUFSIZE]; + + struct etimer timeout_timer; + uint8_t timeout_timer_started; + struct pt pt, headerpt; + int header_chars; + char header_field[15]; + struct http_socket_header header; + uint8_t header_received; + uint64_t bodylen; + const char *content_type; +}; + +void http_socket_init(struct http_socket *s); + +int http_socket_get(struct http_socket *s, const char *url, + int64_t pos, uint64_t length, + http_socket_callback_t callback, + void *callbackptr); + +int http_socket_post(struct http_socket *s, const char *url, + const void *postdata, + uint16_t postdatalen, + const char *content_type, + http_socket_callback_t callback, + void *callbackptr); + +int http_socket_close(struct http_socket *socket); + +void http_socket_set_proxy(struct http_socket *s, + const uip_ipaddr_t *addr, uint16_t port); + + +#endif /* HTTP_SOCKET_H */ diff --git a/core/net/ip64-addr/ip64-addr.c b/core/net/ip/ip64-addr.c similarity index 100% rename from core/net/ip64-addr/ip64-addr.c rename to core/net/ip/ip64-addr.c diff --git a/core/net/ip64-addr/ip64-addr.h b/core/net/ip/ip64-addr.h similarity index 100% rename from core/net/ip64-addr/ip64-addr.h rename to core/net/ip/ip64-addr.h diff --git a/core/net/ip/resolv.c b/core/net/ip/resolv.c index 4a9999cca..58bda004d 100644 --- a/core/net/ip/resolv.c +++ b/core/net/ip/resolv.c @@ -787,7 +787,7 @@ newdata(void) static int8_t i; - register struct namemap *namemapptr; + register struct namemap *namemapptr = NULL; struct dns_answer *ans; diff --git a/core/net/ip/slipdev.c b/core/net/ip/slipdev.c index caab454ac..8bc688557 100644 --- a/core/net/ip/slipdev.c +++ b/core/net/ip/slipdev.c @@ -103,7 +103,7 @@ slipdev_send(void) ptr = &uip_buf[UIP_LLH_LEN]; for(i = 0; i < uip_len; ++i) { if(i == UIP_TCPIP_HLEN) { - ptr = (char *)uip_appdata; + ptr = (uint8_t *)uip_appdata; } c = *ptr++; switch(c) { diff --git a/core/net/ip/tcp-socket.c b/core/net/ip/tcp-socket.c index 44010ce1c..eac008cde 100644 --- a/core/net/ip/tcp-socket.c +++ b/core/net/ip/tcp-socket.c @@ -30,6 +30,7 @@ */ #include "contiki.h" +#include "sys/cc.h" #include "contiki-net.h" #include "lib/list.h" @@ -39,7 +40,8 @@ #include #include -#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +static void relisten(struct tcp_socket *s); LIST(socketlist); /*---------------------------------------------------------------------------*/ @@ -58,8 +60,8 @@ senddata(struct tcp_socket *s) { int len = MIN(s->output_data_max_seg, uip_mss()); - if(s->output_data_len > 0) { - len = MIN(s->output_data_len, len); + if(s->output_senddata_len > 0) { + len = MIN(s->output_senddata_len, len); s->output_data_send_nxt = len; uip_send(s->output_data_ptr, len); } @@ -68,21 +70,27 @@ senddata(struct tcp_socket *s) static void acked(struct tcp_socket *s) { - if(s->output_data_len > 0) { + if(s->output_senddata_len > 0) { /* Copy the data in the outputbuf down and update outputbufptr and outputbuf_lastsent */ if(s->output_data_send_nxt > 0) { memcpy(&s->output_data_ptr[0], - &s->output_data_ptr[s->output_data_send_nxt], - s->output_data_maxlen - s->output_data_send_nxt); + &s->output_data_ptr[s->output_data_send_nxt], + s->output_data_maxlen - s->output_data_send_nxt); } if(s->output_data_len < s->output_data_send_nxt) { printf("tcp: acked assertion failed s->output_data_len (%d) < s->output_data_send_nxt (%d)\n", - s->output_data_len, - s->output_data_send_nxt); + s->output_data_len, + s->output_data_send_nxt); + tcp_markconn(uip_conn, NULL); + uip_abort(); + call_event(s, TCP_SOCKET_ABORTED); + relisten(s); + return; } s->output_data_len -= s->output_data_send_nxt; + s->output_senddata_len = s->output_data_len; s->output_data_send_nxt = 0; call_event(s, TCP_SOCKET_DATA_SENT); @@ -134,6 +142,11 @@ appcall(void *state) { struct tcp_socket *s = state; + if(s != NULL && s->c != NULL && s->c != uip_conn) { + /* Safe-guard: this should not happen, as the incoming event relates to + * a previous connection */ + return; + } if(uip_connected()) { /* Check if this connection originated in a local listen socket. We do this by checking the state pointer - if NULL, @@ -176,8 +189,10 @@ appcall(void *state) } if(uip_aborted()) { + tcp_markconn(uip_conn, NULL); call_event(s, TCP_SOCKET_ABORTED); relisten(s); + } if(s == NULL) { @@ -203,13 +218,16 @@ appcall(void *state) if(s->output_data_len == 0 && s->flags & TCP_SOCKET_FLAGS_CLOSING) { s->flags &= ~TCP_SOCKET_FLAGS_CLOSING; uip_close(); + s->c = NULL; tcp_markconn(uip_conn, NULL); - call_event(s, TCP_SOCKET_CLOSED); + s->c = NULL; + /*call_event(s, TCP_SOCKET_CLOSED);*/ relisten(s); } if(uip_closed()) { tcp_markconn(uip_conn, NULL); + s->c = NULL; call_event(s, TCP_SOCKET_CLOSED); relisten(s); } @@ -255,6 +273,7 @@ tcp_socket_register(struct tcp_socket *s, void *ptr, s->ptr = ptr; s->input_data_ptr = input_databuf; s->input_data_maxlen = input_databuf_len; + s->output_data_len = 0; s->output_data_ptr = output_databuf; s->output_data_maxlen = output_databuf_len; s->input_callback = input_callback; @@ -268,12 +287,15 @@ tcp_socket_register(struct tcp_socket *s, void *ptr, /*---------------------------------------------------------------------------*/ int tcp_socket_connect(struct tcp_socket *s, - uip_ipaddr_t *ipaddr, - uint16_t port) + const uip_ipaddr_t *ipaddr, + uint16_t port) { if(s == NULL) { return -1; } + if(s->c != NULL) { + tcp_markconn(s->c, NULL); + } PROCESS_CONTEXT_BEGIN(&tcp_socket_process); s->c = tcp_connect(ipaddr, uip_htons(port), s); PROCESS_CONTEXT_END(); @@ -317,7 +339,7 @@ tcp_socket_unlisten(struct tcp_socket *s) /*---------------------------------------------------------------------------*/ int tcp_socket_send(struct tcp_socket *s, - const uint8_t *data, int datalen) + const uint8_t *data, int datalen) { int len; @@ -329,6 +351,11 @@ tcp_socket_send(struct tcp_socket *s, memcpy(&s->output_data_ptr[s->output_data_len], data, len); s->output_data_len += len; + + if(s->output_senddata_len == 0) { + s->output_senddata_len = s->output_data_len; + } + return len; } /*---------------------------------------------------------------------------*/ @@ -365,3 +392,9 @@ tcp_socket_unregister(struct tcp_socket *s) return 1; } /*---------------------------------------------------------------------------*/ +int +tcp_socket_max_sendlen(struct tcp_socket *s) +{ + return s->output_data_maxlen - s->output_data_len; +} +/*---------------------------------------------------------------------------*/ diff --git a/core/net/ip/tcp-socket.h b/core/net/ip/tcp-socket.h index 208bc8288..34cb0d6b7 100644 --- a/core/net/ip/tcp-socket.h +++ b/core/net/ip/tcp-socket.h @@ -32,6 +32,8 @@ #ifndef TCP_SOCKET_H #define TCP_SOCKET_H +#include "uip.h" + struct tcp_socket; typedef enum { @@ -95,6 +97,7 @@ struct tcp_socket { uint16_t output_data_maxlen; uint16_t output_data_len; uint16_t output_data_send_nxt; + uint16_t output_senddata_len; uint16_t output_data_max_seg; uint8_t flags; @@ -170,7 +173,7 @@ int tcp_socket_register(struct tcp_socket *s, void *ptr, * */ int tcp_socket_connect(struct tcp_socket *s, - uip_ipaddr_t *ipaddr, + const uip_ipaddr_t *ipaddr, uint16_t port); /** @@ -266,4 +269,19 @@ int tcp_socket_close(struct tcp_socket *s); * */ int tcp_socket_unregister(struct tcp_socket *s); + +/** + * \brief The maximum amount of data that could currently be sent + * \param s A pointer to a TCP socket + * \return The number of bytes available in the output buffer + * + * This function queries the TCP socket and returns the + * number of bytes available in the output buffer. This + * function is used before calling tcp_socket_send() to + * ensure that one application level message can be held + * in the output buffer. + * + */ +int tcp_socket_max_sendlen(struct tcp_socket *s); + #endif /* TCP_SOCKET_H */ diff --git a/core/net/ip/tcpip.c b/core/net/ip/tcpip.c index 6f2744785..1c75d1bc9 100644 --- a/core/net/ip/tcpip.c +++ b/core/net/ip/tcpip.c @@ -228,7 +228,7 @@ packet_input(void) #if UIP_TCP #if UIP_ACTIVE_OPEN struct uip_conn * -tcp_connect(uip_ipaddr_t *ripaddr, uint16_t port, void *appstate) +tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate) { struct uip_conn *c; diff --git a/core/net/ip/tcpip.h b/core/net/ip/tcpip.h index 3fd64bce8..8fb2ff526 100644 --- a/core/net/ip/tcpip.h +++ b/core/net/ip/tcpip.h @@ -165,7 +165,7 @@ CCIF void tcp_unlisten(uint16_t port); * memory could not be allocated for the connection. * */ -CCIF struct uip_conn *tcp_connect(uip_ipaddr_t *ripaddr, uint16_t port, +CCIF struct uip_conn *tcp_connect(const uip_ipaddr_t *ripaddr, uint16_t port, void *appstate); /** diff --git a/core/net/ip/uip.h b/core/net/ip/uip.h index 78ebfef59..cb12f52ab 100644 --- a/core/net/ip/uip.h +++ b/core/net/ip/uip.h @@ -600,7 +600,7 @@ void uip_unlisten(uint16_t port); * or NULL if no connection could be allocated. * */ -struct uip_conn *uip_connect(uip_ipaddr_t *ripaddr, uint16_t port); +struct uip_conn *uip_connect(const uip_ipaddr_t *ripaddr, uint16_t port); @@ -1030,10 +1030,10 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport); #define uip_ipaddr_copy(dest, src) (*(dest) = *(src)) #endif #ifndef uip_ip4addr_copy -#define uip_ip4addr_copy(dest, src) (*(dest) = *(src)) +#define uip_ip4addr_copy(dest, src) (*((uip_ip4addr_t *)dest) = *((uip_ip4addr_t *)src)) #endif #ifndef uip_ip6addr_copy -#define uip_ip6addr_copy(dest, src) (*(dest) = *(src)) +#define uip_ip6addr_copy(dest, src) (*((uip_ip6addr_t *)dest) = *((uip_ip6addr_t *)src)) #endif /** diff --git a/core/net/ip64-addr/README.md b/core/net/ip64-addr/README.md deleted file mode 100644 index 258fb7905..000000000 --- a/core/net/ip64-addr/README.md +++ /dev/null @@ -1,5 +0,0 @@ -The `ip64-addr` module converts between IPv4 addresses and -IPv4-encoded IPv6 addresses. It is used in IPv6 networks that are -attached to the IPv4 world through an `ip64` router. With such a -router, IPv6 nodes in the network can reach IPv4 nodes by using their -IPv6-encoded address. diff --git a/core/net/ip64/ip64-addrmap.c b/core/net/ip64/ip64-addrmap.c index d7cfcb74f..3a36b2344 100644 --- a/core/net/ip64/ip64-addrmap.c +++ b/core/net/ip64/ip64-addrmap.c @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. @@ -148,6 +149,7 @@ ip64_addrmap_lookup(const uip_ip6addr_t *ip6addr, m->ip6port == ip6port && uip_ip4addr_cmp(&m->ip4addr, ip4addr) && uip_ip6addr_cmp(&m->ip6addr, ip6addr)) { + m->ip6to4++; return m; } } @@ -166,6 +168,7 @@ ip64_addrmap_lookup_port(uint16_t mapped_port, uint8_t protocol) m->protocol, protocol); if(m->mapped_port == mapped_port && m->protocol == protocol) { + m->ip4to6++; return m; } } @@ -204,6 +207,8 @@ ip64_addrmap_create(const uip_ip6addr_t *ip6addr, m->ip6port = ip6port; m->protocol = protocol; m->flags = FLAGS_NONE; + m->ip6to4 = 1; + m->ip4to6 = 0; timer_set(&m->timer, 0); /* Pick a new, unused local port. First make sure that the diff --git a/core/net/ip64/ip64-addrmap.h b/core/net/ip64/ip64-addrmap.h index a055efdd0..c4a31efcc 100644 --- a/core/net/ip64/ip64-addrmap.h +++ b/core/net/ip64/ip64-addrmap.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. @@ -40,6 +41,7 @@ struct ip64_addrmap_entry { struct timer timer; uip_ip6addr_t ip6addr; uip_ip4addr_t ip4addr; + uint32_t ip6to4, ip4to6; uint16_t mapped_port; uint16_t ip6port; uint16_t ip4port; diff --git a/core/net/ip64/ip64-conf-example.h b/core/net/ip64/ip64-conf-example.h index 33c1ff285..66102d5c8 100644 --- a/core/net/ip64/ip64-conf-example.h +++ b/core/net/ip64/ip64-conf-example.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. diff --git a/core/net/ip64/ip64-dns64.c b/core/net/ip64/ip64-dns64.c new file mode 100644 index 000000000..d9527629a --- /dev/null +++ b/core/net/ip64/ip64-dns64.c @@ -0,0 +1,259 @@ +/* + * 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. + * + */ + +#include "ip64.h" +#include "ip64-addr.h" +#include "ip64-dns64.h" + +#include + +#define DEBUG 0 + +#if DEBUG +#undef PRINTF +#define PRINTF(...) printf(__VA_ARGS__) +#else /* DEBUG */ +#define PRINTF(...) +#endif /* DEBUG */ + +struct dns_hdr { + uint8_t id[2]; + uint8_t flags1, flags2; +#define DNS_FLAG1_RESPONSE 0x80 +#define DNS_FLAG1_OPCODE_STATUS 0x10 +#define DNS_FLAG1_OPCODE_INVERSE 0x08 +#define DNS_FLAG1_OPCODE_STANDARD 0x00 +#define DNS_FLAG1_AUTHORATIVE 0x04 +#define DNS_FLAG1_TRUNC 0x02 +#define DNS_FLAG1_RD 0x01 +#define DNS_FLAG2_RA 0x80 +#define DNS_FLAG2_ERR_MASK 0x0f +#define DNS_FLAG2_ERR_NONE 0x00 +#define DNS_FLAG2_ERR_NAME 0x03 + uint8_t numquestions[2]; + uint8_t numanswers[2]; + uint8_t numauthrr[2]; + uint8_t numextrarr[2]; +}; + +#define DNS_QUESTION_TYPE0 0 +#define DNS_QUESTION_TYPE1 1 +#define DNS_QUESTION_CLASS0 2 +#define DNS_QUESTION_CLASS1 3 +#define DNS_QUESTION_SIZE 4 + +struct dns_answer { + /* DNS answer record starts with either a domain name or a pointer + * to a name already present somewhere in the packet. */ + uint8_t type[2]; + uint8_t class[2]; + uint8_t ttl[4]; + uint8_t len[2]; + union { + uint8_t ip6[16]; + uint8_t ip4[4]; + } addr; +}; + +#define DNS_TYPE_A 1 +#define DNS_TYPE_AAAA 28 + +#define DNS_CLASS_IN 1 +#define DNS_CLASS_ANY 255 + +/*---------------------------------------------------------------------------*/ +void +ip64_dns64_6to4(const uint8_t *ipv6data, int ipv6datalen, + uint8_t *ipv4data, int ipv4datalen) +{ + int i, j; + int qlen; + uint8_t *qdata; + uint8_t *q; + struct dns_hdr *hdr; + + hdr = (struct dns_hdr *)ipv4data; + PRINTF("ip64_dns64_6to4 id: %02x%02x\n", hdr->id[0], hdr->id[1]); + PRINTF("ip64_dns64_6to4 flags1: 0x%02x\n", hdr->flags1); + PRINTF("ip64_dns64_6to4 flags2: 0x%02x\n", hdr->flags2); + PRINTF("ip64_dns64_6to4 numquestions: 0x%02x\n", ((hdr->numquestions[0] << 8) + hdr->numquestions[1])); + PRINTF("ip64_dns64_6to4 numanswers: 0x%02x\n", ((hdr->numanswers[0] << 8) + hdr->numanswers[1])); + PRINTF("ip64_dns64_6to4 numauthrr: 0x%02x\n", ((hdr->numauthrr[0] << 8) + hdr->numauthrr[1])); + PRINTF("ip64_dns64_6to4 numextrarr: 0x%02x\n", ((hdr->numextrarr[0] << 8) + hdr->numextrarr[1])); + + /* Find the DNS question header by scanning through the question + labels. */ + qdata = ipv4data + sizeof(struct dns_hdr); + for(i = 0; i < ((hdr->numquestions[0] << 8) + hdr->numquestions[1]); i++) { + do { + qlen = *qdata; + qdata++; + for(j = 0; j < qlen; j++) { + qdata++; + if(qdata > ipv4data + ipv4datalen) { + PRINTF("ip64_dns64_6to4: packet ended while parsing\n"); + return; + } + } + } while(qlen != 0); + q = qdata; + if(q[DNS_QUESTION_CLASS0] == 0 && q[DNS_QUESTION_CLASS1] == DNS_CLASS_IN && + q[DNS_QUESTION_TYPE0] == 0 && q[DNS_QUESTION_TYPE1] == DNS_TYPE_AAAA) { + q[DNS_QUESTION_TYPE1] = DNS_TYPE_A; + } + + qdata += DNS_QUESTION_SIZE; + } +} +/*---------------------------------------------------------------------------*/ +int +ip64_dns64_4to6(const uint8_t *ipv4data, int ipv4datalen, + uint8_t *ipv6data, int ipv6datalen) +{ + uint8_t n; + int i, j; + int qlen, len; + const uint8_t *qdata, *adata; + uint8_t *qcopy, *acopy, *lenptr; + uint8_t *q; + struct dns_hdr *hdr; + + hdr = (struct dns_hdr *)ipv4data; + PRINTF("ip64_dns64_4to6 id: %02x%02x\n", hdr->id[0], hdr->id[1]); + PRINTF("ip64_dns64_4to6 flags1: 0x%02x\n", hdr->flags1); + PRINTF("ip64_dns64_4to6 flags2: 0x%02x\n", hdr->flags2); + PRINTF("ip64_dns64_4to6 numquestions: 0x%02x\n", ((hdr->numquestions[0] << 8) + hdr->numquestions[1])); + PRINTF("ip64_dns64_4to6 numanswers: 0x%02x\n", ((hdr->numanswers[0] << 8) + hdr->numanswers[1])); + PRINTF("ip64_dns64_4to6 numauthrr: 0x%02x\n", ((hdr->numauthrr[0] << 8) + hdr->numauthrr[1])); + PRINTF("ip64_dns64_4to6 numextrarr: 0x%02x\n", ((hdr->numextrarr[0] << 8) + hdr->numextrarr[1])); + + /* Find the DNS answer header by scanning through the question + labels. */ + qdata = ipv4data + sizeof(struct dns_hdr); + qcopy = ipv6data + sizeof(struct dns_hdr); + for(i = 0; i < ((hdr->numquestions[0] << 8) + hdr->numquestions[1]); i++) { + do { + qlen = *qdata; + qdata++; + qcopy++; + for(j = 0; j < qlen; j++) { + qdata++; + qcopy++; + if(qdata > ipv4data + ipv4datalen) { + PRINTF("ip64_dns64_4to6: packet ended while parsing\n"); + return ipv6datalen; + } + } + } while(qlen != 0); + q = qcopy; + if(q[DNS_QUESTION_CLASS0] == 0 && q[DNS_QUESTION_CLASS1] == DNS_CLASS_IN && + q[DNS_QUESTION_TYPE0] == 0 && q[DNS_QUESTION_TYPE1] == DNS_TYPE_AAAA) { + q[DNS_QUESTION_TYPE1] = DNS_TYPE_AAAA; + } + + qdata += DNS_QUESTION_SIZE; + qcopy += DNS_QUESTION_SIZE; + } + + adata = qdata; + acopy = qcopy; + + /* Go through the answers section and update the answers. */ + for(i = 0; i < ((hdr->numanswers[0] << 8) + hdr->numanswers[1]); i++) { + + n = *adata; + if(n & 0xc0) { + /* Short-hand name format: 2 bytes */ + *acopy++ = *adata++; + *acopy++ = *adata++; + } else { + /* Name spelled out */ + do { + n = *adata; + adata++; + acopy++; + for(j = 0; j < n; j++) { + *acopy++ = *adata++; + } + } while(n != 0); + } + + if(adata[0] == 0 && adata[1] == DNS_TYPE_A) { + /* Update the type field from A to AAAA */ + *acopy = *adata; + acopy++; + adata++; + *acopy = DNS_TYPE_AAAA; + acopy++; + adata++; + + /* Get the length of the address record. Should be 4. */ + lenptr = &acopy[6]; + len = (adata[6] << 8) + adata[7]; + + /* Copy the class, the TTL, and the data length */ + memcpy(acopy, adata, 2 + 4 + 2); + acopy += 8; + adata += 8; + + if(len == 4) { + uip_ip4addr_t addr; + uip_ipaddr(&addr, adata[0], adata[1], adata[2], adata[3]); + ip64_addr_4to6(&addr, (uip_ip6addr_t *)acopy); + + adata += len; + acopy += 16; + lenptr[0] = 0; + lenptr[1] = 16; + ipv6datalen += 12; + + } else { + memcpy(acopy, adata, len); + acopy += len; + adata += len; + } + } else { + len = (adata[8] << 8) + adata[9]; + + /* Copy the type, class, the TTL, and the data length */ + memcpy(acopy, adata, 2 + 2 + 4 + 2); + acopy += 10; + adata += 10; + + /* Copy the data */ + memcpy(acopy, adata, len); + acopy += len; + adata += len; + } + } + return ipv6datalen; +} +/*---------------------------------------------------------------------------*/ diff --git a/core/net/ip64/ip64-dns64.h b/core/net/ip64/ip64-dns64.h new file mode 100644 index 000000000..27eb73127 --- /dev/null +++ b/core/net/ip64/ip64-dns64.h @@ -0,0 +1,40 @@ +/* + * 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. + * + */ + +#ifndef IP64_DNS64_H_ +#define IP64_DNS64_H_ + +void ip64_dns64_6to4(const uint8_t *ipv6data, int ipv6datalen, + uint8_t *ipv4data, int ipv4datalen); +int ip64_dns64_4to6(const uint8_t *ipv4data, int ipv4datalen, + uint8_t *ipv6data, int ipv6datalen); + +#endif /* IP64_DNS64_H_ */ diff --git a/core/net/ip64/ip64-driver.h b/core/net/ip64/ip64-driver.h index 9de5d44a3..50b00cfd9 100644 --- a/core/net/ip64/ip64-driver.h +++ b/core/net/ip64/ip64-driver.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. diff --git a/core/net/ip64/ip64-eth-interface.c b/core/net/ip64/ip64-eth-interface.c index d2d941e2a..42f6234cc 100644 --- a/core/net/ip64/ip64-eth-interface.c +++ b/core/net/ip64/ip64-eth-interface.c @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. diff --git a/core/net/ip64/ip64-eth-interface.h b/core/net/ip64/ip64-eth-interface.h index 83dc6ab53..21bbd947f 100644 --- a/core/net/ip64/ip64-eth-interface.h +++ b/core/net/ip64/ip64-eth-interface.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. diff --git a/core/net/ip64/ip64-eth.c b/core/net/ip64/ip64-eth.c index 1f6c67525..0a717c625 100644 --- a/core/net/ip64/ip64-eth.c +++ b/core/net/ip64/ip64-eth.c @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. diff --git a/core/net/ip64/ip64-eth.h b/core/net/ip64/ip64-eth.h index 3f5982df3..aa9448a86 100644 --- a/core/net/ip64/ip64-eth.h +++ b/core/net/ip64/ip64-eth.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. diff --git a/core/net/ip64/ip64-interface.h b/core/net/ip64/ip64-interface.h index 0e304ed37..574ae1c7f 100644 --- a/core/net/ip64/ip64-interface.h +++ b/core/net/ip64/ip64-interface.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. diff --git a/core/net/ip64/ip64-ipv4-dhcp.c b/core/net/ip64/ip64-ipv4-dhcp.c index 6381fa179..ab8c6a517 100644 --- a/core/net/ip64/ip64-ipv4-dhcp.c +++ b/core/net/ip64/ip64-ipv4-dhcp.c @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. diff --git a/core/net/ip64/ip64-ipv4-dhcp.h b/core/net/ip64/ip64-ipv4-dhcp.h index c0ebdf52f..295af6854 100644 --- a/core/net/ip64/ip64-ipv4-dhcp.h +++ b/core/net/ip64/ip64-ipv4-dhcp.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. diff --git a/core/net/ip64/ip64-null-driver.c b/core/net/ip64/ip64-null-driver.c index 95f2b1f72..dafef5ea5 100644 --- a/core/net/ip64/ip64-null-driver.c +++ b/core/net/ip64/ip64-null-driver.c @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. diff --git a/core/net/ip64/ip64-null-driver.h b/core/net/ip64/ip64-null-driver.h index 2a9ad0711..f77691154 100644 --- a/core/net/ip64/ip64-null-driver.h +++ b/core/net/ip64/ip64-null-driver.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. diff --git a/core/net/ip64/ip64-slip-interface.c b/core/net/ip64/ip64-slip-interface.c index dab563f51..05fe704c7 100644 --- a/core/net/ip64/ip64-slip-interface.c +++ b/core/net/ip64/ip64-slip-interface.c @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. diff --git a/core/net/ip64/ip64-slip-interface.h b/core/net/ip64/ip64-slip-interface.h index eecb14395..c3cf26a2f 100644 --- a/core/net/ip64/ip64-slip-interface.h +++ b/core/net/ip64/ip64-slip-interface.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. diff --git a/core/net/ip64/ip64.c b/core/net/ip64/ip64.c index f058f1d22..e00e1e443 100644 --- a/core/net/ip64/ip64.c +++ b/core/net/ip64/ip64.c @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. @@ -58,7 +59,8 @@ #include "ip64-special-ports.h" #include "ip64-eth-interface.h" #include "ip64-slip-interface.h" - +#include "ip64-dns64.h" +#include "net/ipv6/uip-ds6.h" #include "ip64-ipv4-dhcp.h" #include "contiki-net.h" @@ -172,6 +174,8 @@ static uip_ip4addr_t ipv4_broadcast_addr; #define TCP_SYN 0x02 #define TCP_RST 0x04 +#define DNS_PORT 53 + /*---------------------------------------------------------------------------*/ void ip64_init(void) @@ -366,7 +370,7 @@ ip64_6to4(const uint8_t *ipv6packet, const uint16_t ipv6packet_len, struct icmpv6_hdr *icmpv6hdr; uint16_t ipv6len, ipv4len; struct ip64_addrmap_entry *m; - + v6hdr = (struct ipv6_hdr *)ipv6packet; v4hdr = (struct ipv4_hdr *)resultpacket; @@ -434,6 +438,15 @@ ip64_6to4(const uint8_t *ipv6packet, const uint16_t ipv6packet_len, case IP_PROTO_UDP: PRINTF("ip64_6to4: UDP header\n"); v4hdr->proto = IP_PROTO_UDP; + + /* Check if this is a DNS request. If so, we should rewrite it + with the DNS64 module. */ + if(udphdr->destport == UIP_HTONS(DNS_PORT)) { + ip64_dns64_6to4((uint8_t *)v6hdr + IPV6_HDRLEN + sizeof(struct udp_hdr), + ipv6len - IPV6_HDRLEN - sizeof(struct udp_hdr), + (uint8_t *)udphdr + sizeof(struct udp_hdr), + BUFSIZE - IPV4_HDRLEN - sizeof(struct udp_hdr)); + } /* Compute and check the UDP checksum - since we're going to recompute it ourselves, we must ensure that it was correct in the first place. */ @@ -572,9 +585,18 @@ ip64_6to4(const uint8_t *ipv6packet, const uint16_t ipv6packet_len, } else { ip64_addrmap_set_lifetime(m, DEFAULT_LIFETIME); - /* Treat DNS requests specially: since the are one-shot, we + /* Treat UDP packets from the IPv6 network to a multicast + address on the IPv4 network differently: since there is + no way for packets from the IPv4 network to go back to + the IPv6 network on these mappings, we'll mark them as + recyclable. */ + if(v4hdr->destipaddr.u8[0] == 224) { + ip64_addrmap_set_recycleble(m); + } + + /* Treat DNS requests differently: since the are one-shot, we mark them as recyclable. */ - if(udphdr->destport == UIP_HTONS(53)) { + if(udphdr->destport == UIP_HTONS(DNS_PORT)) { ip64_addrmap_set_recycleble(m); } } @@ -706,6 +728,21 @@ ip64_4to6(const uint8_t *ipv4packet, const uint16_t ipv4packet_len, switch(v4hdr->proto) { case IP_PROTO_UDP: v6hdr->nxthdr = IP_PROTO_UDP; + /* Check if this is a DNS request. If so, we should rewrite it + with the DNS64 module. */ + if(udphdr->srcport == UIP_HTONS(DNS_PORT)) { + int len; + + len = ip64_dns64_4to6((uint8_t *)v4hdr + IPV4_HDRLEN + sizeof(struct udp_hdr), + ipv4len - IPV4_HDRLEN - sizeof(struct udp_hdr), + (uint8_t *)v6hdr + IPV6_HDRLEN + sizeof(struct udp_hdr), + ipv6_packet_len - sizeof(struct udp_hdr)); + ipv6_packet_len = len + sizeof(struct udp_hdr); + v6hdr->len[0] = ipv6_packet_len >> 8; + v6hdr->len[1] = ipv6_packet_len & 0xff; + ipv6len = ipv6_packet_len + IPV6_HDRLEN; + + } break; case IP_PROTO_TCP: diff --git a/core/net/ip64/ip64.h b/core/net/ip64/ip64.h index 58cda4511..50d37d691 100644 --- a/core/net/ip64/ip64.h +++ b/core/net/ip64/ip64.h @@ -10,6 +10,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. diff --git a/core/net/ipv4/uip-over-mesh.c b/core/net/ipv4/uip-over-mesh.c index 92c5dbfd4..e6709f1d4 100644 --- a/core/net/ipv4/uip-over-mesh.c +++ b/core/net/ipv4/uip-over-mesh.c @@ -262,8 +262,8 @@ uip_over_mesh_send(void) if(BUF->proto == UIP_PROTO_TCP) { #if NETSTACK_CONF_WITH_RIME packetbuf_set_attr(PACKETBUF_ATTR_ERELIABLE, 1); -#endif /* NETSTACK_CONF_WITH_RIME */ packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1); +#endif /* NETSTACK_CONF_WITH_RIME */ /* packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_STREAM);*/ } diff --git a/core/net/ipv4/uip.c b/core/net/ipv4/uip.c index 1c767e170..1c3c24aaf 100644 --- a/core/net/ipv4/uip.c +++ b/core/net/ipv4/uip.c @@ -78,6 +78,8 @@ #include "net/ipv4/uip-neighbor.h" #include +#include "sys/cc.h" + /*---------------------------------------------------------------------------*/ /* Variable definitions. */ @@ -386,7 +388,7 @@ uip_init(void) /*---------------------------------------------------------------------------*/ #if UIP_ACTIVE_OPEN struct uip_conn * -uip_connect(uip_ipaddr_t *ripaddr, uint16_t rport) +uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport) { register struct uip_conn *conn, *cconn; @@ -1953,7 +1955,6 @@ void uip_send(const void *data, int len) { int copylen; -#define MIN(a,b) ((a) < (b)? (a): (b)) copylen = MIN(len, UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN - (int)((char *)uip_sappdata - (char *)&uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN])); if(copylen > 0) { diff --git a/core/net/ipv6/sicslowpan.c b/core/net/ipv6/sicslowpan.c index 3be5a0f2a..62b9014c5 100644 --- a/core/net/ipv6/sicslowpan.c +++ b/core/net/ipv6/sicslowpan.c @@ -1336,11 +1336,6 @@ send_packet(linkaddr_t *dest) packetbuf_set_addr(PACKETBUF_ADDR_SENDER,(void*)&uip_lladdr); #endif - /* Force acknowledge from sender (test hardware autoacks) */ -#if SICSLOWPAN_CONF_ACK_ALL - packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1); -#endif - /* Provide a callback function to receive the result of a packet transmission. */ NETSTACK_LLSEC.send(&packet_sent, NULL); @@ -1388,6 +1383,7 @@ output(const uip_lladdr_t *localdest) set_packet_attrs(); } +#if PACKETBUF_WITH_PACKET_TYPE #define TCP_FIN 0x01 #define TCP_ACK 0x10 #define TCP_CTL 0x3f @@ -1402,6 +1398,7 @@ output(const uip_lladdr_t *localdest) packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_STREAM_END); } +#endif /* * The destination address will be tagged to each outbound diff --git a/core/net/ipv6/uip-ds6-route.c b/core/net/ipv6/uip-ds6-route.c index 3931319a0..49e3d3588 100644 --- a/core/net/ipv6/uip-ds6-route.c +++ b/core/net/ipv6/uip-ds6-route.c @@ -280,7 +280,7 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, if(r != NULL) { uip_ipaddr_t *current_nexthop; current_nexthop = uip_ds6_route_nexthop(r); - if(uip_ipaddr_cmp(nexthop, current_nexthop)) { + if(current_nexthop != NULL && uip_ipaddr_cmp(nexthop, current_nexthop)) { /* no need to update route - already correct! */ return r; } diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index 701f458fa..72b1badfa 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -116,17 +116,20 @@ void uip_log(char *msg); #define UIP_ND6_OPT_RDNSS_BUF ((uip_nd6_opt_dns *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) /** @} */ +#if UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER static uint8_t nd6_opt_offset; /** Offset from the end of the icmpv6 header to the option in uip_buf*/ static uint8_t *nd6_opt_llao; /** Pointer to llao option in uip_buf */ +static uip_ds6_nbr_t *nbr; /** Pointer to a nbr cache entry*/ +static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */ +static uip_ds6_addr_t *addr; /** Pointer to an interface address */ +#endif /* UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER */ #if !UIP_CONF_ROUTER // TBD see if we move it to ra_input static uip_nd6_opt_prefix_info *nd6_opt_prefix_info; /** Pointer to prefix information option in uip_buf */ static uip_ipaddr_t ipaddr; static uip_ds6_prefix_t *prefix; /** Pointer to a prefix list entry */ #endif -static uip_ds6_nbr_t *nbr; /** Pointer to a nbr cache entry*/ -static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */ -static uip_ds6_addr_t *addr; /** Pointer to an interface address */ + /*------------------------------------------------------------------*/ /* create a llao */ static void @@ -141,7 +144,7 @@ create_llao(uint8_t *llao, uint8_t type) { /*------------------------------------------------------------------*/ - +#if UIP_ND6_SEND_NA static void ns_input(void) { @@ -321,7 +324,7 @@ discard: uip_len = 0; return; } - +#endif /* UIP_ND6_SEND_NA */ /*------------------------------------------------------------------*/ @@ -387,6 +390,7 @@ uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt) PRINTF("\n"); return; } +#if UIP_ND6_SEND_NA /*------------------------------------------------------------------*/ /** * Neighbor Advertisement Processing @@ -556,7 +560,7 @@ discard: uip_len = 0; return; } - +#endif /* UIP_ND6_SEND_NA */ #if UIP_CONF_ROUTER #if UIP_ND6_SEND_RA @@ -859,7 +863,7 @@ ra_input(void) (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 1, NBR_STALE); } else { - uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr); + uip_lladdr_t *lladdr = (uip_lladdr_t *)uip_ds6_nbr_get_ll(nbr); if(nbr->state == NBR_INCOMPLETE) { nbr->state = NBR_STALE; } diff --git a/core/net/ipv6/uip6.c b/core/net/ipv6/uip6.c index a5d1db13c..73abd1115 100644 --- a/core/net/ipv6/uip6.c +++ b/core/net/ipv6/uip6.c @@ -71,6 +71,7 @@ * the packet back to the peer. */ +#include "sys/cc.h" #include "net/ip/uip.h" #include "net/ip/uipopt.h" #include "net/ipv6/uip-icmp6.h" @@ -459,7 +460,7 @@ uip_init(void) /*---------------------------------------------------------------------------*/ #if UIP_TCP && UIP_ACTIVE_OPEN struct uip_conn * -uip_connect(uip_ipaddr_t *ripaddr, uint16_t rport) +uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport) { register struct uip_conn *conn, *cconn; @@ -2332,7 +2333,6 @@ void uip_send(const void *data, int len) { int copylen; -#define MIN(a,b) ((a) < (b)? (a): (b)) if(uip_sappdata != NULL) { copylen = MIN(len, UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN - diff --git a/core/net/mac/contikimac/contikimac.c b/core/net/mac/contikimac/contikimac.c index cdfffc13b..7aea60928 100644 --- a/core/net/mac/contikimac/contikimac.c +++ b/core/net/mac/contikimac/contikimac.c @@ -229,10 +229,6 @@ static struct compower_activity current_packet; #define DEFAULT_STREAM_TIME (4 * CYCLE_TIME) -#ifndef MIN -#define MIN(a, b) ((a) < (b)? (a) : (b)) -#endif /* MIN */ - #if CONTIKIMAC_CONF_BROADCAST_RATE_LIMIT static struct timer broadcast_rate_timer; static int broadcast_rate_counter; @@ -341,7 +337,6 @@ powercycle(struct rtimer *t, void *ptr) while(1) { static uint8_t packet_seen; - static rtimer_clock_t t0; static uint8_t count; #if SYNC_CYCLE_STARTS @@ -365,7 +360,6 @@ powercycle(struct rtimer *t, void *ptr) packet_seen = 0; for(count = 0; count < CCA_COUNT_MAX; ++count) { - t0 = RTIMER_NOW(); if(we_are_sending == 0 && we_are_receiving_burst == 0) { powercycle_turn_radio_on(); /* Check if a packet is seen in the air. If so, we keep the @@ -499,7 +493,6 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, uint8_t got_strobe_ack = 0; int len; uint8_t is_broadcast = 0; - uint8_t is_reliable = 0; uint8_t is_known_receiver = 0; uint8_t collisions; int transmit_len; @@ -546,11 +539,6 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]); #endif /* NETSTACK_CONF_WITH_IPV6 */ } - is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) -#if NETSTACK_CONF_WITH_RIME - || packetbuf_attr(PACKETBUF_ATTR_ERELIABLE) -#endif /* NETSTACK_CONF_WITH_RIME */ - ; if(!packetbuf_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED)) { packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); @@ -672,11 +660,12 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, { rtimer_clock_t wt; - rtimer_clock_t txtime; - int ret; - - txtime = RTIMER_NOW(); - ret = NETSTACK_RADIO.transmit(transmit_len); + rtimer_clock_t txtime = RTIMER_NOW(); +#if RDC_CONF_HARDWARE_ACK + int ret = NETSTACK_RADIO.transmit(transmit_len); +#else + NETSTACK_RADIO.transmit(transmit_len); +#endif #if RDC_CONF_HARDWARE_ACK /* For radios that block in the transmit routine and detect the diff --git a/core/net/mac/csma.c b/core/net/mac/csma.c index 6ede3ec8d..ab6fec726 100644 --- a/core/net/mac/csma.c +++ b/core/net/mac/csma.c @@ -373,11 +373,13 @@ send_packet(mac_callback_t sent, void *ptr) } metadata->sent = sent; metadata->cptr = ptr; - +#if PACKETBUF_WITH_PACKET_TYPE if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_ACK) { list_push(n->queued_packet_list, q); - } else { + } else +#endif + { list_add(n->queued_packet_list, q); } diff --git a/core/net/mac/cxmac/cxmac.c b/core/net/mac/cxmac/cxmac.c index ebf7651dd..e07fde3d9 100644 --- a/core/net/mac/cxmac/cxmac.c +++ b/core/net/mac/cxmac/cxmac.c @@ -52,6 +52,7 @@ #include "sys/rtimer.h" #include "contiki-conf.h" +#include "sys/cc.h" #ifdef EXPERIMENT_SETUP #include "experiment-setup.h" @@ -215,10 +216,6 @@ static linkaddr_t is_streaming_to, is_streaming_to_too; static rtimer_clock_t stream_until; #define DEFAULT_STREAM_TIME (RTIMER_ARCH_SECOND) -#ifndef MIN -#define MIN(a, b) ((a) < (b)? (a) : (b)) -#endif /* MIN */ - /*---------------------------------------------------------------------------*/ static void on(void) @@ -453,8 +450,6 @@ send_packet(void) packetbuf_addr(PACKETBUF_ADDR_RECEIVER)->u8[1]); #endif /* NETSTACK_CONF_WITH_IPV6 */ } -/* is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) || - packetbuf_attr(PACKETBUF_ATTR_ERELIABLE);*/ len = NETSTACK_FRAMER.create(); strobe_len = len + sizeof(struct cxmac_hdr); if(len < 0 || strobe_len > (int)sizeof(strobe)) { @@ -475,7 +470,7 @@ send_packet(void) return MAC_TX_ERR; } -#if WITH_STREAMING +#if WITH_STREAMING && PACKETBUF_WITH_PACKET_TYPE if(is_streaming == 1 && (linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &is_streaming_to) || @@ -519,7 +514,7 @@ send_packet(void) wait = ((rtimer_clock_t)(e->time - now)) % (DEFAULT_PERIOD); expected = now + wait - 2 * DEFAULT_ON_TIME; -#if WITH_ACK_OPTIMIZATION +#if WITH_ACK_OPTIMIZATION && PACKETBUF_WITH_PACKET_TYPE /* Wait until the receiver is expected to be awake */ if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) != PACKETBUF_ATTR_PACKET_TYPE_ACK && @@ -624,12 +619,16 @@ send_packet(void) /* If we have received the strobe ACK, and we are sending a packet that will need an upper layer ACK (as signified by the PACKETBUF_ATTR_RELIABLE packet attribute), we keep the radio on. */ - if(got_strobe_ack && (packetbuf_attr(PACKETBUF_ATTR_RELIABLE) || + if(got_strobe_ack && ( #if NETSTACK_CONF_WITH_RIME + packetbuf_attr(PACKETBUF_ATTR_RELIABLE) || packetbuf_attr(PACKETBUF_ATTR_ERELIABLE) || #endif /* NETSTACK_CONF_WITH_RIME */ +#if PACKETBUF_WITH_PACKET_TYPE packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == - PACKETBUF_ATTR_PACKET_TYPE_STREAM)) { + PACKETBUF_ATTR_PACKET_TYPE_STREAM || +#endif + 0)) { on(); /* Wait for ACK packet */ waiting_for_packet = 1; } else { diff --git a/core/net/mac/framer-802154.c b/core/net/mac/framer-802154.c index 03b091feb..987d142ba 100644 --- a/core/net/mac/framer-802154.c +++ b/core/net/mac/framer-802154.c @@ -242,8 +242,10 @@ parse(void) } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr); packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending); - /* packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, frame.fcf.ack_required);*/ + packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq); +#if NETSTACK_CONF_WITH_RIME packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq); +#endif #if LLSEC802154_SECURITY_LEVEL if(frame.fcf.security_enabled) { diff --git a/core/net/mac/mac-sequence.c b/core/net/mac/mac-sequence.c index 638dece13..40ac3c28a 100644 --- a/core/net/mac/mac-sequence.c +++ b/core/net/mac/mac-sequence.c @@ -74,7 +74,7 @@ mac_sequence_is_duplicate(void) for(i = 0; i < MAX_SEQNOS; ++i) { if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), &received_seqnos[i].sender)) { - if(packetbuf_attr(PACKETBUF_ATTR_PACKET_ID) == received_seqnos[i].seqno) { + if(packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO) == received_seqnos[i].seqno) { /* Duplicate packet. */ return 1; } @@ -102,7 +102,7 @@ mac_sequence_register_seqno(void) for(j = i - 1; j > 0; --j) { memcpy(&received_seqnos[j], &received_seqnos[j - 1], sizeof(struct seqno)); } - received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); + received_seqnos[0].seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO); linkaddr_copy(&received_seqnos[0].sender, packetbuf_addr(PACKETBUF_ADDR_SENDER)); } diff --git a/core/net/mac/nullrdc.c b/core/net/mac/nullrdc.c index 3403b764e..111211a2b 100644 --- a/core/net/mac/nullrdc.c +++ b/core/net/mac/nullrdc.c @@ -264,11 +264,13 @@ send_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list) static void packet_input(void) { +#if NULLRDC_SEND_802154_ACK int original_datalen; uint8_t *original_dataptr; original_datalen = packetbuf_datalen(); original_dataptr = packetbuf_dataptr(); +#endif #if NULLRDC_802154_AUTOACK if(packetbuf_datalen() == ACK_LEN) { @@ -294,7 +296,7 @@ packet_input(void) if(duplicate) { /* Drop the packet. */ PRINTF("nullrdc: drop duplicate link layer packet %u\n", - packetbuf_attr(PACKETBUF_ATTR_PACKET_ID)); + packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)); } else { mac_sequence_register_seqno(); } diff --git a/core/net/mac/sicslowmac/sicslowmac.c b/core/net/mac/sicslowmac/sicslowmac.c index 9d88a6b78..09d77ae17 100644 --- a/core/net/mac/sicslowmac/sicslowmac.c +++ b/core/net/mac/sicslowmac/sicslowmac.c @@ -106,7 +106,9 @@ send_packet(mac_callback_t sent, void *ptr) params.fcf.frame_type = FRAME802154_DATAFRAME; params.fcf.security_enabled = 0; params.fcf.frame_pending = 0; +#if NETSTACK_CONF_WITH_RIME params.fcf.ack_required = packetbuf_attr(PACKETBUF_ATTR_RELIABLE); +#endif params.fcf.panid_compression = 0; /* Insert IEEE 802.15.4 (2003) version bit. */ diff --git a/core/net/packetbuf.c b/core/net/packetbuf.c index 6e4c3e720..217f40bc2 100644 --- a/core/net/packetbuf.c +++ b/core/net/packetbuf.c @@ -106,10 +106,7 @@ packetbuf_compact(void) { int i, len; - if(packetbuf_is_reference()) { - memcpy(&packetbuf[PACKETBUF_HDR_SIZE], packetbuf_reference_ptr(), - packetbuf_datalen()); - } else if(bufptr > 0) { + if(bufptr > 0) { len = packetbuf_datalen() + PACKETBUF_HDR_SIZE; for(i = PACKETBUF_HDR_SIZE; i < len; i++) { packetbuf[i] = packetbuf[bufptr + i]; @@ -215,26 +212,6 @@ packetbuf_hdrptr(void) return (void *)(&packetbuf[hdrptr]); } /*---------------------------------------------------------------------------*/ -void -packetbuf_reference(void *ptr, uint16_t len) -{ - packetbuf_clear(); - packetbufptr = ptr; - buflen = len; -} -/*---------------------------------------------------------------------------*/ -int -packetbuf_is_reference(void) -{ - return packetbufptr != &packetbuf[PACKETBUF_HDR_SIZE]; -} -/*---------------------------------------------------------------------------*/ -void * -packetbuf_reference_ptr(void) -{ - return packetbufptr; -} -/*---------------------------------------------------------------------------*/ uint16_t packetbuf_datalen(void) { diff --git a/core/net/packetbuf.h b/core/net/packetbuf.h index 048493897..3c1839bf1 100644 --- a/core/net/packetbuf.h +++ b/core/net/packetbuf.h @@ -74,6 +74,12 @@ #define PACKETBUF_HDR_SIZE 48 #endif +#ifdef PACKETBUF_CONF_WITH_PACKET_TYPE +#define PACKETBUF_WITH_PACKET_TYPE PACKETBUF_CONF_WITH_PACKET_TYPE +#else +#define PACKETBUF_WITH_PACKET_TYPE NETSTACK_CONF_WITH_RIME +#endif + /** * \brief Clear and reset the packetbuf * @@ -181,52 +187,12 @@ uint16_t packetbuf_totlen(void); */ void packetbuf_set_datalen(uint16_t len); -/** - * \brief Point the packetbuf to external data - * \param ptr A pointer to the external data - * \param len The length of the external data - * - * For outbound packets, the packetbuf consists of two - * parts: header and data. This function is used to make - * the packetbuf point to external data. The function also - * specifies the length of the external data that the - * packetbuf references. - */ -void packetbuf_reference(void *ptr, uint16_t len); - -/** - * \brief Check if the packetbuf references external data - * \retval Non-zero if the packetbuf references external data, zero otherwise. - * - * For outbound packets, the packetbuf consists of two - * parts: header and data. This function is used to check - * if the packetbuf points to external data that has - * previously been referenced with packetbuf_reference(). - * - */ -int packetbuf_is_reference(void); - -/** - * \brief Get a pointer to external data referenced by the packetbuf - * \retval A pointer to the external data - * - * For outbound packets, the packetbuf consists of two - * parts: header and data. The data may point to external - * data that has previously been referenced with - * packetbuf_reference(). This function is used to get a - * pointer to the external data. - * - */ -void *packetbuf_reference_ptr(void); - /** * \brief Compact the packetbuf * * This function compacts the packetbuf by copying the data * portion of the packetbuf so that becomes consecutive to - * the header. It also copies external data that has - * previously been referenced with packetbuf_reference() - * into the packetbuf. + * the header. * * This function is called by the Rime code before a * packet is to be sent by a device driver. This assures @@ -257,9 +223,7 @@ int packetbuf_copyfrom(const void *from, uint16_t len); * * This function copies the packetbuf to an external * buffer. Both the data portion and the header portion of - * the packetbuf is copied. If the packetbuf referenced - * external data (referenced with packetbuf_reference()) the - * external data is copied. + * the packetbuf is copied. * * The external buffer to which the packetbuf is to be * copied must be able to accomodate at least @@ -351,10 +315,12 @@ enum { PACKETBUF_ATTR_IS_CREATED_AND_SECURED, /* Scope 1 attributes: used between two neighbors only. */ - PACKETBUF_ATTR_RELIABLE, - PACKETBUF_ATTR_PACKET_ID, +#if PACKETBUF_WITH_PACKET_TYPE PACKETBUF_ATTR_PACKET_TYPE, +#endif #if NETSTACK_CONF_WITH_RIME + PACKETBUF_ATTR_PACKET_ID, + PACKETBUF_ATTR_RELIABLE, PACKETBUF_ATTR_REXMIT, PACKETBUF_ATTR_MAX_REXMIT, PACKETBUF_ATTR_NUM_REXMIT, diff --git a/core/net/queuebuf.c b/core/net/queuebuf.c index 72c35c3c6..8a9ebfe8a 100644 --- a/core/net/queuebuf.c +++ b/core/net/queuebuf.c @@ -43,18 +43,13 @@ */ #include "contiki-net.h" + #if WITH_SWAP #include "cfs/cfs.h" #endif #include /* for memcpy() */ -#ifdef QUEUEBUF_CONF_REF_NUM -#define QUEUEBUF_REF_NUM QUEUEBUF_CONF_REF_NUM -#else -#define QUEUEBUF_REF_NUM 2 -#endif - /* Structure pointing to a buffer either stored in RAM or swapped in CFS */ struct queuebuf { @@ -83,15 +78,7 @@ struct queuebuf_data { struct packetbuf_addr addrs[PACKETBUF_NUM_ADDRS]; }; -struct queuebuf_ref { - uint16_t len; - uint8_t *ref; - uint8_t hdr[PACKETBUF_HDR_SIZE]; - uint8_t hdrlen; -}; - MEMB(bufmem, struct queuebuf, QUEUEBUF_NUM); -MEMB(refbufmem, struct queuebuf_ref, QUEUEBUF_REF_NUM); MEMB(buframmem, struct queuebuf_data, QUEUEBUFRAM_NUM); #if WITH_SWAP @@ -144,7 +131,7 @@ LIST(queuebuf_list); #endif /* QUEUEBUF_CONF_STATS */ #if QUEUEBUF_STATS -uint8_t queuebuf_len, queuebuf_ref_len, queuebuf_max_len; +uint8_t queuebuf_len, queuebuf_max_len; #endif /* QUEUEBUF_STATS */ #if WITH_SWAP @@ -301,20 +288,15 @@ queuebuf_init(void) #endif memb_init(&buframmem); memb_init(&bufmem); - memb_init(&refbufmem); #if QUEUEBUF_STATS - queuebuf_max_len = QUEUEBUF_NUM; + queuebuf_max_len = 0; #endif /* QUEUEBUF_STATS */ } /*---------------------------------------------------------------------------*/ int queuebuf_numfree(void) { - if(packetbuf_is_reference()) { - return memb_numfree(&refbufmem); - } else { - return memb_numfree(&bufmem); - } + return memb_numfree(&bufmem); } /*---------------------------------------------------------------------------*/ #if QUEUEBUF_DEBUG @@ -326,81 +308,62 @@ queuebuf_new_from_packetbuf(void) #endif /* QUEUEBUF_DEBUG */ { struct queuebuf *buf; - struct queuebuf_ref *rbuf; - if(packetbuf_is_reference()) { - rbuf = memb_alloc(&refbufmem); - if(rbuf != NULL) { -#if QUEUEBUF_STATS - ++queuebuf_ref_len; -#endif /* QUEUEBUF_STATS */ - rbuf->len = packetbuf_datalen(); - rbuf->ref = packetbuf_reference_ptr(); - rbuf->hdrlen = packetbuf_copyto_hdr(rbuf->hdr); - } else { - PRINTF("queuebuf_new_from_packetbuf: could not allocate a reference queuebuf\n"); - } - return (struct queuebuf *)rbuf; - } else { - struct queuebuf_data *buframptr; - buf = memb_alloc(&bufmem); - if(buf != NULL) { + struct queuebuf_data *buframptr; + buf = memb_alloc(&bufmem); + if(buf != NULL) { #if QUEUEBUF_DEBUG - list_add(queuebuf_list, buf); - buf->file = file; - buf->line = line; - buf->time = clock_time(); + list_add(queuebuf_list, buf); + buf->file = file; + buf->line = line; + buf->time = clock_time(); #endif /* QUEUEBUF_DEBUG */ - buf->ram_ptr = memb_alloc(&buframmem); + buf->ram_ptr = memb_alloc(&buframmem); #if WITH_SWAP - /* If the allocation failed, store the qbuf in swap files */ - if(buf->ram_ptr != NULL) { - buf->location = IN_RAM; - buframptr = buf->ram_ptr; - } else { - buf->location = IN_CFS; - buf->swap_id = -1; - tmpdata_qbuf = buf; - buframptr = &tmpdata; - } + /* If the allocation failed, store the qbuf in swap files */ + if(buf->ram_ptr != NULL) { + buf->location = IN_RAM; + buframptr = buf->ram_ptr; + } else { + buf->location = IN_CFS; + buf->swap_id = -1; + tmpdata_qbuf = buf; + buframptr = &tmpdata; + } #else - if(buf->ram_ptr == NULL) { - PRINTF("queuebuf_new_from_packetbuf: could not queuebuf data\n"); + if(buf->ram_ptr == NULL) { + PRINTF("queuebuf_new_from_packetbuf: could not queuebuf data\n"); + memb_free(&bufmem, buf); + return NULL; + } + buframptr = buf->ram_ptr; +#endif + + buframptr->len = packetbuf_copyto(buframptr->data); + packetbuf_attr_copyto(buframptr->attrs, buframptr->addrs); + +#if WITH_SWAP + if(buf->location == IN_CFS) { + if(queuebuf_flush_tmpdata() == -1) { + /* We were unable to write the data in the swap */ memb_free(&bufmem, buf); return NULL; } - buframptr = buf->ram_ptr; -#endif - - buframptr->len = packetbuf_copyto(buframptr->data); - packetbuf_attr_copyto(buframptr->attrs, buframptr->addrs); - -#if WITH_SWAP - if(buf->location == IN_CFS) { - if(queuebuf_flush_tmpdata() == -1) { - /* We were unable to write the data in the swap */ - memb_free(&bufmem, buf); - return NULL; - } - } + } #endif #if QUEUEBUF_STATS - ++queuebuf_len; - PRINTF("queuebuf len %d\n", queuebuf_len); - printf("#A q=%d\n", queuebuf_len); - if(queuebuf_len == queuebuf_max_len + 1) { - queuebuf_free(buf); - queuebuf_len--; - return NULL; - } + ++queuebuf_len; + PRINTF("#A q=%d\n", queuebuf_len); + if(queuebuf_len > queuebuf_max_len) { + queuebuf_max_len = queuebuf_len; + } #endif /* QUEUEBUF_STATS */ - } else { - PRINTF("queuebuf_new_from_packetbuf: could not allocate a queuebuf\n"); - } - return buf; + } else { + PRINTF("queuebuf_new_from_packetbuf: could not allocate a queuebuf\n"); } + return buf; } /*---------------------------------------------------------------------------*/ void @@ -444,47 +407,30 @@ queuebuf_free(struct queuebuf *buf) memb_free(&bufmem, buf); #if QUEUEBUF_STATS --queuebuf_len; - printf("#A q=%d\n", queuebuf_len); + PRINTF("#A q=%d\n", queuebuf_len); #endif /* QUEUEBUF_STATS */ #if QUEUEBUF_DEBUG list_remove(queuebuf_list, buf); #endif /* QUEUEBUF_DEBUG */ - } else if(memb_inmemb(&refbufmem, buf)) { - memb_free(&refbufmem, buf); -#if QUEUEBUF_STATS - --queuebuf_ref_len; -#endif /* QUEUEBUF_STATS */ } } /*---------------------------------------------------------------------------*/ void queuebuf_to_packetbuf(struct queuebuf *b) { - struct queuebuf_ref *r; if(memb_inmemb(&bufmem, b)) { struct queuebuf_data *buframptr = queuebuf_load_to_ram(b); packetbuf_copyfrom(buframptr->data, buframptr->len); packetbuf_attr_copyfrom(buframptr->attrs, buframptr->addrs); - } else if(memb_inmemb(&refbufmem, b)) { - r = (struct queuebuf_ref *)b; - packetbuf_clear(); - packetbuf_copyfrom(r->ref, r->len); - packetbuf_hdralloc(r->hdrlen); - memcpy(packetbuf_hdrptr(), r->hdr, r->hdrlen); } } /*---------------------------------------------------------------------------*/ void * queuebuf_dataptr(struct queuebuf *b) { - struct queuebuf_ref *r; - if(memb_inmemb(&bufmem, b)) { struct queuebuf_data *buframptr = queuebuf_load_to_ram(b); return buframptr->data; - } else if(memb_inmemb(&refbufmem, b)) { - r = (struct queuebuf_ref *)b; - return r->ref; } return NULL; } diff --git a/core/net/rime/broadcast-announcement.c b/core/net/rime/broadcast-announcement.c index b865c507b..945d0a78d 100644 --- a/core/net/rime/broadcast-announcement.c +++ b/core/net/rime/broadcast-announcement.c @@ -92,8 +92,6 @@ static struct broadcast_announcement_state { #define PRINTF(...) #endif -#define MIN(a, b) ((a)<(b)?(a):(b)) - /*---------------------------------------------------------------------------*/ static void send_adv(void *ptr) diff --git a/core/net/rime/ipolite.c b/core/net/rime/ipolite.c index d667a0714..11fbd6b17 100644 --- a/core/net/rime/ipolite.c +++ b/core/net/rime/ipolite.c @@ -42,20 +42,13 @@ * @{ */ +#include "sys/cc.h" #include "net/rime/rime.h" #include "net/rime/ipolite.h" #include "lib/random.h" #include -#ifndef MAX -#define MAX(a, b) ((a) > (b)? (a) : (b)) -#endif /* MAX */ - -#ifndef MIN -#define MIN(a, b) ((a) < (b)? (a) : (b)) -#endif /* MIN */ - #define DEBUG 0 #if DEBUG #include diff --git a/core/net/rime/polite-announcement.c b/core/net/rime/polite-announcement.c index 1383eaf43..d678931d8 100644 --- a/core/net/rime/polite-announcement.c +++ b/core/net/rime/polite-announcement.c @@ -43,7 +43,7 @@ */ #include "contiki.h" - +#include "sys/cc.h" #include "lib/list.h" #include "net/rime/rime.h" #include "net/rime/announcement.h" @@ -90,8 +90,6 @@ static struct polite_announcement_state { #define PRINTF(...) #endif -#define MIN(a, b) ((a)<(b)?(a):(b)) - /*---------------------------------------------------------------------------*/ static void send_adv(clock_time_t interval) diff --git a/core/net/rime/polite.c b/core/net/rime/polite.c index 531ae6228..6d0afed9b 100644 --- a/core/net/rime/polite.c +++ b/core/net/rime/polite.c @@ -42,21 +42,13 @@ * @{ */ +#include "sys/cc.h" #include "net/rime/rime.h" #include "net/rime/polite.h" #include "lib/random.h" #include -#ifndef MAX -#define MAX(a,b) ((a) > (b)? (a) : (b)) -#endif /* MAX */ - -#ifndef MIN -#define MIN(a, b) ((a) < (b)? (a) : (b)) -#endif /* MIN */ - - /*---------------------------------------------------------------------------*/ static void recv(struct abc_conn *abc) diff --git a/core/net/rime/rudolph0.c b/core/net/rime/rudolph0.c deleted file mode 100644 index 9582430b4..000000000 --- a/core/net/rime/rudolph0.c +++ /dev/null @@ -1,242 +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 - * Rudolph0: a simple block data flooding protocol - * \author - * Adam Dunkels - */ - -/** - * \addtogroup rudolph0 - * @{ - */ - -#include /* for offsetof */ - -#include "net/rime/rime.h" -#include "net/rime/rudolph0.h" - -#define STEADY_TIME CLOCK_SECOND * 2 - -#define DEFAULT_SEND_INTERVAL CLOCK_SECOND / 2 -enum { - TYPE_DATA, - TYPE_NACK, -}; - -enum { - STATE_RECEIVER, - STATE_SENDER, -}; - -#define VERSION_LT(a, b) ((signed char)((a) - (b)) < 0) - -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif - -/*---------------------------------------------------------------------------*/ -static void -read_new_datapacket(struct rudolph0_conn *c) -{ - int len = 0; - - if(c->cb->read_chunk) { - len = c->cb->read_chunk(c, c->current.h.chunk * RUDOLPH0_DATASIZE, - c->current.data, RUDOLPH0_DATASIZE); - } - c->current.datalen = len; - - PRINTF("read_new_datapacket len %d\n", len); -} -/*---------------------------------------------------------------------------*/ -static void -send_nack(struct rudolph0_conn *c) -{ - struct rudolph0_hdr *hdr; - packetbuf_clear(); - packetbuf_hdralloc(sizeof(struct rudolph0_hdr)); - hdr = packetbuf_hdrptr(); - - hdr->type = TYPE_NACK; - hdr->version = c->current.h.version; - hdr->chunk = c->current.h.chunk; - - PRINTF("Sending nack for %d:%d\n", hdr->version, hdr->chunk); - polite_send(&c->nackc, c->send_interval / 2, sizeof(struct rudolph0_hdr)); -} -/*---------------------------------------------------------------------------*/ -static void -sent(struct stbroadcast_conn *stbroadcast) -{ - struct rudolph0_conn *c = (struct rudolph0_conn *)stbroadcast; - - if(c->current.datalen == RUDOLPH0_DATASIZE) { - c->current.h.chunk++; - PRINTF("Sending data chunk %d next time\n", c->current.h.chunk); - read_new_datapacket(c); - } else { - stbroadcast_set_timer(&c->c, STEADY_TIME); - PRINTF("Steady: Sending the same data chunk next time datalen %d, %d\n", - c->current.datalen, RUDOLPH0_DATASIZE); - } -} -/*---------------------------------------------------------------------------*/ -static void -recv(struct stbroadcast_conn *stbroadcast) -{ - struct rudolph0_conn *c = (struct rudolph0_conn *)stbroadcast; - struct rudolph0_datapacket *p = packetbuf_dataptr(); - - if(p->h.type == TYPE_DATA) { - if(c->current.h.version != p->h.version) { - PRINTF("rudolph0 new version %d\n", p->h.version); - c->current.h.version = p->h.version; - c->current.h.chunk = 0; - c->cb->write_chunk(c, 0, RUDOLPH0_FLAG_NEWFILE, p->data, 0); - if(p->h.chunk != 0) { - send_nack(c); - } else { - c->cb->write_chunk(c, 0, RUDOLPH0_FLAG_NONE, p->data, p->datalen); - c->current.h.chunk++; - } - } else if(p->h.version == c->current.h.version) { - if(p->h.chunk == c->current.h.chunk) { - PRINTF("received chunk %d\n", p->h.chunk); - if(p->datalen < RUDOLPH0_DATASIZE) { - c->cb->write_chunk(c, c->current.h.chunk * RUDOLPH0_DATASIZE, - RUDOLPH0_FLAG_LASTCHUNK, p->data, p->datalen); - } else { - c->cb->write_chunk(c, c->current.h.chunk * RUDOLPH0_DATASIZE, - RUDOLPH0_FLAG_NONE, p->data, p->datalen); - } - c->current.h.chunk++; - - } else if(p->h.chunk > c->current.h.chunk) { - PRINTF("received chunk %d > %d, sending NACK\n", p->h.chunk, c->current.h.chunk); - send_nack(c); - } - } else { /* p->h.version < c->current.h.version */ - /* Ignore packets with old version */ - } - } -} -/*---------------------------------------------------------------------------*/ -static void -recv_nack(struct polite_conn *polite) -{ - struct rudolph0_conn *c = (struct rudolph0_conn *) - ((char *)polite - offsetof(struct rudolph0_conn, - nackc)); - struct rudolph0_datapacket *p = packetbuf_dataptr(); - - if(p->h.type == TYPE_NACK && c->state == STATE_SENDER) { - if(p->h.version == c->current.h.version) { - PRINTF("Reseting chunk to %d\n", p->h.chunk); - c->current.h.chunk = p->h.chunk; - } else { - PRINTF("Wrong version, reseting chunk to 0\n"); - c->current.h.chunk = 0; - } - read_new_datapacket(c); - stbroadcast_set_timer(&c->c, c->send_interval); - } -} -/*---------------------------------------------------------------------------*/ -static const struct polite_callbacks polite = { recv_nack, 0, 0 }; -static const struct stbroadcast_callbacks stbroadcast = { recv, sent }; -/*---------------------------------------------------------------------------*/ -void -rudolph0_open(struct rudolph0_conn *c, uint16_t channel, - const struct rudolph0_callbacks *cb) -{ - stbroadcast_open(&c->c, channel, &stbroadcast); - polite_open(&c->nackc, channel + 1, &polite); - c->cb = cb; - c->current.h.version = 0; - c->state = STATE_RECEIVER; - c->send_interval = DEFAULT_SEND_INTERVAL; -} -/*---------------------------------------------------------------------------*/ -void -rudolph0_close(struct rudolph0_conn *c) -{ - stbroadcast_close(&c->c); - polite_close(&c->nackc); -} -/*---------------------------------------------------------------------------*/ -void -rudolph0_send(struct rudolph0_conn *c, clock_time_t send_interval) -{ - c->state = STATE_SENDER; - c->current.h.version++; - c->current.h.version++; - c->current.h.chunk = 0; - c->current.h.type = TYPE_DATA; - read_new_datapacket(c); - packetbuf_reference(&c->current, sizeof(struct rudolph0_datapacket)); - c->send_interval = send_interval; - stbroadcast_send_stubborn(&c->c, c->send_interval); -} -/*---------------------------------------------------------------------------*/ -void -rudolph0_force_restart(struct rudolph0_conn *c) -{ - c->current.h.chunk = 0; - send_nack(c); -} -/*---------------------------------------------------------------------------*/ -void -rudolph0_stop(struct rudolph0_conn *c) -{ - stbroadcast_cancel(&c->c); -} -/*---------------------------------------------------------------------------*/ -int -rudolph0_version(struct rudolph0_conn *c) -{ - return c->current.h.version; -} -/*---------------------------------------------------------------------------*/ -void -rudolph0_set_version(struct rudolph0_conn *c, int version) -{ - c->current.h.version = version; -} -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/core/net/rime/rudolph0.h b/core/net/rime/rudolph0.h deleted file mode 100644 index 695d97950..000000000 --- a/core/net/rime/rudolph0.h +++ /dev/null @@ -1,122 +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 file for the single-hop reliable bulk data transfer module - * \author - * Adam Dunkels - */ - -/** - * \addtogroup rime - * @{ - */ - -/** - * \defgroup rudolph0 Single-hop reliable bulk data transfer (rudolph0) - * @{ - * - * The rudolph0 module implements a single-hop reliable bulk data - * transfer mechanism. - * - * \section rudolph0-channels Channels - * - * The rudolph0 module uses 2 channels; one for data packets and one - * for NACK and repair packets. - * - */ - -#ifndef RUDOLPH0_H_ -#define RUDOLPH0_H_ - -#include "net/rime/stbroadcast.h" -#include "net/rime/polite.h" - -struct rudolph0_conn; - -enum { - RUDOLPH0_FLAG_NONE, - RUDOLPH0_FLAG_NEWFILE, - RUDOLPH0_FLAG_LASTCHUNK, -}; - -struct rudolph0_callbacks { - void (* write_chunk)(struct rudolph0_conn *c, int offset, int flag, - uint8_t *data, int len); - int (* read_chunk)(struct rudolph0_conn *c, int offset, uint8_t *to, - int maxsize); -}; - -#ifdef RUDOLPH0_CONF_DATASIZE -#define RUDOLPH0_DATASIZE RUDOLPH0_CONF_DATASIZE -#else -#define RUDOLPH0_DATASIZE 64 -#endif - -struct rudolph0_hdr { - uint8_t type; - uint8_t version; - uint16_t chunk; -}; - -struct rudolph0_datapacket { - struct rudolph0_hdr h; - uint8_t datalen; - uint8_t data[RUDOLPH0_DATASIZE]; -}; - -struct rudolph0_conn { - struct stbroadcast_conn c; - struct polite_conn nackc; - const struct rudolph0_callbacks *cb; - clock_time_t send_interval; - uint8_t state; - struct rudolph0_datapacket current; -}; - -void rudolph0_open(struct rudolph0_conn *c, uint16_t channel, - const struct rudolph0_callbacks *cb); -void rudolph0_close(struct rudolph0_conn *c); -void rudolph0_send(struct rudolph0_conn *c, clock_time_t interval); -void rudolph0_stop(struct rudolph0_conn *c); - -/* Force the sender to restart sending the file from the start. */ -void rudolph0_force_restart(struct rudolph0_conn *c); - -void rudolph0_set_version(struct rudolph0_conn *c, int version); -int rudolph0_version(struct rudolph0_conn *c); - -#endif /* RUDOLPH0_H_ */ -/** @} */ -/** @} */ - diff --git a/core/net/rpl/rpl-conf.h b/core/net/rpl/rpl-conf.h index 95a05a499..69199f9ac 100644 --- a/core/net/rpl/rpl-conf.h +++ b/core/net/rpl/rpl-conf.h @@ -105,6 +105,22 @@ #define RPL_MAX_DAG_PER_INSTANCE 2 #endif /* RPL_CONF_MAX_DAG_PER_INSTANCE */ +/* + * RPL Default route lifetime + * The RPL route lifetime is used for the downward routes and for the default + * route. In a high density network with DIO suppression activated it may happen + * that a node will never send a DIO once the DIO interval becomes high as it + * has heard DIO from many neighbors already. As the default route to the + * preferred parent has a lifetime reset by receiving DIO from the parent, it + * means that the default route can be destroyed after a while. Setting the + * default route with infinite lifetime secures the upstream route. + */ +#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 +#endif /* RPL_CONF_DEFAULT_ROUTE_INFINITE_LIFETIME */ + /* * */ @@ -207,4 +223,65 @@ #define RPL_INSERT_HBH_OPTION 1 #endif +/* + * RPL probing. When enabled, probes will be sent periodically to keep + * parent link estimates up to date. + * */ +#ifdef RPL_CONF_WITH_PROBING +#define RPL_WITH_PROBING RPL_CONF_WITH_PROBING +#else +#define RPL_WITH_PROBING 1 +#endif + +/* + * RPL probing interval. + * */ +#ifdef RPL_CONF_PROBING_INTERVAL +#define RPL_PROBING_INTERVAL RPL_CONF_PROBING_INTERVAL +#else +#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)) +#endif + +/* + * Function used to send RPL probes. + * To probe with DIO, use: + * #define RPL_CONF_PROBING_SEND_FUNC(instance, addr) dio_output((instance), (addr)) + * To probe with DIS, use: + * #define RPL_CONF_PROBING_SEND_FUNC(instance, addr) dis_output((addr)) + * Any other custom probing function is also acceptable. + * */ +#ifdef RPL_CONF_PROBING_SEND_FUNC +#define RPL_PROBING_SEND_FUNC RPL_CONF_PROBING_SEND_FUNC +#else +#define RPL_PROBING_SEND_FUNC(instance, addr) dio_output((instance), (addr)) +#endif + +/* + * Function used to calculate next RPL probing interval + * */ +#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)) +#endif + #endif /* RPL_CONF_H */ diff --git a/core/net/rpl/rpl-dag-root.c b/core/net/rpl/rpl-dag-root.c new file mode 100644 index 000000000..44519bcd4 --- /dev/null +++ b/core/net/rpl/rpl-dag-root.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2012-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. + * + */ + +#include "contiki.h" +#include "contiki-net.h" + +#include "net/rpl/rpl.h" +#include "net/rpl/rpl-private.h" +#include "net/rpl/rpl-dag-root.h" + +#include + +#define DEBUG DEBUG_NONE +#include "net/ip/uip-debug.h" + +#define RPL_DAG_GRACE_PERIOD (CLOCK_SECOND * 20 * 1) + +static struct uip_ds6_notification n; +static uint8_t to_become_root; +static struct ctimer c; +/*---------------------------------------------------------------------------*/ +static const uip_ipaddr_t * +dag_root(void) +{ + rpl_dag_t *dag; + + dag = rpl_get_any_dag(); + if(dag != NULL) { + return &dag->dag_id; + } + + return NULL; +} +/*---------------------------------------------------------------------------*/ +static const uip_ipaddr_t * +get_global_address(void) +{ + int i; + uint8_t state; + uip_ipaddr_t *ipaddr = NULL; + + 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_PREFERRED && + !uip_is_addr_link_local(&uip_ds6_if.addr_list[i].ipaddr)) { + ipaddr = &uip_ds6_if.addr_list[i].ipaddr; + } + } + return ipaddr; +} +/*---------------------------------------------------------------------------*/ +static void +create_dag_callback(void *ptr) +{ + const uip_ipaddr_t *root, *ipaddr; + + root = dag_root(); + ipaddr = get_global_address(); + + if(root == NULL || uip_ipaddr_cmp(root, ipaddr)) { + /* The RPL network we are joining is one that we created, so we + become root. */ + if(to_become_root) { + rpl_dag_root_init_dag_immediately(); + to_become_root = 0; + } + } else { + rpl_dag_t *dag; + + dag = rpl_get_any_dag(); +#if DEBUG + printf("Found a network we did not create\n"); + printf("version %d grounded %d preference %d used %d joined %d rank %d\n", + dag->version, dag->grounded, + dag->preference, dag->used, + dag->joined, dag->rank); +#endif /* DEBUG */ + + /* We found a RPL network that we did not create so we just join + it without becoming root. But if the network has an infinite + rank, we assume the network has broken, and we become the new + root of the network. */ + + if(dag->rank == INFINITE_RANK) { + if(to_become_root) { + rpl_dag_root_init_dag_immediately(); + to_become_root = 0; + } + } + + /* Try again after the grace period */ + ctimer_set(&c, RPL_DAG_GRACE_PERIOD, create_dag_callback, NULL); + } +} +/*---------------------------------------------------------------------------*/ +static void +route_callback(int event, uip_ipaddr_t *route, uip_ipaddr_t *ipaddr, + int numroutes) +{ + if(event == UIP_DS6_NOTIFICATION_DEFRT_ADD) { + if(route != NULL && ipaddr != NULL && + !uip_is_addr_unspecified(route) && + !uip_is_addr_unspecified(ipaddr)) { + if(to_become_root) { + ctimer_set(&c, 0, create_dag_callback, NULL); + } + } + } +} +/*---------------------------------------------------------------------------*/ +static uip_ipaddr_t * +set_global_address(void) +{ + static uip_ipaddr_t ipaddr; + int i; + uint8_t state; + + /* Assign a unique local address (RFC4193, + http://tools.ietf.org/html/rfc4193). */ + 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); + + 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; +} +/*---------------------------------------------------------------------------*/ +void +rpl_dag_root_init(void) +{ + static uint8_t initialized = 0; + + if(!initialized) { + to_become_root = 0; + set_global_address(); + uip_ds6_notification_add(&n, route_callback); + initialized = 1; + } +} +/*---------------------------------------------------------------------------*/ +int +rpl_dag_root_init_dag_immediately(void) +{ + struct uip_ds6_addr *root_if; + int i; + uint8_t state; + uip_ipaddr_t *ipaddr = NULL; + + rpl_dag_root_init(); + + 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_PREFERRED && + !uip_is_addr_link_local(&uip_ds6_if.addr_list[i].ipaddr)) { + ipaddr = &uip_ds6_if.addr_list[i].ipaddr; + } + } + + if(ipaddr != NULL) { + 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(); + + /* 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(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); + rpl_set_prefix(dag, &prefix, 64); + PRINTF("rpl_dag_root_init_dag: created a new RPL dag\n"); + return 0; + } else { + PRINTF("rpl_dag_root_init_dag: failed to create a new RPL DAG\n"); + return -1; + } + } else { + PRINTF("rpl_dag_root_init_dag: failed to create a new RPL DAG, no preferred IP address found\n"); + return -2; + } +} +/*---------------------------------------------------------------------------*/ +void +rpl_dag_root_init_dag(void) +{ + rpl_dag_root_init(); + + ctimer_set(&c, RPL_DAG_GRACE_PERIOD, create_dag_callback, NULL); + to_become_root = 1; + + /* Send a DIS packet to request RPL info from neighbors. */ + dis_output(NULL); +} +/*---------------------------------------------------------------------------*/ +int +rpl_dag_root_is_root(void) +{ + rpl_instance_t *instance; + + instance = rpl_get_default_instance(); + + if(instance == NULL) { + return 0; + } + + if(instance->current_dag && + instance->current_dag->rank == ROOT_RANK(instance)) { + return 1; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ diff --git a/core/net/rpl/rpl-dag-root.h b/core/net/rpl/rpl-dag-root.h new file mode 100644 index 000000000..b421841b7 --- /dev/null +++ b/core/net/rpl/rpl-dag-root.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012-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. + * + */ + +#ifndef RPL_DAG_ROOT_H_ +#define RPL_DAG_ROOT_H_ + +void rpl_dag_root_init(void); +void rpl_dag_root_init_dag(void); +int rpl_dag_root_init_dag_immediately(void); + +int rpl_dag_root_is_root(void); + +#endif /* RPL_DAG_ROOT_H_ */ diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index 7b1908cfe..767c58968 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -75,12 +75,37 @@ static rpl_of_t * const objective_functions[] = {&RPL_OF}; /*---------------------------------------------------------------------------*/ /* Per-parent RPL information */ -NBR_TABLE(rpl_parent_t, rpl_parents); +NBR_TABLE_GLOBAL(rpl_parent_t, rpl_parents); /*---------------------------------------------------------------------------*/ /* Allocate instance table. */ rpl_instance_t instance_table[RPL_MAX_INSTANCES]; rpl_instance_t *default_instance; +/*---------------------------------------------------------------------------*/ +void +rpl_print_neighbor_list() +{ + if(default_instance != NULL && default_instance->current_dag != NULL && + default_instance->of != NULL && default_instance->of->calculate_rank != 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(); + + printf("RPL: rank %u dioint %u, %u nbr(s)\n", 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 (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), + p == default_instance->current_dag->preferred_parent ? '*' : ' ', + (unsigned)((now - p->last_tx_time) / (60 * CLOCK_SECOND))); + p = nbr_table_next(rpl_parents, p); + } + printf("RPL: end of list\n"); + } +} /*---------------------------------------------------------------------------*/ uip_ds6_nbr_t * rpl_get_nbr(rpl_parent_t *parent) @@ -269,17 +294,27 @@ rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id) rpl_dag_t *dag; rpl_instance_t *instance; uint8_t version; + int i; version = RPL_LOLLIPOP_INIT; - dag = get_dag(instance_id, dag_id); - if(dag != NULL) { - version = dag->version; - RPL_LOLLIPOP_INCREMENT(version); - PRINTF("RPL: Dropping a joined DAG when setting this node as root"); - if(dag == dag->instance->current_dag) { - dag->instance->current_dag = NULL; + instance = rpl_get_instance(instance_id); + if(instance != NULL) { + for(i = 0; i < RPL_MAX_DAG_PER_INSTANCE; ++i) { + dag = &instance->dag_table[i]; + if(dag->used) { + if(uip_ipaddr_cmp(&dag->dag_id, dag_id)) { + version = dag->version; + RPL_LOLLIPOP_INCREMENT(version); + } + if(dag == dag->instance->current_dag) { + PRINTF("RPL: Dropping a joined DAG when setting this node as root"); + dag->instance->current_dag = NULL; + } else { + PRINTF("RPL: Dropping a DAG when setting this node as root"); + } + rpl_free_dag(dag); + } } - rpl_free_dag(dag); } dag = rpl_alloc_dag(instance_id, dag_id); @@ -446,8 +481,7 @@ rpl_set_default_route(rpl_instance_t *instance, uip_ipaddr_t *from) PRINT6ADDR(from); PRINTF("\n"); instance->def_route = uip_ds6_defrt_add(from, - RPL_LIFETIME(instance, - instance->default_lifetime)); + RPL_DEFAULT_ROUTE_INFINITE_LIFETIME ? 0 : RPL_LIFETIME(instance, instance->default_lifetime)); if(instance->def_route == NULL) { return 0; } @@ -474,6 +508,9 @@ rpl_alloc_instance(uint8_t instance_id) instance->instance_id = instance_id; instance->def_route = NULL; instance->used = 1; +#if RPL_WITH_PROBING + rpl_schedule_probing(instance); +#endif /* RPL_WITH_PROBING */ return instance; } } @@ -507,7 +544,6 @@ rpl_alloc_dag(uint8_t instance_id, uip_ipaddr_t *dag_id) } RPL_STAT(rpl_stats.mem_overflows++); - rpl_free_instance(instance); return NULL; } /*---------------------------------------------------------------------------*/ @@ -517,6 +553,12 @@ rpl_set_default_instance(rpl_instance_t *instance) default_instance = instance; } /*---------------------------------------------------------------------------*/ +rpl_instance_t * +rpl_get_default_instance(void) +{ + return default_instance; +} +/*---------------------------------------------------------------------------*/ void rpl_free_instance(rpl_instance_t *instance) { @@ -534,6 +576,9 @@ rpl_free_instance(rpl_instance_t *instance) rpl_set_default_route(instance, NULL); +#if RPL_WITH_PROBING + ctimer_stop(&instance->probing_timer); +#endif /* RPL_WITH_PROBING */ ctimer_stop(&instance->dio_timer); ctimer_stop(&instance->dao_timer); ctimer_stop(&instance->dao_lifetime_timer); @@ -729,6 +774,9 @@ rpl_select_dag(rpl_instance_t *instance, rpl_parent_t *p) rpl_schedule_dao(instance); } rpl_reset_dio_timer(instance); +#if DEBUG + rpl_print_neighbor_list(); +#endif } else if(best_dag->rank != old_rank) { PRINTF("RPL: Preferred parent update, rank changed from %u to %u\n", (unsigned)old_rank, best_dag->rank); @@ -765,6 +813,9 @@ rpl_select_parent(rpl_dag_t *dag) if(best != NULL) { rpl_set_preferred_parent(dag, best); + dag->rank = dag->instance->of->calculate_rank(dag->preferred_parent, 0); + } else { + dag->rank = INFINITE_RANK; } return best; @@ -1324,12 +1375,15 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) } } + /* Parent info has been updated, trigger rank recalculation */ + p->flags |= RPL_PARENT_FLAG_UPDATED; + PRINTF("RPL: preferred DAG "); 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*/, p->link_metric, instance->mc.obj.etx); + p->rank, -1/*p->mc.obj.etx*/, rpl_get_nbr(p)->link_metric, instance->mc.obj.etx); /* We have allocated a candidate parent; process the DIO further. */ @@ -1349,7 +1403,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) } /* We received a new DIO from our preferred parent. * Call uip_ds6_defrt_add to set a fresh value for the lifetime counter */ - uip_ds6_defrt_add(from, RPL_LIFETIME(instance, instance->default_lifetime)); + uip_ds6_defrt_add(from, RPL_DEFAULT_ROUTE_INFINITE_LIFETIME ? 0 : RPL_LIFETIME(instance, instance->default_lifetime)); } p->dtsn = dio->dtsn; } diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index c9890b706..66e311d51 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -466,8 +466,12 @@ dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr) buffer[pos++] = instance->dtsn_out; - /* always request new DAO to refresh route */ - RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); + if(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. */ + RPL_LOLLIPOP_INCREMENT(instance->dtsn_out); + } /* reserved 2 bytes */ buffer[pos++] = 0; /* flags */ diff --git a/core/net/rpl/rpl-private.h b/core/net/rpl/rpl-private.h index a9ca3f375..b49d71089 100644 --- a/core/net/rpl/rpl-private.h +++ b/core/net/rpl/rpl-private.h @@ -313,6 +313,7 @@ rpl_of_t *rpl_find_of(rpl_ocp_t); void rpl_schedule_dao(rpl_instance_t *); void rpl_schedule_dao_immediately(rpl_instance_t *); void rpl_cancel_dao(rpl_instance_t *instance); +void rpl_schedule_probing(rpl_instance_t *instance); void rpl_reset_dio_timer(rpl_instance_t *); void rpl_reset_periodic_timer(void); @@ -320,4 +321,7 @@ void rpl_reset_periodic_timer(void); /* Route poisoning. */ void rpl_poison_routes(rpl_dag_t *, rpl_parent_t *); + +rpl_instance_t *rpl_get_default_instance(void); + #endif /* RPL_PRIVATE_H */ diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index ea7bfe7f2..27fff0ddf 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -166,6 +166,10 @@ handle_dio_timer(void *ptr) } new_dio_interval(instance); } + +#if DEBUG + rpl_print_neighbor_list(); +#endif } /*---------------------------------------------------------------------------*/ void @@ -323,5 +327,97 @@ rpl_cancel_dao(rpl_instance_t *instance) ctimer_stop(&instance->dao_lifetime_timer); } /*---------------------------------------------------------------------------*/ +#if RPL_WITH_PROBING +static 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. + * Otherwise, it picks at random between: + * (1) selecting the best parent not updated for RPL_PROBING_EXPIRATION_TIME + * (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; + + if(dag == NULL || + dag->instance == NULL || + dag->preferred_parent == NULL) { + return NULL; + } + + /* Our preferred parent needs probing */ + if(dag->preferred_parent->last_tx_time < min_last_tx) { + probing_target = dag->preferred_parent; + } + + /* With 50% probability: probe best parent not updated for RPL_PROBING_EXPIRATION_TIME */ + if(probing_target == NULL && (random_rand() % 2) == 0) { + p = nbr_table_head(rpl_parents); + while(p != NULL) { + if(p->dag == dag && p->last_tx_time < min_last_tx) { + /* p is in our dag and needs probing */ + rpl_rank_t p_rank = dag->instance->of->calculate_rank(p, 0); + if(probing_target == NULL + || p_rank < probing_target_rank) { + probing_target = p; + probing_target_rank = p_rank; + } + } + p = nbr_table_next(rpl_parents, p); + } + } + + /* The default probing target is the least recently updated parent */ + if(probing_target == NULL) { + p = nbr_table_head(rpl_parents); + while(p != NULL) { + if(p->dag == dag) { + if(probing_target == NULL + || p->last_tx_time < probing_target->last_tx_time) { + probing_target = p; + } + } + p = nbr_table_next(rpl_parents, p); + } + } + + return probing_target; +} +/*---------------------------------------------------------------------------*/ +static void +handle_probing_timer(void *ptr) +{ + rpl_instance_t *instance = (rpl_instance_t *)ptr; + rpl_parent_t *probing_target = RPL_PROBING_SELECT_FUNC(instance->current_dag); + + /* Perform probing */ + if(probing_target != NULL && rpl_get_parent_ipaddr(probing_target) != NULL) { + PRINTF("RPL: probing %3u\n", + nbr_table_get_lladdr(rpl_parents, probing_target)->u8[7]); + /* Send probe, e.g. unicast DIO or DIS */ + RPL_PROBING_SEND_FUNC(instance, rpl_get_parent_ipaddr(probing_target)); + } + + /* Schedule next probing */ + rpl_schedule_probing(instance); + +#if DEBUG + rpl_print_neighbor_list(); +#endif +} +/*---------------------------------------------------------------------------*/ +void +rpl_schedule_probing(rpl_instance_t *instance) +{ + ctimer_set(&instance->probing_timer, RPL_PROBING_DELAY_FUNC(), + handle_probing_timer, instance); +} +#endif /* RPL_WITH_PROBING */ /** @}*/ diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index f92d5f5f8..db5230611 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -263,6 +263,7 @@ rpl_link_neighbor_callback(const linkaddr_t *addr, int status, int numtx) 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(); } } } diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index 512c1a8f0..e6e385375 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -114,6 +114,7 @@ struct rpl_parent { rpl_metric_container_t mc; #endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */ rpl_rank_t rank; + clock_time_t last_tx_time; uint8_t dtsn; uint8_t flags; }; @@ -224,6 +225,9 @@ struct rpl_instance { uint16_t dio_totrecv; #endif /* RPL_CONF_STATS */ clock_time_t dio_next_delay; /* delay for completion of dio interval */ +#if RPL_WITH_PROBING + struct ctimer probing_timer; +#endif /* RPL_WITH_PROBING */ struct ctimer dio_timer; struct ctimer dao_timer; struct ctimer dao_lifetime_timer; @@ -251,6 +255,10 @@ 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(); + +/* Per-parent RPL information */ +NBR_TABLE_DECLARE(rpl_parents); /** * RPL modes diff --git a/core/sys/cc.h b/core/sys/cc.h index 90ef3e710..06b8889ec 100644 --- a/core/sys/cc.h +++ b/core/sys/cc.h @@ -127,14 +127,33 @@ #define NULL 0 #endif /* NULL */ +#ifndef MAX +#define MAX(n, m) (((n) < (m)) ? (m) : (n)) +#endif + +#ifndef MIN +#define MIN(n, m) (((n) < (m)) ? (n) : (m)) +#endif + +#ifndef ABS +#define ABS(n) (((n) < 0) ? -(n) : (n)) +#endif + + #define CC_CONCAT2(s1, s2) s1##s2 /** - * A C preprocessing macro for concatenating to - * strings. + * A C preprocessing macro for concatenating two preprocessor tokens. * * We need use two macros (CC_CONCAT and CC_CONCAT2) in order to allow * concatenation of two \#defined macros. */ #define CC_CONCAT(s1, s2) CC_CONCAT2(s1, s2) +#define CC_CONCAT_EXT_2(s1, s2) CC_CONCAT2(s1, s2) + +/** + * A C preprocessing macro for concatenating three preprocessor tokens. + */ +#define CC_CONCAT3(s1, s2, s3) s1##s2##s3 +#define CC_CONCAT_EXT_3(s1, s2, s3) CC_CONCAT3(s1, s2, s3) #endif /* CC_H_ */ diff --git a/cpu/avr/dev/usb/compiler.h b/cpu/avr/dev/usb/compiler.h index aaa9f1ede..50a02a92d 100644 --- a/cpu/avr/dev/usb/compiler.h +++ b/cpu/avr/dev/usb/compiler.h @@ -280,9 +280,6 @@ typedef char r_uart_ptchar; #define OUT_X(addrx,value) (*addrx = value) #define IN_X(addrx) (*addrx) -# define Max(a, b) ( (a)>(b) ? (a) : (b) ) // Take the max between a and b -# define Min(a, b) ( (a)<(b) ? (a) : (b) ) // Take the min between a and b - // Align on the upper value on a boundary // i.e. Upper(0, 4)= 4 // Upper(1, 4)= 4 diff --git a/cpu/avr/radio/mac/sicslowmac.c b/cpu/avr/radio/mac/sicslowmac.c index 9a176277a..b836bcd3a 100644 --- a/cpu/avr/radio/mac/sicslowmac.c +++ b/cpu/avr/radio/mac/sicslowmac.c @@ -402,14 +402,18 @@ sicslowmac_dataRequest(void) frame_create_params_t params; frame_result_t result; +#if NETSTACK_CONF_WITH_RIME /* Save the msduHandle in a global variable. */ msduHandle = packetbuf_attr(PACKETBUF_ATTR_PACKET_ID); +#endif /* Build the FCF. */ params.fcf.frameType = DATAFRAME; params.fcf.securityEnabled = false; params.fcf.framePending = false; +#if NETSTACK_CONF_WITH_RIME params.fcf.ackRequired = packetbuf_attr(PACKETBUF_ATTR_RELIABLE); +#endif params.fcf.panIdCompression = false; /* Insert IEEE 802.15.4 (2003) version bit. */ diff --git a/cpu/avr/radio/rf230bb/rf230bb.c b/cpu/avr/radio/rf230bb/rf230bb.c index e4181868c..aee2f6d29 100644 --- a/cpu/avr/radio/rf230bb/rf230bb.c +++ b/cpu/avr/radio/rf230bb/rf230bb.c @@ -1073,8 +1073,10 @@ rf230_transmit(unsigned short payload_len) if (tx_result==RADIO_TX_OK) { RIMESTATS_ADD(lltx); +#if NETSTACK_CONF_WITH_RIME if(packetbuf_attr(PACKETBUF_ATTR_RELIABLE)) RIMESTATS_ADD(ackrx); //ack was requested and received +#endif #if RF230_INSERTACK /* Not PAN broadcast to FFFF, and ACK was requested and received */ if (!((buffer[5]==0xff) && (buffer[6]==0xff)) && (buffer[0]&(1<<6))) diff --git a/cpu/cc2538/Makefile.cc2538 b/cpu/cc2538/Makefile.cc2538 index 9fd8a08be..29795111c 100644 --- a/cpu/cc2538/Makefile.cc2538 +++ b/cpu/cc2538/Makefile.cc2538 @@ -49,16 +49,24 @@ 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 += nvic.c cpu.c sys-ctrl.c gpio.c ioc.c spi.c adc.c +CONTIKI_CPU_SOURCEFILES += crypto.c aes.c ccm.c sha256.c CONTIKI_CPU_SOURCEFILES += cc2538-rf.c udma.c lpm.c CONTIKI_CPU_SOURCEFILES += dbg.c ieee-addr.c CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c -CONTIKI_CPU_SOURCEFILES += i2c.c +CONTIKI_CPU_SOURCEFILES += i2c.c cc2538-temp-sensor.c vdd3-sensor.c DEBUG_IO_SOURCEFILES += dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c USB_CORE_SOURCEFILES += usb-core.c cdc-acm.c USB_ARCH_SOURCEFILES += usb-arch.c usb-serial.c cdc-acm-descriptors.c +ifneq ($(TARGET_START_SOURCEFILES),) + CPU_START_SOURCEFILES = TARGET_START_SOURCEFILES +else + CPU_START_SOURCEFILES = startup-gcc.c +endif +CPU_STARTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(CPU_START_SOURCEFILES)}} + CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) $(DEBUG_IO_SOURCEFILES) CONTIKI_SOURCEFILES += $(USB_CORE_SOURCEFILES) $(USB_ARCH_SOURCEFILES) @@ -75,7 +83,7 @@ $(OBJECTDIR)/ieee-addr.o: ieee-addr.c FORCE | $(OBJECTDIR) ### Compilation rules CUSTOM_RULE_LINK=1 -%.elf: $(TARGET_STARTFILES) %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(LDSCRIPT) +%.elf: $(CPU_STARTFILES) %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(LDSCRIPT) $(TRACE_LD) $(Q)$(LD) $(LDFLAGS) ${filter-out $(LDSCRIPT) %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -o $@ diff --git a/cpu/cc2538/cc2538.lds b/cpu/cc2538/cc2538.lds index 17b048778..cfd4cb48c 100644 --- a/cpu/cc2538/cc2538.lds +++ b/cpu/cc2538/cc2538.lds @@ -85,12 +85,13 @@ SECTIONS *(.udma_channel_control_table) } > SRAM - .data : + .data : ALIGN(4) { _data = .; *(.data*) _edata = .; } > SRAM AT > FLASH + _ldata = LOADADDR(.data); .ARM.exidx : { @@ -105,6 +106,11 @@ SECTIONS _ebss = .; } > SRAM + .stack (NOLOAD) : + { + *(.stack) + } > SRAM + #if (LPM_CONF_MAX_PM==2) && (LPM_CONF_ENABLE != 0) .nrdata (NOLOAD) : { diff --git a/cpu/cc2538/clock.c b/cpu/cc2538/clock.c index c0abed38b..953f06646 100644 --- a/cpu/cc2538/clock.c +++ b/cpu/cc2538/clock.c @@ -37,12 +37,12 @@ * Implementation of the clock module for the cc2538 * * To implement the clock functionality, we use the SysTick peripheral on the - * cortex-M3. We run the system clock at 16 MHz and we set the SysTick to give - * us 128 interrupts / sec. However, the Sleep Timer counter value is used for - * the number of elapsed ticks in order to avoid a significant time drift caused - * by PM1/2. Contrary to the Sleep Timer, the SysTick peripheral is indeed - * frozen during PM1/2, so adjusting upon wake-up a tick counter based on this - * peripheral would hardly be accurate. + * cortex-M3. We run the system clock at a configurable speed and set the + * SysTick to give us 128 interrupts / sec. However, the Sleep Timer counter + * value is used for the number of elapsed ticks in order to avoid a + * significant time drift caused by PM1/2. Contrary to the Sleep Timer, the + * SysTick peripheral is indeed frozen during PM1/2, so adjusting upon wake-up + * a tick counter based on this peripheral would hardly be accurate. * @{ * * \file @@ -62,7 +62,19 @@ #include /*---------------------------------------------------------------------------*/ #define RTIMER_CLOCK_TICK_RATIO (RTIMER_SECOND / CLOCK_SECOND) -#define RELOAD_VALUE (125000 - 1) /** Fire 128 times / sec */ + +/* Prescaler for GPT0:Timer A used for clock_delay_usec(). */ +#if SYS_CTRL_SYS_CLOCK < SYS_CTRL_1MHZ +#error System clock speeds below 1MHz are not supported +#endif +#define PRESCALER_VALUE (SYS_CTRL_SYS_CLOCK / SYS_CTRL_1MHZ - 1) + +/* Reload value for SysTick counter */ +#if SYS_CTRL_SYS_CLOCK % CLOCK_SECOND +/* Too low clock speeds will lead to reduced accurracy */ +#error System clock speed too slow for CLOCK_SECOND, accuracy reduced +#endif +#define RELOAD_VALUE (SYS_CTRL_SYS_CLOCK / CLOCK_SECOND - 1) static volatile uint64_t rt_ticks_startup = 0, rt_ticks_epoch = 0; /*---------------------------------------------------------------------------*/ @@ -74,8 +86,8 @@ static volatile uint64_t rt_ticks_startup = 0, rt_ticks_epoch = 0; * * We also initialise GPT0:Timer A, which is used by clock_delay_usec(). * We use 16-bit range (individual), count-down, one-shot, no interrupts. - * The system clock is at 16MHz giving us 62.5 nano sec ticks for Timer A. - * Prescaled by 16 gives us a very convenient 1 tick per usec + * The prescaler is computed according to the system clock in order to get 1 + * tick per usec. */ void clock_init(void) @@ -98,15 +110,14 @@ clock_init(void) /* Make sure GPT0 is off */ REG(GPT_0_BASE + GPTIMER_CTL) = 0; - /* 16-bit */ REG(GPT_0_BASE + GPTIMER_CFG) = 0x04; /* One-Shot, Count Down, No Interrupts */ REG(GPT_0_BASE + GPTIMER_TAMR) = GPTIMER_TAMR_TAMR_ONE_SHOT; - /* Prescale by 16 (thus, value 15 in TAPR) */ - REG(GPT_0_BASE + GPTIMER_TAPR) = 0x0F; + /* Prescale depending on system clock used */ + REG(GPT_0_BASE + GPTIMER_TAPR) = PRESCALER_VALUE; } /*---------------------------------------------------------------------------*/ CCIF clock_time_t diff --git a/cpu/cc2538/dev/aes.c b/cpu/cc2538/dev/aes.c new file mode 100644 index 000000000..1bd70690c --- /dev/null +++ b/cpu/cc2538/dev/aes.c @@ -0,0 +1,152 @@ +/* + * Original file: + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.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-aes + * @{ + * + * \file + * Implementation of the cc2538 AES driver + */ +#include "contiki.h" +#include "dev/rom-util.h" +#include "dev/aes.h" +#include "reg.h" + +#include +/*---------------------------------------------------------------------------*/ +uint8_t +aes_load_keys(const void *keys, uint8_t key_size, uint8_t count, + uint8_t start_area) +{ + uint32_t aes_key_store_size; + uint32_t areas; + uint64_t aligned_keys[16]; + int i; + + if(REG(AES_CTRL_ALG_SEL) != 0x00000000) { + return CRYPTO_RESOURCE_IN_USE; + } + + /* 192-bit keys must be padded to 256 bits */ + if(key_size == AES_KEY_STORE_SIZE_KEY_SIZE_192) { + for(i = 0; i < count; i++) { + rom_util_memcpy(&aligned_keys[i << 2], &((uint64_t *)keys)[i * 3], 24); + aligned_keys[(i << 2) + 3] = 0; + } + } + + /* Change count to the number of 128-bit key areas */ + if(key_size != AES_KEY_STORE_SIZE_KEY_SIZE_128) { + count <<= 1; + } + + /* The keys base address needs to be 4-byte aligned */ + if(key_size != AES_KEY_STORE_SIZE_KEY_SIZE_192) { + rom_util_memcpy(aligned_keys, keys, count << 4); + } + + /* Workaround for AES registers not retained after PM2 */ + REG(AES_CTRL_INT_CFG) = AES_CTRL_INT_CFG_LEVEL; + REG(AES_CTRL_INT_EN) = AES_CTRL_INT_EN_DMA_IN_DONE | + AES_CTRL_INT_EN_RESULT_AV; + + /* Configure master control module */ + REG(AES_CTRL_ALG_SEL) = AES_CTRL_ALG_SEL_KEYSTORE; + + /* Clear any outstanding events */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE | + AES_CTRL_INT_CLR_RESULT_AV; + + /* Configure key store module (areas, size) + * Note that writing AES_KEY_STORE_SIZE deletes all stored keys */ + aes_key_store_size = REG(AES_KEY_STORE_SIZE); + if((aes_key_store_size & AES_KEY_STORE_SIZE_KEY_SIZE_M) != key_size) { + REG(AES_KEY_STORE_SIZE) = (aes_key_store_size & + ~AES_KEY_STORE_SIZE_KEY_SIZE_M) | key_size; + } + + /* Free possibly already occupied key areas */ + areas = ((0x00000001 << count) - 1) << start_area; + REG(AES_KEY_STORE_WRITTEN_AREA) = areas; + + /* Enable key areas to write */ + REG(AES_KEY_STORE_WRITE_AREA) = areas; + + /* Configure DMAC + * Enable DMA channel 0 */ + REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN; + + /* Base address of the keys in ext. memory */ + REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)aligned_keys; + + /* Total keys length in bytes (e.g. 16 for 1 x 128-bit key) */ + REG(AES_DMAC_CH0_DMALENGTH) = (REG(AES_DMAC_CH0_DMALENGTH) & + ~AES_DMAC_CH_DMALENGTH_DMALEN_M) | + (count << (4 + AES_DMAC_CH_DMALENGTH_DMALEN_S)); + + /* Wait for operation to complete */ + while(!(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_RESULT_AV)); + + /* Check for absence of errors in DMA and key store */ + if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_DMA_BUS_ERR) { + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_BUS_ERR; + /* Disable master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + return CRYPTO_DMA_BUS_ERROR; + } + if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_KEY_ST_WR_ERR) { + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_KEY_ST_WR_ERR; + /* Disable master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + return AES_KEYSTORE_WRITE_ERROR; + } + + /* Acknowledge the interrupt */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE | + AES_CTRL_INT_CLR_RESULT_AV; + + /* Disable master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + + /* Check status, if error return error code */ + if((REG(AES_KEY_STORE_WRITTEN_AREA) & areas) != areas) { + return AES_KEYSTORE_WRITE_ERROR; + } + + return CRYPTO_SUCCESS; +} + +/** @} */ diff --git a/cpu/cc2538/dev/aes.h b/cpu/cc2538/dev/aes.h new file mode 100644 index 000000000..39c794b51 --- /dev/null +++ b/cpu/cc2538/dev/aes.h @@ -0,0 +1,495 @@ +/* + * Original file: + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.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-crypto + * @{ + * + * \defgroup cc2538-aes cc2538 AES + * + * Driver for the cc2538 AES modes of the security core + * @{ + * + * \file + * Header file for the cc2538 AES driver + */ +#ifndef AES_H_ +#define AES_H_ + +#include "contiki.h" +#include "dev/crypto.h" + +#include +/*---------------------------------------------------------------------------*/ +/** \name AES register offsets + * @{ + */ +#define AES_DMAC_CH0_CTRL 0x4008B000 /**< Channel 0 control */ +#define AES_DMAC_CH0_EXTADDR 0x4008B004 /**< Channel 0 external address */ +#define AES_DMAC_CH0_DMALENGTH 0x4008B00C /**< Channel 0 DMA length */ +#define AES_DMAC_STATUS 0x4008B018 /**< DMAC status */ +#define AES_DMAC_SWRES 0x4008B01C /**< DMAC software reset */ +#define AES_DMAC_CH1_CTRL 0x4008B020 /**< Channel 1 control */ +#define AES_DMAC_CH1_EXTADDR 0x4008B024 /**< Channel 1 external address */ +#define AES_DMAC_CH1_DMALENGTH 0x4008B02C /**< Channel 1 DMA length */ +#define AES_DMAC_MST_RUNPARAMS 0x4008B078 /**< DMAC master run-time parameters */ +#define AES_DMAC_PERSR 0x4008B07C /**< DMAC port error raw status */ +#define AES_DMAC_OPTIONS 0x4008B0F8 /**< DMAC options */ +#define AES_DMAC_VERSION 0x4008B0FC /**< DMAC version */ +#define AES_KEY_STORE_WRITE_AREA \ + 0x4008B400 /**< Key store write area */ +#define AES_KEY_STORE_WRITTEN_AREA \ + 0x4008B404 /**< Key store written area */ +#define AES_KEY_STORE_SIZE 0x4008B408 /**< Key store size */ +#define AES_KEY_STORE_READ_AREA 0x4008B40C /**< Key store read area */ +#define AES_AES_KEY2_0 0x4008B500 /**< AES_KEY2_0 / AES_GHASH_H_IN_0 */ +#define AES_AES_KEY2_1 0x4008B504 /**< AES_KEY2_1 / AES_GHASH_H_IN_1 */ +#define AES_AES_KEY2_2 0x4008B508 /**< AES_KEY2_2 / AES_GHASH_H_IN_2 */ +#define AES_AES_KEY2_3 0x4008B50C /**< AES_KEY2_3 / AES_GHASH_H_IN_3 */ +#define AES_AES_KEY3_0 0x4008B510 /**< AES_KEY3_0 / AES_KEY2_4 */ +#define AES_AES_KEY3_1 0x4008B514 /**< AES_KEY3_1 / AES_KEY2_5 */ +#define AES_AES_KEY3_2 0x4008B518 /**< AES_KEY3_2 / AES_KEY2_6 */ +#define AES_AES_KEY3_3 0x4008B51C /**< AES_KEY3_3 / AES_KEY2_7 */ +#define AES_AES_IV_0 0x4008B540 /**< AES initialization vector */ +#define AES_AES_IV_1 0x4008B544 /**< AES initialization vector */ +#define AES_AES_IV_2 0x4008B548 /**< AES initialization vector */ +#define AES_AES_IV_3 0x4008B54C /**< AES initialization vector */ +#define AES_AES_CTRL 0x4008B550 /**< AES input/output buffer control and mode */ +#define AES_AES_C_LENGTH_0 0x4008B554 /**< AES crypto length (LSW) */ +#define AES_AES_C_LENGTH_1 0x4008B558 /**< AES crypto length (MSW) */ +#define AES_AES_AUTH_LENGTH 0x4008B55C /**< Authentication length */ +#define AES_AES_DATA_IN_OUT_0 0x4008B560 /**< Data input/output */ +#define AES_AES_DATA_IN_OUT_1 0x4008B564 /**< Data Input/Output */ +#define AES_AES_DATA_IN_OUT_2 0x4008B568 /**< Data Input/Output */ +#define AES_AES_DATA_IN_OUT_3 0x4008B56C /**< Data Input/Output */ +#define AES_AES_TAG_OUT_0 0x4008B570 /**< TAG */ +#define AES_AES_TAG_OUT_1 0x4008B574 /**< TAG */ +#define AES_AES_TAG_OUT_2 0x4008B578 /**< TAG */ +#define AES_AES_TAG_OUT_3 0x4008B57C /**< TAG */ +#define AES_HASH_DATA_IN_0 0x4008B600 /**< HASH data input */ +#define AES_HASH_DATA_IN_1 0x4008B604 /**< HASH data input */ +#define AES_HASH_DATA_IN_2 0x4008B608 /**< HASH data input */ +#define AES_HASH_DATA_IN_3 0x4008B60C /**< HASH data input */ +#define AES_HASH_DATA_IN_4 0x4008B610 /**< HASH data input */ +#define AES_HASH_DATA_IN_5 0x4008B614 /**< HASH data input */ +#define AES_HASH_DATA_IN_6 0x4008B618 /**< HASH data input */ +#define AES_HASH_DATA_IN_7 0x4008B61C /**< HASH data input */ +#define AES_HASH_DATA_IN_8 0x4008B620 /**< HASH data input */ +#define AES_HASH_DATA_IN_9 0x4008B624 /**< HASH data input */ +#define AES_HASH_DATA_IN_10 0x4008B628 /**< HASH data input */ +#define AES_HASH_DATA_IN_11 0x4008B62C /**< HASH data input */ +#define AES_HASH_DATA_IN_12 0x4008B630 /**< HASH data input */ +#define AES_HASH_DATA_IN_13 0x4008B634 /**< HASH data input */ +#define AES_HASH_DATA_IN_14 0x4008B638 /**< HASH data input */ +#define AES_HASH_DATA_IN_15 0x4008B63C /**< HASH data input */ +#define AES_HASH_IO_BUF_CTRL 0x4008B640 /**< Input/output buffer control and status */ +#define AES_HASH_MODE_IN 0x4008B644 /**< Hash mode */ +#define AES_HASH_LENGTH_IN_L 0x4008B648 /**< Hash length */ +#define AES_HASH_LENGTH_IN_H 0x4008B64C /**< Hash length */ +#define AES_HASH_DIGEST_A 0x4008B650 /**< Hash digest */ +#define AES_HASH_DIGEST_B 0x4008B654 /**< Hash digest */ +#define AES_HASH_DIGEST_C 0x4008B658 /**< Hash digest */ +#define AES_HASH_DIGEST_D 0x4008B65C /**< Hash digest */ +#define AES_HASH_DIGEST_E 0x4008B660 /**< Hash digest */ +#define AES_HASH_DIGEST_F 0x4008B664 /**< Hash digest */ +#define AES_HASH_DIGEST_G 0x4008B668 /**< Hash digest */ +#define AES_HASH_DIGEST_H 0x4008B66C /**< Hash digest */ +#define AES_CTRL_ALG_SEL 0x4008B700 /**< Algorithm select */ +#define AES_CTRL_PROT_EN 0x4008B704 /**< Master PROT privileged access enable */ +#define AES_CTRL_SW_RESET 0x4008B740 /**< Software reset */ +#define AES_CTRL_INT_CFG 0x4008B780 /**< Interrupt configuration */ +#define AES_CTRL_INT_EN 0x4008B784 /**< Interrupt enable */ +#define AES_CTRL_INT_CLR 0x4008B788 /**< Interrupt clear */ +#define AES_CTRL_INT_SET 0x4008B78C /**< Interrupt set */ +#define AES_CTRL_INT_STAT 0x4008B790 /**< Interrupt status */ +#define AES_CTRL_OPTIONS 0x4008B7F8 /**< Options */ +#define AES_CTRL_VERSION 0x4008B7FC /**< Version */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_CHx_CTRL registers bit fields + * @{ + */ +#define AES_DMAC_CH_CTRL_PRIO 0x00000002 /**< Channel priority 0: Low 1: High */ +#define AES_DMAC_CH_CTRL_EN 0x00000001 /**< Channel enable */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_CHx_DMALENGTH registers bit fields + * @{ + */ +#define AES_DMAC_CH_DMALENGTH_DMALEN_M \ + 0x0000FFFF /**< Channel DMA length in bytes mask */ +#define AES_DMAC_CH_DMALENGTH_DMALEN_S 0 /**< Channel DMA length in bytes shift */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_STATUS register bit fields + * @{ + */ +#define AES_DMAC_STATUS_PORT_ERR \ + 0x00020000 /**< AHB port transfer errors */ +#define AES_DMAC_STATUS_CH1_ACT 0x00000002 /**< Channel 1 active (DMA transfer on-going) */ +#define AES_DMAC_STATUS_CH0_ACT 0x00000001 /**< Channel 0 active (DMA transfer on-going) */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_SWRES register bit fields + * @{ + */ +#define AES_DMAC_SWRES_SWRES 0x00000001 /**< Software reset enable */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_MST_RUNPARAMS register bit fields + * @{ + */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BURST_SIZE_4 \ + (2 << 12) /**< Maximum burst size: 4 bytes */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BURST_SIZE_8 \ + (3 << 12) /**< Maximum burst size: 8 bytes */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BURST_SIZE_16 \ + (4 << 12) /**< Maximum burst size: 16 bytes */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BURST_SIZE_32 \ + (5 << 12) /**< Maximum burst size: 32 bytes */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BURST_SIZE_64 \ + (6 << 12) /**< Maximum burst size: 64 bytes */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BURST_SIZE_M \ + 0x0000F000 /**< Maximum burst size mask */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BURST_SIZE_S \ + 12 /**< Maximum burst size shift */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_IDLE_EN \ + 0x00000800 /**< Idle insertion between bursts */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_INCR_EN \ + 0x00000400 /**< Fixed-length burst or single transfers */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_LOCK_EN \ + 0x00000200 /**< Locked transfers */ +#define AES_DMAC_MST_RUNPARAMS_AHB_MST1_BIGEND \ + 0x00000100 /**< Big endian AHB master */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_PERSR register bit fields + * @{ + */ +#define AES_DMAC_PERSR_PORT1_AHB_ERROR \ + 0x00001000 /**< AHB bus error */ +#define AES_DMAC_PERSR_PORT1_CHANNEL \ + 0x00000200 /**< Last serviced channel (0 or 1) */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_OPTIONS register bit fields + * @{ + */ +#define AES_DMAC_OPTIONS_NR_OF_CHANNELS_M \ + 0x00000F00 /**< Number of channels implemented mask */ +#define AES_DMAC_OPTIONS_NR_OF_CHANNELS_S \ + 8 /**< Number of channels implemented shift */ +#define AES_DMAC_OPTIONS_NR_OF_PORTS_M \ + 0x00000007 /**< Number of ports implemented mask */ +#define AES_DMAC_OPTIONS_NR_OF_PORTS_S 0 /**< Number of ports implemented shift */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_DMAC_VERSION register bit fields + * @{ + */ +#define AES_DMAC_VERSION_HW_MAJOR_VERSION_M \ + 0x0F000000 /**< Major version number mask */ +#define AES_DMAC_VERSION_HW_MAJOR_VERSION_S \ + 24 /**< Major version number shift */ +#define AES_DMAC_VERSION_HW_MINOR_VERSION_M \ + 0x00F00000 /**< Minor version number mask */ +#define AES_DMAC_VERSION_HW_MINOR_VERSION_S \ + 20 /**< Minor version number shift */ +#define AES_DMAC_VERSION_HW_PATCH_LEVEL_M \ + 0x000F0000 /**< Patch level mask */ +#define AES_DMAC_VERSION_HW_PATCH_LEVEL_S \ + 16 /**< Patch level shift */ +#define AES_DMAC_VERSION_EIP_NUMBER_COMPL_M \ + 0x0000FF00 /**< EIP_NUMBER 1's complement mask */ +#define AES_DMAC_VERSION_EIP_NUMBER_COMPL_S \ + 8 /**< EIP_NUMBER 1's complement shift */ +#define AES_DMAC_VERSION_EIP_NUMBER_M \ + 0x000000FF /**< DMAC EIP-number mask */ +#define AES_DMAC_VERSION_EIP_NUMBER_S 0 /**< DMAC EIP-number shift */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_KEY_STORE_SIZE register bit fields + * @{ + */ +#define AES_KEY_STORE_SIZE_KEY_SIZE_128 1 /**< Key size: 128 bits */ +#define AES_KEY_STORE_SIZE_KEY_SIZE_192 2 /**< Key size: 192 bits */ +#define AES_KEY_STORE_SIZE_KEY_SIZE_256 3 /**< Key size: 256 bits */ +#define AES_KEY_STORE_SIZE_KEY_SIZE_M \ + 0x00000003 /**< Key size mask */ +#define AES_KEY_STORE_SIZE_KEY_SIZE_S 0 /**< Key size shift */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_KEY_STORE_READ_AREA register bit fields + * @{ + */ +#define AES_KEY_STORE_READ_AREA_BUSY \ + 0x80000000 /**< Key store operation busy */ +#define AES_KEY_STORE_READ_AREA_RAM_AREA_M \ + 0x0000000F /**< Key store RAM area select mask */ +#define AES_KEY_STORE_READ_AREA_RAM_AREA_S \ + 0 /**< Key store RAM area select shift */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_AES_CTRL register bit fields + * @{ + */ +#define AES_AES_CTRL_CONTEXT_READY \ + 0x80000000 /**< Context data registers can be overwritten */ +#define AES_AES_CTRL_SAVED_CONTEXT_READY \ + 0x40000000 /**< AES auth. TAG and/or IV block(s) available */ +#define AES_AES_CTRL_SAVE_CONTEXT \ + 0x20000000 /**< Auth. TAG or result IV needs to be stored */ +#define AES_AES_CTRL_CCM_M_M 0x01C00000 /**< CCM auth. field length mask */ +#define AES_AES_CTRL_CCM_M_S 22 /**< CCM auth. field length shift */ +#define AES_AES_CTRL_CCM_L_M 0x00380000 /**< CCM length field width mask */ +#define AES_AES_CTRL_CCM_L_S 19 /**< CCM length field width shift */ +#define AES_AES_CTRL_CCM 0x00040000 /**< AES-CCM mode */ +#define AES_AES_CTRL_GCM 0x00030000 /**< AES-GCM mode */ +#define AES_AES_CTRL_CBC_MAC 0x00008000 /**< AES-CBC MAC mode */ +#define AES_AES_CTRL_CTR_WIDTH_32 (0 << 7) /**< CTR counter width: 32 bits */ +#define AES_AES_CTRL_CTR_WIDTH_64 (1 << 7) /**< CTR counter width: 64 bits */ +#define AES_AES_CTRL_CTR_WIDTH_96 (2 << 7) /**< CTR counter width: 96 bits */ +#define AES_AES_CTRL_CTR_WIDTH_128 \ + (3 << 7) /**< CTR counter width: 128 bits */ +#define AES_AES_CTRL_CTR_WIDTH_M \ + 0x00000180 /**< CTR counter width mask */ +#define AES_AES_CTRL_CTR_WIDTH_S 7 /**< CTR counter width shift */ +#define AES_AES_CTRL_CTR 0x00000040 /**< AES-CTR mode */ +#define AES_AES_CTRL_CBC 0x00000020 /**< AES-CBC mode */ +#define AES_AES_CTRL_KEY_SIZE_128 (1 << 3) /**< Key size: 128 bits */ +#define AES_AES_CTRL_KEY_SIZE_192 (2 << 3) /**< Key size: 192 bits */ +#define AES_AES_CTRL_KEY_SIZE_256 (3 << 3) /**< Key size: 256 bits */ +#define AES_AES_CTRL_KEY_SIZE_M 0x00000018 /**< Key size mask */ +#define AES_AES_CTRL_KEY_SIZE_S 3 /**< Key size shift */ +#define AES_AES_CTRL_DIRECTION_ENCRYPT \ + 0x00000004 /**< Encrypt */ +#define AES_AES_CTRL_INPUT_READY \ + 0x00000002 /**< AES input buffer empty */ +#define AES_AES_CTRL_OUTPUT_READY \ + 0x00000001 /**< AES output block available */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_AES_C_LENGTH_1 register bit fields + * @{ + */ +#define AES_AES_C_LENGTH_1_C_LENGTH_M \ + 0x1FFFFFFF /**< Crypto length bits [60:32] mask */ +#define AES_AES_C_LENGTH_1_C_LENGTH_S 0 /**< Crypto length bits [60:32] shift */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_HASH_IO_BUF_CTRL register bit fields + * @{ + */ +#define AES_HASH_IO_BUF_CTRL_PAD_DMA_MESSAGE \ + 0x00000080 /**< Hash engine message padding required */ +#define AES_HASH_IO_BUF_CTRL_GET_DIGEST \ + 0x00000040 /**< Hash engine digest requested */ +#define AES_HASH_IO_BUF_CTRL_PAD_MESSAGE \ + 0x00000020 /**< Last message data in HASH_DATA_IN, apply hash padding */ +#define AES_HASH_IO_BUF_CTRL_RFD_IN \ + 0x00000004 /**< Hash engine input buffer can accept new data */ +#define AES_HASH_IO_BUF_CTRL_DATA_IN_AV \ + 0x00000002 /**< Start processing HASH_DATA_IN data */ +#define AES_HASH_IO_BUF_CTRL_OUTPUT_FULL \ + 0x00000001 /**< Output buffer registers available */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_HASH_MODE_IN register bit fields + * @{ + */ +#define AES_HASH_MODE_IN_SHA256_MODE \ + 0x00000008 /**< Hash mode */ +#define AES_HASH_MODE_IN_NEW_HASH \ + 0x00000001 /**< New hash session */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_ALG_SEL register bit fields + * @{ + */ +#define AES_CTRL_ALG_SEL_TAG 0x80000000 /**< DMA operation includes TAG */ +#define AES_CTRL_ALG_SEL_HASH 0x00000004 /**< Select hash engine as DMA destination */ +#define AES_CTRL_ALG_SEL_AES 0x00000002 /**< Select AES engine as DMA source/destination */ +#define AES_CTRL_ALG_SEL_KEYSTORE \ + 0x00000001 /**< Select Key Store as DMA destination */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_PROT_EN register bit fields + * @{ + */ +#define AES_CTRL_PROT_EN_PROT_EN \ + 0x00000001 /**< m_h_prot[1] asserted for DMA reads towards key store */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_SW_RESET register bit fields + * @{ + */ +#define AES_CTRL_SW_RESET_SW_RESET \ + 0x00000001 /**< Reset master control and key store */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_INT_CFG register bit fields + * @{ + */ +#define AES_CTRL_INT_CFG_LEVEL 0x00000001 /**< Level interrupt type */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_INT_EN register bit fields + * @{ + */ +#define AES_CTRL_INT_EN_DMA_IN_DONE \ + 0x00000002 /**< DMA input done interrupt enabled */ +#define AES_CTRL_INT_EN_RESULT_AV \ + 0x00000001 /**< Result available interrupt enabled */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_INT_CLR register bit fields + * @{ + */ +#define AES_CTRL_INT_CLR_DMA_BUS_ERR \ + 0x80000000 /**< Clear DMA bus error status */ +#define AES_CTRL_INT_CLR_KEY_ST_WR_ERR \ + 0x40000000 /**< Clear key store write error status */ +#define AES_CTRL_INT_CLR_KEY_ST_RD_ERR \ + 0x20000000 /**< Clear key store read error status */ +#define AES_CTRL_INT_CLR_DMA_IN_DONE \ + 0x00000002 /**< Clear DMA in done interrupt */ +#define AES_CTRL_INT_CLR_RESULT_AV \ + 0x00000001 /**< Clear result available interrupt */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_INT_SET register bit fields + * @{ + */ +#define AES_CTRL_INT_SET_DMA_IN_DONE \ + 0x00000002 /**< Set DMA data in done interrupt */ +#define AES_CTRL_INT_SET_RESULT_AV \ + 0x00000001 /**< Set result available interrupt */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_INT_STAT register bit fields + * @{ + */ +#define AES_CTRL_INT_STAT_DMA_BUS_ERR \ + 0x80000000 /**< DMA bus error detected */ +#define AES_CTRL_INT_STAT_KEY_ST_WR_ERR \ + 0x40000000 /**< Write error detected */ +#define AES_CTRL_INT_STAT_KEY_ST_RD_ERR \ + 0x20000000 /**< Read error detected */ +#define AES_CTRL_INT_STAT_DMA_IN_DONE \ + 0x00000002 /**< DMA data in done interrupt status */ +#define AES_CTRL_INT_STAT_RESULT_AV \ + 0x00000001 /**< Result available interrupt status */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_OPTIONS register bit fields + * @{ + */ +#define AES_CTRL_OPTIONS_TYPE_M 0xFF000000 /**< Device type mask */ +#define AES_CTRL_OPTIONS_TYPE_S 24 /**< Device type shift */ +#define AES_CTRL_OPTIONS_AHBINTERFACE \ + 0x00010000 /**< AHB interface available */ +#define AES_CTRL_OPTIONS_SHA_256 \ + 0x00000100 /**< The HASH core supports SHA-256 */ +#define AES_CTRL_OPTIONS_AES_CCM \ + 0x00000080 /**< AES-CCM available as single operation */ +#define AES_CTRL_OPTIONS_AES_GCM \ + 0x00000040 /**< AES-GCM available as single operation */ +#define AES_CTRL_OPTIONS_AES_256 \ + 0x00000020 /**< AES core supports 256-bit keys */ +#define AES_CTRL_OPTIONS_AES_128 \ + 0x00000010 /**< AES core supports 128-bit keys */ +#define AES_CTRL_OPTIONS_HASH 0x00000004 /**< HASH Core available */ +#define AES_CTRL_OPTIONS_AES 0x00000002 /**< AES core available */ +#define AES_CTRL_OPTIONS_KEYSTORE \ + 0x00000001 /**< KEY STORE available */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES_CTRL_VERSION register bit fields + * @{ + */ +#define AES_CTRL_VERSION_MAJOR_VERSION_M \ + 0x0F000000 /**< Major version number mask */ +#define AES_CTRL_VERSION_MAJOR_VERSION_S \ + 24 /**< Major version number shift */ +#define AES_CTRL_VERSION_MINOR_VERSION_M \ + 0x00F00000 /**< Minor version number mask */ +#define AES_CTRL_VERSION_MINOR_VERSION_S \ + 20 /**< Minor version number shift */ +#define AES_CTRL_VERSION_PATCH_LEVEL_M \ + 0x000F0000 /**< Patch level mask */ +#define AES_CTRL_VERSION_PATCH_LEVEL_S 16 /**< Patch level shift */ +#define AES_CTRL_VERSION_EIP_NUMBER_COMPL_M \ + 0x0000FF00 /**< EIP_NUMBER 1's complement mask */ +#define AES_CTRL_VERSION_EIP_NUMBER_COMPL_S \ + 8 /**< EIP_NUMBER 1's complement shift */ +#define AES_CTRL_VERSION_EIP_NUMBER_M \ + 0x000000FF /**< EIP-120t EIP-number mask */ +#define AES_CTRL_VERSION_EIP_NUMBER_S 0 /**< EIP-120t EIP-number shift */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES drivers return codes + * @{ + */ +#define AES_KEYSTORE_READ_ERROR 5 +#define AES_KEYSTORE_WRITE_ERROR 6 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES functions + * @{ + */ + +/** \brief Writes keys into the Key RAM + * \param keys Pointer to AES Keys + * \param key_size Key size: \c AES_KEY_STORE_SIZE_KEY_SIZE_x + * \param count Number of keys (1 to 8 - \p start_area for 128-bit keys, 1 to + * (8 - \p start_area) / 2 for 192- and 256-bit keys) + * \param start_area Start area in Key RAM where to store the key (0 to 7, must + * be even for 192- and 256-bit keys) + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/AES error code + * \note Calling this function with a value of \p key_size different from the + * one passed for the previous calls causes the deletion of all previously + * stored keys. + */ +uint8_t aes_load_keys(const void *keys, uint8_t key_size, uint8_t count, + uint8_t start_area); + +/** @} */ + +#endif /* AES_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index e8ec81309..58b464fc5 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -80,7 +80,6 @@ /* Local RF Flags */ #define RX_ACTIVE 0x80 #define RF_MUST_RESET 0x40 -#define WAS_OFF 0x10 #define RF_ON 0x01 /* Bit Masks for the last byte in the RX FIFO */ @@ -180,6 +179,8 @@ get_channel() static int8_t set_channel(uint8_t channel) { + uint8_t was_on = 0; + PRINTF("RF: Set Channel\n"); if((channel < CC2538_RF_CHANNEL_MIN) || (channel > CC2538_RF_CHANNEL_MAX)) { @@ -189,16 +190,14 @@ set_channel(uint8_t channel) /* Changes to FREQCTRL take effect after the next recalibration */ /* If we are off, save state, otherwise switch off and save state */ - if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) == 0) { - rf_flags |= WAS_OFF; - } else { - rf_flags &= ~WAS_OFF; + if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) != 0) { + was_on = 1; off(); } REG(RFCORE_XREG_FREQCTRL) = (CC2538_RF_CHANNEL_MIN + (channel - CC2538_RF_CHANNEL_MIN) * CC2538_RF_CHANNEL_SPACING); /* switch radio back on only if radio was on before - otherwise will turn on radio foor sleepy nodes */ - if((rf_flags & WAS_OFF) != WAS_OFF) { + if(was_on) { on(); } @@ -244,10 +243,11 @@ static radio_value_t get_rssi(void) { int8_t rssi; + uint8_t was_off = 0; /* If we are off, turn on first */ if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) == 0) { - rf_flags |= WAS_OFF; + was_off = 1; on(); } @@ -257,8 +257,7 @@ get_rssi(void) rssi = (int8_t)(REG(RFCORE_XREG_RSSI) & RFCORE_XREG_RSSI_RSSI_VAL) - RSSI_OFFSET; /* If we were off, turn back off */ - if((rf_flags & WAS_OFF) == WAS_OFF) { - rf_flags &= ~WAS_OFF; + if(was_off) { off(); } @@ -345,12 +344,13 @@ static int channel_clear(void) { int cca; + uint8_t was_off = 0; PRINTF("RF: CCA\n"); /* If we are off, turn on first */ if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) == 0) { - rf_flags |= WAS_OFF; + was_off = 1; on(); } @@ -364,8 +364,7 @@ channel_clear(void) } /* If we were off, turn back off */ - if((rf_flags & WAS_OFF) == WAS_OFF) { - rf_flags &= ~WAS_OFF; + if(was_off) { off(); } @@ -561,13 +560,14 @@ transmit(unsigned short transmit_len) uint8_t counter; int ret = RADIO_TX_ERR; rtimer_clock_t t0; + uint8_t was_off = 0; PRINTF("RF: Transmit\n"); if(!(rf_flags & RX_ACTIVE)) { t0 = RTIMER_NOW(); on(); - rf_flags |= WAS_OFF; + was_off = 1; while(RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ONOFF_TIME)); } @@ -609,8 +609,7 @@ transmit(unsigned short transmit_len) ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); ENERGEST_ON(ENERGEST_TYPE_LISTEN); - if(rf_flags & WAS_OFF) { - rf_flags &= ~WAS_OFF; + if(was_off) { off(); } diff --git a/cpu/cc2538/dev/cc2538-sensors.h b/cpu/cc2538/dev/cc2538-sensors.h new file mode 100644 index 000000000..b4d3ada91 --- /dev/null +++ b/cpu/cc2538/dev/cc2538-sensors.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, 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 cc2538 + * @{ + * + * \defgroup cc2538-sensors CC2538 Built-In Sensors + * + * Module controlling sensors on the CC2538 SoC (Tmp and VDD3) + * @{ + * + * \file + * Generic header usable by all CC2538 sensor drivers + */ +/*---------------------------------------------------------------------------*/ +#ifndef CC2538_SENSORS_H_ +#define CC2538_SENSORS_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +#include "dev/cc2538-temp-sensor.h" +#include "dev/vdd3-sensor.h" +/*---------------------------------------------------------------------------*/ +/** + * \name CC2538 sensor constants + * + * These constants are used by various sensors on the CC2538. They can be used + * to differentiate between raw and converted readings, to configure ADC + * decimation rate (where applicable). + * @{ + */ +#define CC2538_SENSORS_VALUE_TYPE_RAW 0 /**< Request the raw reading */ +#define CC2538_SENSORS_VALUE_TYPE_CONVERTED 1 /**< Request the converted reading */ + +#define CC2538_SENSORS_ERROR 0x80000000 /**< Generic Error */ +/** @} */ +/*---------------------------------------------------------------------------*/ +#endif /* CC2538_SENSORS_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/cc2538-temp-sensor.c b/cpu/cc2538/dev/cc2538-temp-sensor.c new file mode 100644 index 000000000..dd5dcba6c --- /dev/null +++ b/cpu/cc2538/dev/cc2538-temp-sensor.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, 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 cc2538-temp-sensor + * @{ + * + * \file + * Driver for the CC2538 On-Chip temperature sensor + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/sensors.h" +#include "dev/adc.h" +#include "dev/cc2538-sensors.h" + +#include +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + int raw = adc_get(SOC_ADC_ADCCON_CH_TEMP, SOC_ADC_ADCCON_REF_INT, + SOC_ADC_ADCCON_DIV_512); + + if(type == CC2538_SENSORS_VALUE_TYPE_RAW) { + return raw; + } else if(type == CC2538_SENSORS_VALUE_TYPE_CONVERTED) { + return 25000 + ((raw >> 4) - 1422) * 10000 / 42; + } + + return CC2538_SENSORS_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(cc2538_temp_sensor, TEMP_SENSOR, value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc2538/dev/cc2538-temp-sensor.h b/cpu/cc2538/dev/cc2538-temp-sensor.h new file mode 100644 index 000000000..b515c5042 --- /dev/null +++ b/cpu/cc2538/dev/cc2538-temp-sensor.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, 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 cc2538-sensors + * @{ + * + * \defgroup cc2538-temp-sensor CC2538 on-chip temperature Sensor + * + * Driver for the CC2538 on-chip temperature sensor + * + * This driver can return the raw as well as the converted value of the sensor + * reading. This is controlled by the type argument of the sensor driver's + * value() function. The choices for the type argument are: + * - CC2538_SENSORS_VALUE_TYPE_RAW (value() returns the raw reading) + * - CC2538_SENSORS_VALUE_TYPE_CONVERTED (value() returns degrees mC) + * @{ + * + * \file + * Header file for the CC2538 on-chip temperature Sensor Driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef CC2538_TEMP_SENSOR_H_ +#define CC2538_TEMP_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +/** + * \name temperature sensor + * @{ + */ +#define TEMP_SENSOR "On-Chip Temperature" +/** @} */ +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor cc2538_temp_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* CC2538_TEMP_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/ccm.c b/cpu/cc2538/dev/ccm.c new file mode 100644 index 000000000..b25ef29b3 --- /dev/null +++ b/cpu/cc2538/dev/ccm.c @@ -0,0 +1,413 @@ +/* + * Original file: + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.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-ccm + * @{ + * + * \file + * Implementation of the cc2538 AES-CCM driver + */ +#include "contiki.h" +#include "sys/cc.h" +#include "dev/rom-util.h" +#include "dev/nvic.h" +#include "dev/ccm.h" +#include "reg.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +uint8_t +ccm_auth_encrypt_start(uint8_t len_len, uint8_t key_area, const void *nonce, + const void *adata, uint16_t adata_len, void *pdata, + uint16_t pdata_len, uint8_t mic_len, + struct process *process) +{ + uint32_t iv[4]; + + if(REG(AES_CTRL_ALG_SEL) != 0x00000000) { + return CRYPTO_RESOURCE_IN_USE; + } + + /* Workaround for AES registers not retained after PM2 */ + REG(AES_CTRL_INT_CFG) = AES_CTRL_INT_CFG_LEVEL; + REG(AES_CTRL_INT_EN) = AES_CTRL_INT_EN_DMA_IN_DONE | + AES_CTRL_INT_EN_RESULT_AV; + + REG(AES_CTRL_ALG_SEL) = AES_CTRL_ALG_SEL_AES; + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE | + AES_CTRL_INT_CLR_RESULT_AV; + + REG(AES_KEY_STORE_READ_AREA) = key_area; + + /* Wait until key is loaded to the AES module */ + while(REG(AES_KEY_STORE_READ_AREA) & AES_KEY_STORE_READ_AREA_BUSY); + + /* Check for Key Store read error */ + if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_KEY_ST_RD_ERR) { + /* Clear the Keystore Read error bit */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_KEY_ST_RD_ERR; + /* Disable the master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + return AES_KEYSTORE_READ_ERROR; + } + + /* Prepare the encryption initialization vector + * Flags: L' = L - 1 */ + ((uint8_t *)iv)[0] = len_len - 1; + /* Nonce */ + rom_util_memcpy(&((uint8_t *)iv)[1], nonce, 15 - len_len); + /* Initialize counter to 0 */ + rom_util_memset(&((uint8_t *)iv)[16 - len_len], 0, len_len); + + /* Write initialization vector */ + REG(AES_AES_IV_0) = iv[0]; + REG(AES_AES_IV_1) = iv[1]; + REG(AES_AES_IV_2) = iv[2]; + REG(AES_AES_IV_3) = iv[3]; + + /* Program AES-CCM encryption */ + REG(AES_AES_CTRL) = AES_AES_CTRL_SAVE_CONTEXT | /* Save context */ + (((MAX(mic_len, 2) - 2) >> 1) << AES_AES_CTRL_CCM_M_S) | /* M */ + ((len_len - 1) << AES_AES_CTRL_CCM_L_S) | /* L */ + AES_AES_CTRL_CCM | /* CCM */ + AES_AES_CTRL_CTR_WIDTH_128 | /* CTR width 128 */ + AES_AES_CTRL_CTR | /* CTR */ + AES_AES_CTRL_DIRECTION_ENCRYPT; /* Encryption */ + + /* Write the length of the crypto block (lo) */ + REG(AES_AES_C_LENGTH_0) = pdata_len; + /* Write the length of the crypto block (hi) */ + REG(AES_AES_C_LENGTH_1) = 0; + + /* Write the length of the AAD data block (may be non-block size-aligned) */ + REG(AES_AES_AUTH_LENGTH) = adata_len; + + if(adata_len != 0) { + /* Configure DMAC to fetch the AAD data + * Enable DMA channel 0 */ + REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN; + /* Base address of the AAD input data in ext. memory */ + REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)adata; + /* AAD data length in bytes */ + REG(AES_DMAC_CH0_DMALENGTH) = adata_len; + + /* Wait for completion of the AAD data transfer, DMA_IN_DONE */ + while(!(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_DMA_IN_DONE)); + + /* Check for the absence of error */ + if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_DMA_BUS_ERR) { + /* Clear the DMA error */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_BUS_ERR; + /* Disable the master control / DMA clock */ + 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 | + AES_CTRL_INT_CLR_RESULT_AV; + + if(process != NULL) { + crypto_register_process_notification(process); + nvic_interrupt_unpend(NVIC_INT_AES); + 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(pdata_len != 0) { + /* Configure DMAC + * Enable DMA channel 0 */ + REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN; + /* Base address of the payload data in ext. memory */ + REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)pdata; + /* Payload data length in bytes */ + REG(AES_DMAC_CH0_DMALENGTH) = pdata_len; + + /* Enable DMA channel 1 */ + REG(AES_DMAC_CH1_CTRL) = AES_DMAC_CH_CTRL_EN; + /* Base address of the output data buffer */ + REG(AES_DMAC_CH1_EXTADDR) = (uint32_t)pdata; + /* Output data length in bytes */ + REG(AES_DMAC_CH1_DMALENGTH) = pdata_len; + } + + return CRYPTO_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +uint8_t +ccm_auth_encrypt_check_status(void) +{ + return !!(REG(AES_CTRL_INT_STAT) & + (AES_CTRL_INT_STAT_DMA_BUS_ERR | AES_CTRL_INT_STAT_KEY_ST_WR_ERR | + AES_CTRL_INT_STAT_KEY_ST_RD_ERR | AES_CTRL_INT_STAT_RESULT_AV)); +} +/*---------------------------------------------------------------------------*/ +uint8_t +ccm_auth_encrypt_get_result(void *mic, uint8_t mic_len) +{ + uint32_t aes_ctrl_int_stat; + uint32_t tag[4]; + + aes_ctrl_int_stat = REG(AES_CTRL_INT_STAT); + /* Clear the error bits */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_BUS_ERR | + AES_CTRL_INT_CLR_KEY_ST_WR_ERR | + AES_CTRL_INT_CLR_KEY_ST_RD_ERR; + + nvic_interrupt_disable(NVIC_INT_AES); + crypto_register_process_notification(NULL); + + /* Disable the master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + + if(aes_ctrl_int_stat & AES_CTRL_INT_STAT_DMA_BUS_ERR) { + return CRYPTO_DMA_BUS_ERROR; + } + if(aes_ctrl_int_stat & AES_CTRL_INT_STAT_KEY_ST_WR_ERR) { + return AES_KEYSTORE_WRITE_ERROR; + } + if(aes_ctrl_int_stat & AES_CTRL_INT_STAT_KEY_ST_RD_ERR) { + return AES_KEYSTORE_READ_ERROR; + } + + /* Read tag + * Wait for the context ready bit */ + while(!(REG(AES_AES_CTRL) & AES_AES_CTRL_SAVED_CONTEXT_READY)); + + /* Read the tag registers */ + tag[0] = REG(AES_AES_TAG_OUT_0); + tag[1] = REG(AES_AES_TAG_OUT_1); + tag[2] = REG(AES_AES_TAG_OUT_2); + tag[3] = REG(AES_AES_TAG_OUT_3); + + /* Clear the interrupt status */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE | + AES_CTRL_INT_CLR_RESULT_AV; + + /* Copy tag to MIC */ + rom_util_memcpy(mic, tag, mic_len); + + return CRYPTO_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +uint8_t +ccm_auth_decrypt_start(uint8_t len_len, uint8_t key_area, const void *nonce, + const void *adata, uint16_t adata_len, void *cdata, + uint16_t cdata_len, uint8_t mic_len, + struct process *process) +{ + uint16_t pdata_len = cdata_len - mic_len; + uint32_t iv[4]; + + if(REG(AES_CTRL_ALG_SEL) != 0x00000000) { + return CRYPTO_RESOURCE_IN_USE; + } + + /* Workaround for AES registers not retained after PM2 */ + REG(AES_CTRL_INT_CFG) = AES_CTRL_INT_CFG_LEVEL; + REG(AES_CTRL_INT_EN) = AES_CTRL_INT_EN_DMA_IN_DONE | + AES_CTRL_INT_EN_RESULT_AV; + + REG(AES_CTRL_ALG_SEL) = AES_CTRL_ALG_SEL_AES; + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE | + AES_CTRL_INT_CLR_RESULT_AV; + + REG(AES_KEY_STORE_READ_AREA) = key_area; + + /* Wait until key is loaded to the AES module */ + while(REG(AES_KEY_STORE_READ_AREA) & AES_KEY_STORE_READ_AREA_BUSY); + + /* Check for Key Store read error */ + if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_KEY_ST_RD_ERR) { + /* Clear the Keystore Read error bit */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_KEY_ST_RD_ERR; + /* Disable the master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + return AES_KEYSTORE_READ_ERROR; + } + + /* Prepare the decryption initialization vector + * Flags: L' = L - 1 */ + ((uint8_t *)iv)[0] = len_len - 1; + /* Nonce */ + rom_util_memcpy(&((uint8_t *)iv)[1], nonce, 15 - len_len); + /* Initialize counter to 0 */ + rom_util_memset(&((uint8_t *)iv)[16 - len_len], 0, len_len); + + /* Write initialization vector */ + REG(AES_AES_IV_0) = iv[0]; + REG(AES_AES_IV_1) = iv[1]; + REG(AES_AES_IV_2) = iv[2]; + REG(AES_AES_IV_3) = iv[3]; + + /* Program AES-CCM decryption */ + REG(AES_AES_CTRL) = AES_AES_CTRL_SAVE_CONTEXT | /* Save context */ + (((MAX(mic_len, 2) - 2) >> 1) << AES_AES_CTRL_CCM_M_S) | /* M */ + ((len_len - 1) << AES_AES_CTRL_CCM_L_S) | /* L */ + AES_AES_CTRL_CCM | /* CCM */ + AES_AES_CTRL_CTR_WIDTH_128 | /* CTR width 128 */ + AES_AES_CTRL_CTR; /* CTR */ + + /* Write the length of the crypto block (lo) */ + REG(AES_AES_C_LENGTH_0) = pdata_len; + /* Write the length of the crypto block (hi) */ + REG(AES_AES_C_LENGTH_1) = 0; + + /* Write the length of the AAD data block (may be non-block size-aligned) */ + REG(AES_AES_AUTH_LENGTH) = adata_len; + + if(adata_len != 0) { + /* Configure DMAC to fetch the AAD data + * Enable DMA channel 0 */ + REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN; + /* Base address of the AAD input data in ext. memory */ + REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)adata; + /* AAD data length in bytes */ + REG(AES_DMAC_CH0_DMALENGTH) = adata_len; + + /* Wait for completion of the AAD data transfer, DMA_IN_DONE */ + while(!(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_DMA_IN_DONE)); + + /* Check for the absence of error */ + if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_DMA_BUS_ERR) { + /* Clear the DMA error */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_BUS_ERR; + /* Disable the master control / DMA clock */ + 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 | + AES_CTRL_INT_CLR_RESULT_AV; + + if(process != NULL) { + crypto_register_process_notification(process); + nvic_interrupt_unpend(NVIC_INT_AES); + 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(pdata_len != 0) { + /* Configure DMAC + * Enable DMA channel 0 */ + REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN; + /* Base address of the payload data in ext. memory */ + REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)cdata; + /* Payload data length in bytes */ + REG(AES_DMAC_CH0_DMALENGTH) = pdata_len; + + /* Enable DMA channel 1 */ + REG(AES_DMAC_CH1_CTRL) = AES_DMAC_CH_CTRL_EN; + /* Base address of the output data buffer */ + REG(AES_DMAC_CH1_EXTADDR) = (uint32_t)cdata; + /* Output data length in bytes */ + REG(AES_DMAC_CH1_DMALENGTH) = pdata_len; + } + + return CRYPTO_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +uint8_t +ccm_auth_decrypt_check_status(void) +{ + /* Check if result is available or some error has occured */ + return ccm_auth_encrypt_check_status(); +} +/*---------------------------------------------------------------------------*/ +uint8_t +ccm_auth_decrypt_get_result(const void *cdata, uint16_t cdata_len, + void *mic, uint8_t mic_len) +{ + uint32_t aes_ctrl_int_stat; + uint16_t pdata_len = cdata_len - mic_len; + uint32_t tag[4]; + + aes_ctrl_int_stat = REG(AES_CTRL_INT_STAT); + /* Clear the error bits */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_BUS_ERR | + AES_CTRL_INT_CLR_KEY_ST_WR_ERR | + AES_CTRL_INT_CLR_KEY_ST_RD_ERR; + + nvic_interrupt_disable(NVIC_INT_AES); + crypto_register_process_notification(NULL); + + /* Disable the master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + + if(aes_ctrl_int_stat & AES_CTRL_INT_STAT_DMA_BUS_ERR) { + return CRYPTO_DMA_BUS_ERROR; + } + if(aes_ctrl_int_stat & AES_CTRL_INT_STAT_KEY_ST_WR_ERR) { + return AES_KEYSTORE_WRITE_ERROR; + } + if(aes_ctrl_int_stat & AES_CTRL_INT_STAT_KEY_ST_RD_ERR) { + return AES_KEYSTORE_READ_ERROR; + } + + /* Read tag + * Wait for the context ready bit */ + while(!(REG(AES_AES_CTRL) & AES_AES_CTRL_SAVED_CONTEXT_READY)); + + /* Read the tag registers */ + tag[0] = REG(AES_AES_TAG_OUT_0); + tag[1] = REG(AES_AES_TAG_OUT_1); + tag[2] = REG(AES_AES_TAG_OUT_2); + tag[3] = REG(AES_AES_TAG_OUT_3); + + /* Clear the interrupt status */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE | + AES_CTRL_INT_CLR_RESULT_AV; + + /* Check MIC */ + if(rom_util_memcmp(tag, &((const uint8_t *)cdata)[pdata_len], mic_len)) { + return CCM_AUTHENTICATION_FAILED; + } + + /* Copy tag to MIC */ + rom_util_memcpy(mic, tag, mic_len); + + return CRYPTO_SUCCESS; +} + +/** @} */ diff --git a/cpu/cc2538/dev/ccm.h b/cpu/cc2538/dev/ccm.h new file mode 100644 index 000000000..1cab578af --- /dev/null +++ b/cpu/cc2538/dev/ccm.h @@ -0,0 +1,141 @@ +/* + * Original file: + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.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-aes + * @{ + * + * \defgroup cc2538-ccm cc2538 AES-CCM + * + * Driver for the cc2538 AES-CCM mode of the security core + * @{ + * + * \file + * Header file for the cc2538 AES-CCM driver + */ +#ifndef CCM_H_ +#define CCM_H_ + +#include "contiki.h" +#include "dev/aes.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +/** \name AES-CCM driver return codes + * @{ + */ +#define CCM_AUTHENTICATION_FAILED 7 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name AES-CCM functions + * @{ + */ + +/** \brief Starts the CCM authentication and encryption operation + * \param len_len Number of octets in length field (2, 4 or 8) + * \param key_area Area in Key RAM where the key is stored (0 to 7) + * \param nonce Pointer to nonce (15 - \p len_len octets) + * \param adata Pointer to additional authenticated data, or \c NULL + * \param adata_len Length of additional authenticated data in octets, or \c 0 + * \param pdata Pointer to message to authenticate and encrypt, or \c NULL + * \param pdata_len Length of message to authenticate and encrypt in octets, or \c 0 + * \param mic_len Number of octets in authentication field (even value between 0 and 16) + * \param process Process to be polled upon completion of the operation, or \c NULL + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/AES/CCM error code + */ +uint8_t ccm_auth_encrypt_start(uint8_t len_len, uint8_t key_area, + const void *nonce, const void *adata, + uint16_t adata_len, void *pdata, + uint16_t pdata_len, uint8_t mic_len, + struct process *process); + +/** \brief Checks the status of the CCM authentication and encryption operation + * \retval false Result not yet available, and no error occurred + * \retval true Result available, or error occurred + */ +uint8_t ccm_auth_encrypt_check_status(void); + +/** \brief Gets the result of the CCM authentication and encryption operation + * \param mic Pointer to authentication field, or \c NULL + * \param mic_len Number of octets in authentication field (even value between 0 and 16) + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/AES/CCM error code + * \note This function must be called only after \c ccm_auth_encrypt_start(). + */ +uint8_t ccm_auth_encrypt_get_result(void *mic, uint8_t mic_len); + +/** \brief Starts the CCM authentication checking and decryption operation + * \param len_len Number of octets in length field (2, 4 or 8) + * \param key_area Area in Key RAM where the key is stored (0 to 7) + * \param nonce Pointer to nonce (15 - \p len_len octets) + * \param adata Pointer to additional authenticated data, or \c NULL + * \param adata_len Length of additional authenticated data in octets, or \c 0 + * \param cdata Pointer to encrypted and authenticated message + * \param cdata_len Length of encrypted and authenticated message in octets + * \param mic_len Number of octets in authentication field (even value between 0 and 16) + * \param process Process to be polled upon completion of the operation, or \c NULL + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/AES/CCM error code + */ +uint8_t ccm_auth_decrypt_start(uint8_t len_len, uint8_t key_area, + const void *nonce, const void *adata, + uint16_t adata_len, void *cdata, + uint16_t cdata_len, uint8_t mic_len, + struct process *process); + +/** \brief Checks the status of the CCM authentication checking and decryption operation + * \retval false Result not yet available, and no error occurred + * \retval true Result available, or error occurred + */ +uint8_t ccm_auth_decrypt_check_status(void); + +/** \brief Gets the result of the CCM authentication checking and decryption operation + * \param cdata Pointer to encrypted and authenticated message + * \param cdata_len Length of encrypted and authenticated message in octets + * \param mic Pointer to authentication field, or \c NULL + * \param mic_len Number of octets in authentication field (even value between 0 and 16) + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/AES/CCM error code + * \note This function must be called only after \c ccm_auth_decrypt_start(). + */ +uint8_t ccm_auth_decrypt_get_result(const void *cdata, uint16_t cdata_len, + void *mic, uint8_t mic_len); + +/** @} */ + +#endif /* CCM_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/crypto.c b/cpu/cc2538/dev/crypto.c new file mode 100644 index 000000000..7dc5d3342 --- /dev/null +++ b/cpu/cc2538/dev/crypto.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2013, ADVANSEE - http://www.advansee.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-crypto + * @{ + * + * \file + * Implementation of the cc2538 AES/SHA cryptoprocessor driver + */ +#include "contiki.h" +#include "sys/energest.h" +#include "dev/sys-ctrl.h" +#include "dev/nvic.h" +#include "dev/crypto.h" +#include "dev/aes.h" +#include "reg.h" +#include "lpm.h" + +#include +/*---------------------------------------------------------------------------*/ +static volatile struct process *notification_process = NULL; +/*---------------------------------------------------------------------------*/ +/** \brief The AES/SHA cryptoprocessor ISR + * + * This is the interrupt service routine for the AES/SHA + * cryptoprocessor. + * + * This ISR is called at worst from PM0, so lpm_exit() does not need + * to be called. + */ +void +crypto_isr(void) +{ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + nvic_interrupt_unpend(NVIC_INT_AES); + nvic_interrupt_disable(NVIC_INT_AES); + + if(notification_process != NULL) { + process_poll((struct process *)notification_process); + notification_process = NULL; + } + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +/*---------------------------------------------------------------------------*/ +static bool +permit_pm1(void) +{ + return REG(AES_CTRL_ALG_SEL) == 0; +} +/*---------------------------------------------------------------------------*/ +void +crypto_init(void) +{ + volatile int i; + + lpm_register_peripheral(permit_pm1); + + crypto_enable(); + + /* Reset the AES/SHA cryptoprocessor */ + REG(SYS_CTRL_SRSEC) |= SYS_CTRL_SRSEC_AES; + for(i = 0; i < 16; i++); + REG(SYS_CTRL_SRSEC) &= ~SYS_CTRL_SRSEC_AES; +} +/*---------------------------------------------------------------------------*/ +void +crypto_enable(void) +{ + /* Enable the clock for the AES/SHA cryptoprocessor */ + REG(SYS_CTRL_RCGCSEC) |= SYS_CTRL_RCGCSEC_AES; + REG(SYS_CTRL_SCGCSEC) |= SYS_CTRL_SCGCSEC_AES; + REG(SYS_CTRL_DCGCSEC) |= SYS_CTRL_DCGCSEC_AES; +} +/*---------------------------------------------------------------------------*/ +void +crypto_disable(void) +{ + /* Gate the clock for the AES/SHA cryptoprocessor */ + REG(SYS_CTRL_RCGCSEC) &= ~SYS_CTRL_RCGCSEC_AES; + REG(SYS_CTRL_SCGCSEC) &= ~SYS_CTRL_SCGCSEC_AES; + REG(SYS_CTRL_DCGCSEC) &= ~SYS_CTRL_DCGCSEC_AES; +} +/*---------------------------------------------------------------------------*/ +void +crypto_register_process_notification(struct process *p) +{ + notification_process = p; +} + +/** @} */ diff --git a/cpu/cc2538/dev/crypto.h b/cpu/cc2538/dev/crypto.h new file mode 100644 index 000000000..ad06ef343 --- /dev/null +++ b/cpu/cc2538/dev/crypto.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013, ADVANSEE - http://www.advansee.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 + * @{ + * + * \defgroup cc2538-crypto cc2538 AES/SHA cryptoprocessor + * + * Driver for the cc2538 AES/SHA cryptoprocessor + * @{ + * + * \file + * Header file for the cc2538 AES/SHA cryptoprocessor driver + */ +#ifndef CRYPTO_H_ +#define CRYPTO_H_ + +#include "contiki.h" +/*---------------------------------------------------------------------------*/ +/** \name Crypto drivers return codes + * @{ + */ +#define CRYPTO_SUCCESS 0 +#define CRYPTO_INVALID_PARAM 1 +#define CRYPTO_NULL_ERROR 2 +#define CRYPTO_RESOURCE_IN_USE 3 +#define CRYPTO_DMA_BUS_ERROR 4 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name Crypto functions + * @{ + */ + +/** \brief Enables and resets the AES/SHA cryptoprocessor + */ +void crypto_init(void); + +/** \brief Enables the AES/SHA cryptoprocessor + */ +void crypto_enable(void); + +/** \brief Disables the AES/SHA cryptoprocessor + * \note Call this function to save power when the cryptoprocessor is unused. + */ +void crypto_disable(void); + +/** \brief Registers a process to be notified of the completion of a crypto + * operation + * \param p Process to be polled upon IRQ + * \note This function is only supposed to be called by the crypto drivers. + */ +void crypto_register_process_notification(struct process *p); + +/** @} */ + +#endif /* CRYPTO_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/gpio.c b/cpu/cc2538/dev/gpio.c index 581e52839..eb561c757 100644 --- a/cpu/cc2538/dev/gpio.c +++ b/cpu/cc2538/dev/gpio.c @@ -79,69 +79,41 @@ notify(uint8_t mask, uint8_t port) } } /*---------------------------------------------------------------------------*/ -/** \brief Interrupt service routine for Port A */ -void -gpio_port_a_isr() +/** \brief Interrupt service routine for Port \a port + * \param port Number between 0 and 3. Port A: 0, Port B: 1, etc. + */ +static void +gpio_port_isr(uint8_t port) { + uint32_t base; + uint8_t int_status, power_up_int_status; + lpm_exit(); ENERGEST_ON(ENERGEST_TYPE_IRQ); - notify(REG(GPIO_A_BASE + GPIO_MIS), GPIO_A_NUM); + base = GPIO_PORT_TO_BASE(port); + int_status = GPIO_GET_MASKED_INT_STATUS(base); + power_up_int_status = GPIO_GET_POWER_UP_INT_STATUS(port); - GPIO_CLEAR_INTERRUPT(GPIO_A_BASE, 0xFF); - GPIO_CLEAR_POWER_UP_INTERRUPT(GPIO_A_NUM, 0xFF); + notify(int_status | power_up_int_status, port); + + GPIO_CLEAR_INTERRUPT(base, int_status); + GPIO_CLEAR_POWER_UP_INTERRUPT(port, power_up_int_status); ENERGEST_OFF(ENERGEST_TYPE_IRQ); } /*---------------------------------------------------------------------------*/ -/** \brief Interrupt service routine for Port B */ -void -gpio_port_b_isr() -{ - lpm_exit(); - - ENERGEST_ON(ENERGEST_TYPE_IRQ); - - notify(REG(GPIO_B_BASE + GPIO_MIS), GPIO_B_NUM); - - GPIO_CLEAR_INTERRUPT(GPIO_B_BASE, 0xFF); - GPIO_CLEAR_POWER_UP_INTERRUPT(GPIO_B_NUM, 0xFF); - - ENERGEST_OFF(ENERGEST_TYPE_IRQ); -} -/*---------------------------------------------------------------------------*/ -/** \brief Interrupt service routine for Port C */ -void -gpio_port_c_isr() -{ - lpm_exit(); - - ENERGEST_ON(ENERGEST_TYPE_IRQ); - - notify(REG(GPIO_C_BASE + GPIO_MIS), GPIO_C_NUM); - - GPIO_CLEAR_INTERRUPT(GPIO_C_BASE, 0xFF); - GPIO_CLEAR_POWER_UP_INTERRUPT(GPIO_C_NUM, 0xFF); - - ENERGEST_OFF(ENERGEST_TYPE_IRQ); -} -/*---------------------------------------------------------------------------*/ -/** \brief Interrupt service routine for Port D */ -void -gpio_port_d_isr() -{ - lpm_exit(); - - ENERGEST_ON(ENERGEST_TYPE_IRQ); - - notify(REG(GPIO_D_BASE + GPIO_MIS), GPIO_D_NUM); - - GPIO_CLEAR_INTERRUPT(GPIO_D_BASE, 0xFF); - GPIO_CLEAR_POWER_UP_INTERRUPT(GPIO_D_NUM, 0xFF); - - ENERGEST_OFF(ENERGEST_TYPE_IRQ); +#define GPIO_PORT_ISR(lowercase_port, uppercase_port) \ +void \ +gpio_port_##lowercase_port##_isr(void) \ +{ \ + gpio_port_isr(GPIO_##uppercase_port##_NUM); \ } +GPIO_PORT_ISR(a, A) +GPIO_PORT_ISR(b, B) +GPIO_PORT_ISR(c, C) +GPIO_PORT_ISR(d, D) /*---------------------------------------------------------------------------*/ void gpio_init() diff --git a/cpu/cc2538/dev/gpio.h b/cpu/cc2538/dev/gpio.h index 33980501b..e97ba2825 100644 --- a/cpu/cc2538/dev/gpio.h +++ b/cpu/cc2538/dev/gpio.h @@ -210,6 +210,31 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); #define GPIO_DISABLE_INTERRUPT(PORT_BASE, PIN_MASK) \ do { REG((PORT_BASE) + GPIO_IE) &= ~(PIN_MASK); } while(0) +/** \brief Get raw interrupt status of port with PORT_BASE. + * \param PORT_BASE GPIO Port register offset + * \return Bit-mask reflecting the raw interrupt status of all the port pins + * + * The bits set in the returned bit-mask reflect the status of the interrupts + * trigger conditions detected (raw, before interrupt masking), indicating that + * all the requirements are met, before they are finally allowed to trigger by + * the interrupt mask. The bits cleared indicate that corresponding input pins + * have not initiated an interrupt. + */ +#define GPIO_GET_RAW_INT_STATUS(PORT_BASE) \ + REG((PORT_BASE) + GPIO_RIS) + +/** \brief Get masked interrupt status of port with PORT_BASE. + * \param PORT_BASE GPIO Port register offset + * \return Bit-mask reflecting the masked interrupt status of all the port pins + * + * The bits set in the returned bit-mask reflect the status of input lines + * triggering an interrupt. The bits cleared indicate that either no interrupt + * has been generated, or the interrupt is masked. This is the state of the + * interrupt after interrupt masking. + */ +#define GPIO_GET_MASKED_INT_STATUS(PORT_BASE) \ + REG((PORT_BASE) + GPIO_MIS) + /** \brief Clear interrupt triggering for pins with PIN_MASK of port with * PORT_BASE. * \param PORT_BASE GPIO Port register offset @@ -270,6 +295,14 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); do { REG(GPIO_PORT_TO_BASE(PORT) + GPIO_PI_IEN) &= \ ~((PIN_MASK) << ((PORT) << 3)); } while(0) +/** \brief Get power-up interrupt status of port PORT. + * \param PORT GPIO Port (not port base address) + * \return Bit-mask reflecting the power-up interrupt status of all the port + * pins + */ +#define GPIO_GET_POWER_UP_INT_STATUS(PORT) \ + ((REG(GPIO_PORT_TO_BASE(PORT) + GPIO_IRQ_DETECT_ACK) >> ((PORT) << 3)) & 0xFF) + /** \brief Clear power-up interrupt triggering for pins with PIN_MASK of port * PORT. * \param PORT GPIO Port (not port base address) diff --git a/cpu/cc2538/dev/i2c.c b/cpu/cc2538/dev/i2c.c index 29ded2967..76cac20f8 100644 --- a/cpu/cc2538/dev/i2c.c +++ b/cpu/cc2538/dev/i2c.c @@ -43,15 +43,7 @@ #include #include "clock.h" -/*---------------------------------------------------------------------------*/ -/* Additional functions */ -static uint32_t -get_sys_clock(void) -{ - /* Get the clock status diviser */ - return SYS_CTRL_32MHZ / - ((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SYS_DIV) + 1); -} +#include "sys-ctrl.h" /*---------------------------------------------------------------------------*/ void i2c_init(uint8_t port_sda, uint8_t pin_sda, uint8_t port_scl, uint8_t pin_scl, @@ -111,7 +103,7 @@ void i2c_set_frequency(uint32_t freq) { /* Peripheral clock setting, using the system clock */ - REG(I2CM_TPR) = ((get_sys_clock() + (2 * 10 * freq) - 1) / + REG(I2CM_TPR) = ((SYS_CTRL_SYS_CLOCK + (2 * 10 * freq) - 1) / (2 * 10 * freq)) - 1; } /*---------------------------------------------------------------------------*/ diff --git a/cpu/cc2538/dev/sha256.c b/cpu/cc2538/dev/sha256.c new file mode 100644 index 000000000..347c54081 --- /dev/null +++ b/cpu/cc2538/dev/sha256.c @@ -0,0 +1,356 @@ +/* + * Original file: + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.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-sha256 + * @{ + * + * \file + * Implementation of the cc2538 SHA-256 driver + */ +#include "contiki.h" +#include "sys/cc.h" +#include "dev/rom-util.h" +#include "dev/aes.h" +#include "dev/sha256.h" +#include "reg.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +#define BLOCK_SIZE 64 +#define OUTPUT_LEN 32 +/*---------------------------------------------------------------------------*/ +/** \brief Starts a new hash session in hardware + * \param state Hash state + * \param data Pointer to input message + * \param hash Destination of the hash (32 bytes) + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/SHA256 error code + */ +static uint8_t +new_hash(sha256_state_t *state, const void *data, void *hash) +{ + /* Workaround for AES registers not retained after PM2 */ + REG(AES_CTRL_INT_CFG) = AES_CTRL_INT_CFG_LEVEL; + REG(AES_CTRL_INT_EN) = AES_CTRL_INT_EN_DMA_IN_DONE | + AES_CTRL_INT_EN_RESULT_AV; + + /* Configure master control module and enable DMA path to the SHA-256 engine + * + Digest readout */ + REG(AES_CTRL_ALG_SEL) = AES_CTRL_ALG_SEL_TAG | AES_CTRL_ALG_SEL_HASH; + + /* Clear any outstanding events */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_RESULT_AV; + + /* Configure hash engine + * Indicate start of a new hash session and SHA-256 */ + REG(AES_HASH_MODE_IN) = AES_HASH_MODE_IN_SHA256_MODE | + AES_HASH_MODE_IN_NEW_HASH; + + /* If the final digest is required (pad the input DMA data), write the + * following register */ + if(state->final_digest) { + /* Write length of the message (lo) */ + REG(AES_HASH_LENGTH_IN_L) = (uint32_t)state->length; + /* Write length of the message (hi) */ + REG(AES_HASH_LENGTH_IN_H) = (uint32_t)(state->length >> 32); + /* Pad the DMA-ed data */ + REG(AES_HASH_IO_BUF_CTRL) = AES_HASH_IO_BUF_CTRL_PAD_DMA_MESSAGE; + } + + /* Enable DMA channel 0 for message data */ + REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN; + /* Base address of the data in ext. memory */ + REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)data; + if(state->final_digest) { + /* Input data length in bytes, equal to the message */ + REG(AES_DMAC_CH0_DMALENGTH) = state->curlen; + } else { + REG(AES_DMAC_CH0_DMALENGTH) = BLOCK_SIZE; + } + + /* Enable DMA channel 1 for result digest */ + REG(AES_DMAC_CH1_CTRL) = AES_DMAC_CH_CTRL_EN; + /* Base address of the digest buffer */ + REG(AES_DMAC_CH1_EXTADDR) = (uint32_t)hash; + /* Length of the result digest */ + REG(AES_DMAC_CH1_DMALENGTH) = OUTPUT_LEN; + + /* Wait for completion of the operation */ + while(!(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_RESULT_AV)); + + if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_DMA_BUS_ERR) { + /* Clear the DMA error */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_BUS_ERR; + /* Disable master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + return CRYPTO_DMA_BUS_ERROR; + } + + /* Clear the interrupt */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE | + AES_CTRL_INT_CLR_RESULT_AV; + /* Disable master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + /* Clear mode */ + REG(AES_AES_CTRL) = 0x00000000; + + return CRYPTO_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +/** \brief Resumes an already started hash session in hardware + * \param state Hash state + * \param data Pointer to the input message + * \param hash Pointer to the destination of the hash (32 bytes) + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/SHA256 error code + */ +static uint8_t +resume_hash(sha256_state_t *state, const void *data, void *hash) +{ + /* Workaround for AES registers not retained after PM2 */ + REG(AES_CTRL_INT_CFG) = AES_CTRL_INT_CFG_LEVEL; + REG(AES_CTRL_INT_EN) = AES_CTRL_INT_EN_DMA_IN_DONE | + AES_CTRL_INT_EN_RESULT_AV; + + /* Configure master control module and enable the DMA path to the SHA-256 + * engine */ + REG(AES_CTRL_ALG_SEL) = AES_CTRL_ALG_SEL_HASH; + + /* Clear any outstanding events */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_RESULT_AV; + + /* Configure hash engine + * Indicate the start of a resumed hash session and SHA-256 */ + REG(AES_HASH_MODE_IN) = AES_HASH_MODE_IN_SHA256_MODE; + + /* If the final digest is required (pad the input DMA data) */ + if(state->final_digest) { + /* Write length of the message (lo) */ + REG(AES_HASH_LENGTH_IN_L) = (uint32_t)state->length; + /* Write length of the message (hi) */ + REG(AES_HASH_LENGTH_IN_H) = (uint32_t)(state->length >> 32); + } + + /* Write the initial digest */ + REG(AES_HASH_DIGEST_A) = (uint32_t)state->state[0]; + REG(AES_HASH_DIGEST_B) = (uint32_t)state->state[1]; + REG(AES_HASH_DIGEST_C) = (uint32_t)state->state[2]; + REG(AES_HASH_DIGEST_D) = (uint32_t)state->state[3]; + REG(AES_HASH_DIGEST_E) = (uint32_t)state->state[4]; + REG(AES_HASH_DIGEST_F) = (uint32_t)state->state[5]; + REG(AES_HASH_DIGEST_G) = (uint32_t)state->state[6]; + REG(AES_HASH_DIGEST_H) = (uint32_t)state->state[7]; + + /* If final digest, pad the DMA-ed data */ + if(state->final_digest) { + REG(AES_HASH_IO_BUF_CTRL) = AES_HASH_IO_BUF_CTRL_PAD_DMA_MESSAGE; + } + + /* Enable DMA channel 0 for message data */ + REG(AES_DMAC_CH0_CTRL) = AES_DMAC_CH_CTRL_EN; + /* Base address of the data in ext. memory */ + REG(AES_DMAC_CH0_EXTADDR) = (uint32_t)data; + /* Input data length in bytes, equal to the message */ + if(state->final_digest) { + REG(AES_DMAC_CH0_DMALENGTH) = state->curlen; + } else { + REG(AES_DMAC_CH0_DMALENGTH) = BLOCK_SIZE; + } + + /* Wait for completion of the operation */ + while(!(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_RESULT_AV)); + + /* Check for any DMA Bus errors */ + if(REG(AES_CTRL_INT_STAT) & AES_CTRL_INT_STAT_DMA_BUS_ERR) { + /* Clear the DMA error */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_BUS_ERR; + /* Disable master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + return CRYPTO_DMA_BUS_ERROR; + } + + /* Read digest */ + ((uint32_t *)hash)[0] = REG(AES_HASH_DIGEST_A); + ((uint32_t *)hash)[1] = REG(AES_HASH_DIGEST_B); + ((uint32_t *)hash)[2] = REG(AES_HASH_DIGEST_C); + ((uint32_t *)hash)[3] = REG(AES_HASH_DIGEST_D); + ((uint32_t *)hash)[4] = REG(AES_HASH_DIGEST_E); + ((uint32_t *)hash)[5] = REG(AES_HASH_DIGEST_F); + ((uint32_t *)hash)[6] = REG(AES_HASH_DIGEST_G); + ((uint32_t *)hash)[7] = REG(AES_HASH_DIGEST_H); + + /* Acknowledge reading of the digest */ + REG(AES_HASH_IO_BUF_CTRL) = AES_HASH_IO_BUF_CTRL_OUTPUT_FULL; + + /* Clear the interrupt */ + REG(AES_CTRL_INT_CLR) = AES_CTRL_INT_CLR_DMA_IN_DONE | + AES_CTRL_INT_CLR_RESULT_AV; + /* Disable master control / DMA clock */ + REG(AES_CTRL_ALG_SEL) = 0x00000000; + /* Clear mode */ + REG(AES_AES_CTRL) = 0x00000000; + + return CRYPTO_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +uint8_t +sha256_init(sha256_state_t *state) +{ + if(state == NULL) { + return CRYPTO_NULL_ERROR; + } + + state->curlen = 0; + state->length = 0; + state->new_digest = true; + state->final_digest = false; + return CRYPTO_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +uint8_t +sha256_process(sha256_state_t *state, const void *data, uint32_t len) +{ + uint32_t n; + uint8_t ret; + + if(state == NULL || data == NULL) { + return CRYPTO_NULL_ERROR; + } + + if(state->curlen > sizeof(state->buf)) { + return CRYPTO_INVALID_PARAM; + } + + if(REG(AES_CTRL_ALG_SEL) != 0x00000000) { + return CRYPTO_RESOURCE_IN_USE; + } + + if(len > 0 && state->new_digest) { + if(state->curlen == 0 && len > BLOCK_SIZE) { + rom_util_memcpy(state->buf, data, BLOCK_SIZE); + ret = new_hash(state, state->buf, state->state); + if(ret != CRYPTO_SUCCESS) { + return ret; + } + state->new_digest = false; + state->length += BLOCK_SIZE << 3; + data += BLOCK_SIZE; + len -= BLOCK_SIZE; + } else { + n = MIN(len, BLOCK_SIZE - state->curlen); + rom_util_memcpy(&state->buf[state->curlen], data, n); + state->curlen += n; + data += n; + len -= n; + if(state->curlen == BLOCK_SIZE && len > 0) { + ret = new_hash(state, state->buf, state->state); + if(ret != CRYPTO_SUCCESS) { + return ret; + } + state->new_digest = false; + state->length += BLOCK_SIZE << 3; + state->curlen = 0; + } + } + } + + while(len > 0 && !state->new_digest) { + if(state->curlen == 0 && len > BLOCK_SIZE) { + rom_util_memcpy(state->buf, data, BLOCK_SIZE); + ret = resume_hash(state, state->buf, state->state); + if(ret != CRYPTO_SUCCESS) { + return ret; + } + state->length += BLOCK_SIZE << 3; + data += BLOCK_SIZE; + len -= BLOCK_SIZE; + } else { + n = MIN(len, BLOCK_SIZE - state->curlen); + rom_util_memcpy(&state->buf[state->curlen], data, n); + state->curlen += n; + data += n; + len -= n; + if(state->curlen == BLOCK_SIZE && len > 0) { + ret = resume_hash(state, state->buf, state->state); + if(ret != CRYPTO_SUCCESS) { + return ret; + } + state->length += BLOCK_SIZE << 3; + state->curlen = 0; + } + } + } + + return CRYPTO_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +uint8_t +sha256_done(sha256_state_t *state, void *hash) +{ + uint8_t ret; + + if(state == NULL || hash == NULL) { + return CRYPTO_NULL_ERROR; + } + + if(state->curlen > sizeof(state->buf)) { + return CRYPTO_INVALID_PARAM; + } + + if(REG(AES_CTRL_ALG_SEL) != 0x00000000) { + return CRYPTO_RESOURCE_IN_USE; + } + + /* Increase the length of the message */ + state->length += state->curlen << 3; + state->final_digest = true; + if(state->new_digest) { + ret = new_hash(state, state->buf, hash); + if(ret != CRYPTO_SUCCESS) { + return ret; + } + } else { + ret = resume_hash(state, state->buf, hash); + if(ret != CRYPTO_SUCCESS) { + return ret; + } + } + state->new_digest = false; + state->final_digest = false; + + return CRYPTO_SUCCESS; +} + +/** @} */ diff --git a/cpu/cc2538/dev/sha256.h b/cpu/cc2538/dev/sha256.h new file mode 100644 index 000000000..b2e799bd8 --- /dev/null +++ b/cpu/cc2538/dev/sha256.h @@ -0,0 +1,103 @@ +/* + * Original file: + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.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-crypto + * @{ + * + * \defgroup cc2538-sha526 cc2538 SHA-256 + * + * Driver for the cc2538 SHA-256 mode of the security core + * @{ + * + * \file + * Header file for the cc2538 SHA-256 driver + */ +#ifndef SHA256_H_ +#define SHA256_H_ + +#include "contiki.h" +#include "dev/crypto.h" + +#include +/*---------------------------------------------------------------------------*/ +/** \name SHA-256 structures + * @{ + */ +typedef struct { + uint64_t length; + uint32_t state[8]; + uint32_t curlen; + uint8_t buf[64]; + uint8_t new_digest; + uint8_t final_digest; +} sha256_state_t; +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name SHA-256 functions + * @{ + */ + +/** \brief Initializes the hash state + * \param state Pointer to hash state to initialize + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/SHA256 error code + */ +uint8_t sha256_init(sha256_state_t *state); + +/** \brief Processes a block of memory through the hash + * \param state Pointer to hash state + * \param data Pointer to the data to hash + * \param len Length of the data to hash in bytes (octets) + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/SHA256 error code + * \note This function must be called only after \c sha256_init(). + */ +uint8_t sha256_process(sha256_state_t *state, const void *data, uint32_t len); + +/** \brief Terminates hash session to get the digest + * \param state Pointer to hash state + * \param hash Pointer to hash + * \return \c CRYPTO_SUCCESS if successful, or CRYPTO/SHA256 error code + * \note This function must be called only after \c sha256_process(). + */ +uint8_t sha256_done(sha256_state_t *state, void *hash); + +/** @} */ + +#endif /* SHA256_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/spi.c b/cpu/cc2538/dev/spi.c index bff1783b5..48048a6a3 100644 --- a/cpu/cc2538/dev/spi.c +++ b/cpu/cc2538/dev/spi.c @@ -1,5 +1,9 @@ /* * Copyright (c) 2013, University of Michigan. + * + * Copyright (c) 2015, Weptech elektronik GmbH + * Author: Ulf Knoblich, ulf.knoblich@weptech.de + * * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -41,102 +45,281 @@ #include "dev/spi.h" #include "dev/ssi.h" #include "dev/gpio.h" +/*---------------------------------------------------------------------------*/ +/* Check port / pin settings for SPI0 and provide default values for spi_cfg */ +#ifndef SPI0_CLK_PORT +#define SPI0_CLK_PORT (-1) +#endif +#ifndef SPI0_CLK_PIN +#define SPI0_CLK_PIN (-1) +#endif +#if SPI0_CLK_PORT >= 0 && SPI0_CLK_PIN < 0 || \ + SPI0_CLK_PORT < 0 && SPI0_CLK_PIN >= 0 +#error Both SPI0_CLK_PORT and SPI0_CLK_PIN must be valid or invalid +#endif -#define SPI_CLK_PORT_BASE GPIO_PORT_TO_BASE(SPI_CLK_PORT) -#define SPI_CLK_PIN_MASK GPIO_PIN_MASK(SPI_CLK_PIN) -#define SPI_MOSI_PORT_BASE GPIO_PORT_TO_BASE(SPI_MOSI_PORT) -#define SPI_MOSI_PIN_MASK GPIO_PIN_MASK(SPI_MOSI_PIN) -#define SPI_MISO_PORT_BASE GPIO_PORT_TO_BASE(SPI_MISO_PORT) -#define SPI_MISO_PIN_MASK GPIO_PIN_MASK(SPI_MISO_PIN) +#ifndef SPI0_TX_PORT +#define SPI0_TX_PORT (-1) +#endif +#ifndef SPI0_TX_PIN +#define SPI0_TX_PIN (-1) +#endif +#if SPI0_TX_PORT >= 0 && SPI0_TX_PIN < 0 || \ + SPI0_TX_PORT < 0 && SPI0_TX_PIN >= 0 +#error Both SPI0_TX_PORT and SPI0_TX_PIN must be valid or invalid +#endif -/** - * \brief Initialize the SPI bus. - * - * This SPI init() function uses the following defines to set the pins: - * SPI_CLK_PORT SPI_CLK_PIN - * SPI_MOSI_PORT SPI_MOSI_PIN - * SPI_MISO_PORT SPI_MISO_PIN - * - * This sets the mode to Motorola SPI with the following format options: - * Clock phase: 1; data captured on second (rising) edge - * Clock polarity: 1; clock is high when idle - * Data size: 8 bits - */ +#ifndef SPI0_RX_PORT +#define SPI0_RX_PORT (-1) +#endif +#ifndef SPI0_RX_PIN +#define SPI0_RX_PIN (-1) +#endif +#if SPI0_RX_PORT >= 0 && SPI0_RX_PIN < 0 || \ + SPI0_RX_PORT < 0 && SPI0_RX_PIN >= 0 +#error Both SPI0_RX_PORT and SPI0_RX_PIN must be valid or invalid +#endif + +/* Here we check that either all or none of the ports are defined. As + we did already check that both ports + pins are either defined or + not for every pin, this means that we can check for an incomplete + configuration by only looking at the port defines */ +/* If some SPI0 pads are valid */ +#if SPI0_CLK_PORT >= 0 || SPI0_TX_PORT >= 0 || SPI0_RX_PORT >= 0 +/* but not all */ +#if SPI0_CLK_PORT < 0 || SPI0_TX_PORT < 0 || SPI0_RX_PORT < 0 +#error Some SPI0 pad definitions are invalid +#endif +#define SPI0_PADS_VALID +#endif +/*---------------------------------------------------------------------------*/ +/* Check port / pin settings for SPI1 and provide default values for spi_cfg */ +#ifndef SPI1_CLK_PORT +#define SPI1_CLK_PORT (-1) +#endif +#ifndef SPI1_CLK_PIN +#define SPI1_CLK_PIN (-1) +#endif +#if SPI1_CLK_PORT >= 0 && SPI1_CLK_PIN < 0 || \ + SPI1_CLK_PORT < 0 && SPI1_CLK_PIN >= 0 +#error Both SPI1_CLK_PORT and SPI1_CLK_PIN must be valid or invalid +#endif + +#ifndef SPI1_TX_PORT +#define SPI1_TX_PORT (-1) +#endif +#ifndef SPI1_TX_PIN +#define SPI1_TX_PIN (-1) +#endif +#if SPI1_TX_PORT >= 0 && SPI1_TX_PIN < 0 || \ + SPI1_TX_PORT < 0 && SPI1_TX_PIN >= 0 +#error Both SPI1_TX_PORT and SPI1_TX_PIN must be valid or invalid +#endif + +#ifndef SPI1_RX_PORT +#define SPI1_RX_PORT (-1) +#endif +#ifndef SPI1_RX_PIN +#define SPI1_RX_PIN (-1) +#endif +#if SPI1_RX_PORT >= 0 && SPI1_RX_PIN < 0 || \ + SPI1_RX_PORT < 0 && SPI1_RX_PIN >= 0 +#error Both SPI1_RX_PORT and SPI1_RX_PIN must be valid or invalid +#endif + +/* If some SPI1 pads are valid */ +#if SPI1_CLK_PORT >= 0 || SPI1_TX_PORT >= 0 || SPI1_RX_PORT >= 0 +/* but not all */ +#if SPI1_CLK_PORT < 0 || SPI1_TX_PORT < 0 || SPI1_RX_PORT < 0 +#error Some SPI1 pad definitions are invalid +#endif +#define SPI1_PADS_VALID +#endif + +#ifdef SPI_DEFAULT_INSTANCE +#if SPI_DEFAULT_INSTANCE == 0 +#ifndef SPI0_PADS_VALID +#error SPI_DEFAULT_INSTANCE is set to SPI0, but its pads are not valid +#endif +#elif SPI_DEFAULT_INSTANCE == 1 +#ifndef SPI1_PADS_VALID +#error SPI_DEFAULT_INSTANCE is set to SPI1, but its pads are not valid +#endif +#endif +#endif + +#if (SPI0_CPRS_CPSDVSR & 1) == 1 || SPI0_CPRS_CPSDVSR < 2 || SPI0_CPRS_CPSDVSR > 254 +#error SPI0_CPRS_CPSDVSR must be an even number between 2 and 254 +#endif + +#if (SPI1_CPRS_CPSDVSR & 1) == 1 || SPI1_CPRS_CPSDVSR < 2 || SPI1_CPRS_CPSDVSR > 254 +#error SPI1_CPRS_CPSDVSR must be an even number between 2 and 254 +#endif + +/*---------------------------------------------------------------------------*/ +typedef struct { + int8_t port; + int8_t pin; +} spi_pad_t; +typedef struct { + uint32_t base; + uint32_t ioc_ssirxd_ssi; + uint32_t ioc_pxx_sel_ssi_clkout; + uint32_t ioc_pxx_sel_ssi_txd; + uint8_t ssi_cprs_cpsdvsr; + spi_pad_t clk; + spi_pad_t tx; + spi_pad_t rx; +} spi_regs_t; +/*---------------------------------------------------------------------------*/ +static const spi_regs_t spi_regs[SSI_INSTANCE_COUNT] = { + { + .base = SSI0_BASE, + .ioc_ssirxd_ssi = IOC_SSIRXD_SSI0, + .ioc_pxx_sel_ssi_clkout = IOC_PXX_SEL_SSI0_CLKOUT, + .ioc_pxx_sel_ssi_txd = IOC_PXX_SEL_SSI0_TXD, + .ssi_cprs_cpsdvsr = SPI0_CPRS_CPSDVSR, + .clk = { SPI0_CLK_PORT, SPI0_CLK_PIN }, + .tx = { SPI0_TX_PORT, SPI0_TX_PIN }, + .rx = { SPI0_RX_PORT, SPI0_RX_PIN } + }, { + .base = SSI1_BASE, + .ioc_ssirxd_ssi = IOC_SSIRXD_SSI1, + .ioc_pxx_sel_ssi_clkout = IOC_PXX_SEL_SSI1_CLKOUT, + .ioc_pxx_sel_ssi_txd = IOC_PXX_SEL_SSI1_TXD, + .ssi_cprs_cpsdvsr = SPI1_CPRS_CPSDVSR, + .clk = { SPI1_CLK_PORT, SPI1_CLK_PIN }, + .tx = { SPI1_TX_PORT, SPI1_TX_PIN }, + .rx = { SPI1_RX_PORT, SPI1_RX_PIN } + } +}; +/*---------------------------------------------------------------------------*/ +/* Deprecated function call provided for compatibility reasons */ +#ifdef SPI_DEFAULT_INSTANCE void spi_init(void) { - spi_enable(); + spix_init(SPI_DEFAULT_INSTANCE); +} +#endif /* #ifdef SPI_DEFAULT_INSTANCE */ +/*---------------------------------------------------------------------------*/ +void +spix_init(uint8_t spi) +{ + const spi_regs_t *regs; + + if(spi >= SSI_INSTANCE_COUNT) { + return; + } + + regs = &spi_regs[spi]; + + if(regs->clk.port < 0) { + /* Port / pin configuration invalid. We checked for completeness + above. If clk.port is < 0, this means that all other defines are + < 0 as well */ + return; + } + + spix_enable(spi); /* Start by disabling the peripheral before configuring it */ - REG(SSI0_BASE + SSI_CR1) = 0; + REG(regs->base + SSI_CR1) = 0; - /* Set the IO clock as the SSI clock */ - REG(SSI0_BASE + SSI_CC) = 1; + /* Set the system clock as the SSI clock */ + REG(regs->base + SSI_CC) = 0; /* Set the mux correctly to connect the SSI pins to the correct GPIO pins */ - ioc_set_sel(SPI_CLK_PORT, SPI_CLK_PIN, IOC_PXX_SEL_SSI0_CLKOUT); - ioc_set_sel(SPI_MOSI_PORT, SPI_MOSI_PIN, IOC_PXX_SEL_SSI0_TXD); - REG(IOC_SSIRXD_SSI0) = (SPI_MISO_PORT * 8) + SPI_MISO_PIN; + ioc_set_sel(regs->clk.port, + regs->clk.pin, + regs->ioc_pxx_sel_ssi_clkout); + ioc_set_sel(regs->tx.port, + regs->tx.pin, + regs->ioc_pxx_sel_ssi_txd); + REG(regs->ioc_ssirxd_ssi) = (regs->rx.port * 8) + regs->rx.pin; /* Put all the SSI gpios into peripheral mode */ - GPIO_PERIPHERAL_CONTROL(SPI_CLK_PORT_BASE, SPI_CLK_PIN_MASK); - GPIO_PERIPHERAL_CONTROL(SPI_MOSI_PORT_BASE, SPI_MOSI_PIN_MASK); - GPIO_PERIPHERAL_CONTROL(SPI_MISO_PORT_BASE, SPI_MISO_PIN_MASK); + GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->clk.port), + GPIO_PIN_MASK(regs->clk.pin)); + GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->tx.port), + GPIO_PIN_MASK(regs->tx.pin)); + GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->rx.port), + GPIO_PIN_MASK(regs->rx.pin)); /* Disable any pull ups or the like */ - ioc_set_over(SPI_CLK_PORT, SPI_CLK_PIN, IOC_OVERRIDE_DIS); - ioc_set_over(SPI_MOSI_PORT, SPI_MOSI_PIN, IOC_OVERRIDE_DIS); - ioc_set_over(SPI_MISO_PORT, SPI_MISO_PIN, IOC_OVERRIDE_DIS); + ioc_set_over(regs->clk.port, regs->clk.pin, IOC_OVERRIDE_DIS); + ioc_set_over(regs->tx.port, regs->tx.pin, IOC_OVERRIDE_DIS); + ioc_set_over(regs->rx.port, regs->rx.pin, IOC_OVERRIDE_DIS); /* Configure the clock */ - REG(SSI0_BASE + SSI_CPSR) = 2; + REG(regs->base + SSI_CPSR) = regs->ssi_cprs_cpsdvsr; - /* Configure the default SPI options. + /* + * Configure the default SPI options. * mode: Motorola frame format * clock: High when idle * data: Valid on rising edges of the clock * bits: 8 byte data */ - REG(SSI0_BASE + SSI_CR0) = SSI_CR0_SPH | SSI_CR0_SPO | (0x07); + REG(regs->base + SSI_CR0) = SSI_CR0_SPH | SSI_CR0_SPO | (0x07); /* Enable the SSI */ - REG(SSI0_BASE + SSI_CR1) |= SSI_CR1_SSE; + REG(regs->base + SSI_CR1) |= SSI_CR1_SSE; } /*---------------------------------------------------------------------------*/ void -spi_cs_init(uint8_t port, uint8_t pin) +spix_enable(uint8_t spi) { - GPIO_SOFTWARE_CONTROL(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); + if(spi >= SSI_INSTANCE_COUNT) { + return; + } + REG(SYS_CTRL_RCGCSSI) |= (1 << spi); +} +/*---------------------------------------------------------------------------*/ +void +spix_disable(uint8_t spi) +{ + if(spi >= SSI_INSTANCE_COUNT) { + return; + } + REG(SYS_CTRL_RCGCSSI) &= ~(1 << spi); +} +/*---------------------------------------------------------------------------*/ +void +spix_set_mode(uint8_t spi, + uint32_t frame_format, + uint32_t clock_polarity, + uint32_t clock_phase, + uint32_t data_size) +{ + const spi_regs_t *regs; + + if(spi >= SSI_INSTANCE_COUNT) { + return; + } + + regs = &spi_regs[spi]; + + /* Disable the SSI peripheral to configure it */ + REG(regs->base + SSI_CR1) = 0; + + /* Configure the SSI options */ + REG(regs->base + SSI_CR0) = clock_phase | + clock_polarity | + frame_format | + (data_size - 1); + + /* Re-enable the SSI */ + REG(regs->base + SSI_CR1) |= SSI_CR1_SSE; +} +/*---------------------------------------------------------------------------*/ +void +spix_cs_init(uint8_t port, uint8_t pin) +{ + GPIO_SOFTWARE_CONTROL(GPIO_PORT_TO_BASE(port), + GPIO_PIN_MASK(pin)); ioc_set_over(port, pin, IOC_OVERRIDE_DIS); GPIO_SET_OUTPUT(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); GPIO_SET_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); } -/*---------------------------------------------------------------------------*/ -void -spi_enable(void) -{ - /* Enable the clock for the SSI peripheral */ - REG(SYS_CTRL_RCGCSSI) |= 1; -} -/*---------------------------------------------------------------------------*/ -void -spi_disable(void) -{ - /* Gate the clock for the SSI peripheral */ - REG(SYS_CTRL_RCGCSSI) &= ~1; -} -/*---------------------------------------------------------------------------*/ -void -spi_set_mode(uint32_t frame_format, uint32_t clock_polarity, - uint32_t clock_phase, uint32_t data_size) -{ - /* Disable the SSI peripheral to configure it */ - REG(SSI0_BASE + SSI_CR1) = 0; - - /* Configure the SSI options */ - REG(SSI0_BASE + SSI_CR0) = clock_phase | clock_polarity | frame_format | (data_size - 1); - - /* Re-enable the SSI */ - REG(SSI0_BASE + SSI_CR1) |= SSI_CR1_SSE; -} /** @} */ diff --git a/cpu/cc2538/dev/ssi.h b/cpu/cc2538/dev/ssi.h index da41a5b0a..ca06969ee 100644 --- a/cpu/cc2538/dev/ssi.h +++ b/cpu/cc2538/dev/ssi.h @@ -45,6 +45,12 @@ #ifndef SSI_H_ #define SSI_H_ +/*---------------------------------------------------------------------------*/ +/** \name Number of SSI instances supported by this CPU. + * @{ + */ +#define SSI_INSTANCE_COUNT 2 +/** @} */ /*---------------------------------------------------------------------------*/ /** \name Base register memory locations. * @{ diff --git a/cpu/cc2538/dev/sys-ctrl.c b/cpu/cc2538/dev/sys-ctrl.c index 87eabfa44..c2e8777ad 100644 --- a/cpu/cc2538/dev/sys-ctrl.c +++ b/cpu/cc2538/dev/sys-ctrl.c @@ -70,17 +70,18 @@ sys_ctrl_init() * 32KHz source: RC or crystal, according to SYS_CTRL_OSC32K_USE_XTAL * System Clock: 32 MHz * Power Down Unused - * I/O Div: 16MHz - * Sys Div: 16MHz + * I/O Div: according to SYS_CTRL_IO_DIV + * Sys Div: according to SYS_CTRL_SYS_DIV * Rest: Don't care */ val = SYS_CTRL_OSCS | SYS_CTRL_CLOCK_CTRL_OSC_PD - | SYS_CTRL_CLOCK_CTRL_IO_DIV_16MHZ | SYS_CTRL_CLOCK_CTRL_SYS_DIV_16MHZ; + | SYS_CTRL_IO_DIV | SYS_CTRL_SYS_DIV; REG(SYS_CTRL_CLOCK_CTRL) = val; - while((REG(SYS_CTRL_CLOCK_STA) & (SYS_CTRL_CLOCK_STA_OSC32K | - SYS_CTRL_CLOCK_STA_OSC)) != SYS_CTRL_OSCS); + while((REG(SYS_CTRL_CLOCK_STA) + & (SYS_CTRL_CLOCK_STA_OSC32K | SYS_CTRL_CLOCK_STA_OSC)) + != SYS_CTRL_OSCS); #if SYS_CTRL_OSC32K_USE_XTAL /* Wait for the 32-kHz crystal oscillator to stabilize */ @@ -94,7 +95,20 @@ sys_ctrl_reset() { REG(SYS_CTRL_PWRDBG) = SYS_CTRL_PWRDBG_FORCE_WARM_RESET; } - +/*---------------------------------------------------------------------------*/ +uint32_t +sys_ctrl_get_sys_clock(void) +{ + return SYS_CTRL_32MHZ >> (REG(SYS_CTRL_CLOCK_STA) & + SYS_CTRL_CLOCK_STA_SYS_DIV); +} +/*---------------------------------------------------------------------------*/ +uint32_t +sys_ctrl_get_io_clock(void) +{ + return SYS_CTRL_32MHZ >> ((REG(SYS_CTRL_CLOCK_STA) & + SYS_CTRL_CLOCK_STA_IO_DIV) >> 8); +} /** * @} * @} diff --git a/cpu/cc2538/dev/sys-ctrl.h b/cpu/cc2538/dev/sys-ctrl.h index 3c9885a89..3fda071fe 100644 --- a/cpu/cc2538/dev/sys-ctrl.h +++ b/cpu/cc2538/dev/sys-ctrl.h @@ -42,6 +42,8 @@ */ #ifndef SYS_CTRL_H_ #define SYS_CTRL_H_ + +#include /*---------------------------------------------------------------------------*/ /** \name SysCtrl Constants, used by the SYS_DIV and IO_DIV bits of the * SYS_CTRL_CLOCK_CTRL register @@ -159,6 +161,34 @@ #define SYS_CTRL_SRGPT_GPT0 0x00000001 /**< GPT0 is reset */ /** @} */ /*---------------------------------------------------------------------------*/ +/** \name SYS_CTRL_RCGCSEC register bit masks + * @{ + */ +#define SYS_CTRL_RCGCSEC_AES 0x00000002 /**< AES clock enable, CPU running */ +#define SYS_CTRL_RCGCSEC_PKA 0x00000001 /**< PKA clock enable, CPU running */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name SYS_CTRL_SCGCSEC register bit masks + * @{ + */ +#define SYS_CTRL_SCGCSEC_AES 0x00000002 /**< AES clock enable, CPU IDLE */ +#define SYS_CTRL_SCGCSEC_PKA 0x00000001 /**< PKA clock enable, CPU IDLE */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name SYS_CTRL_DCGCSEC register bit masks + * @{ + */ +#define SYS_CTRL_DCGCSEC_AES 0x00000002 /**< AES clock enable, PM0 */ +#define SYS_CTRL_DCGCSEC_PKA 0x00000001 /**< PKA clock enable, PM0 */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name SYS_CTRL_SRSEC register bits + * @{ + */ +#define SYS_CTRL_SRSEC_AES 0x00000002 /**< AES is reset */ +#define SYS_CTRL_SRSEC_PKA 0x00000001 /**< PKA is reset */ +/** @} */ +/*---------------------------------------------------------------------------*/ /** \name SYS_CTRL_PWRDBG register bits * @{ */ @@ -242,6 +272,33 @@ #endif /** @} */ /*---------------------------------------------------------------------------*/ +/** \name System clock divisor selection + * @{ + */ +#ifdef SYS_CTRL_CONF_SYS_DIV +#if SYS_CTRL_CONF_SYS_DIV & ~SYS_CTRL_CLOCK_CTRL_SYS_DIV +#error Invalid system clock divisor +#endif +#define SYS_CTRL_SYS_DIV SYS_CTRL_CONF_SYS_DIV +#else +#define SYS_CTRL_SYS_DIV SYS_CTRL_CLOCK_CTRL_SYS_DIV_16MHZ +#endif + +#ifdef SYS_CTRL_CONF_IO_DIV +#if SYS_CTRL_CONF_IO_DIV & ~SYS_CTRL_CLOCK_CTRL_IO_DIV +#error Invalid I/O clock divisor +#endif +#define SYS_CTRL_IO_DIV SYS_CTRL_CONF_IO_DIV +#else +#define SYS_CTRL_IO_DIV SYS_CTRL_CLOCK_CTRL_IO_DIV_16MHZ +#endif + +/* Returns actual system clock in Hz */ +#define SYS_CTRL_SYS_CLOCK (SYS_CTRL_32MHZ >> SYS_CTRL_SYS_DIV) +/* Returns actual I/O clock in Hz */ +#define SYS_CTRL_IO_CLOCK (SYS_CTRL_32MHZ >> (SYS_CTRL_IO_DIV >> 8)) +/** @} */ +/*---------------------------------------------------------------------------*/ /** \name SysCtrl functions * @{ */ @@ -253,6 +310,12 @@ void sys_ctrl_init(); /** \brief Generates a warm reset through the SYS_CTRL_PWRDBG register */ void sys_ctrl_reset(); +/** \brief Returns the actual system clock in Hz */ +uint32_t sys_ctrl_get_sys_clock(); + +/** \brief Returns the actual io clock in Hz */ +uint32_t sys_ctrl_get_io_clock(); + /** @} */ #endif /* SYS_CTRL_H_ */ diff --git a/cpu/cc2538/dev/uart.c b/cpu/cc2538/dev/uart.c index ea6a6a57a..cefbecf82 100644 --- a/cpu/cc2538/dev/uart.c +++ b/cpu/cc2538/dev/uart.c @@ -136,7 +136,7 @@ * Baud rate defines used in uart_init() to set the values of UART_IBRD and * UART_FBRD in order to achieve the configured baud rates. */ -#define UART_CLOCK_RATE 16000000 /* 16 MHz */ +#define UART_CLOCK_RATE SYS_CTRL_SYS_CLOCK #define UART_CTL_HSE_VALUE 0 #define UART_CTL_VALUE (UART_CTL_RXE | UART_CTL_TXE | (UART_CTL_HSE_VALUE << 5)) @@ -359,7 +359,7 @@ uart_write_byte(uint8_t uart, uint8_t b) REG(uart_base + UART_DR) = b; } /*---------------------------------------------------------------------------*/ -void +static void uart_isr(uint8_t uart) { uint32_t uart_base; diff --git a/cpu/cc2538/dev/vdd3-sensor.c b/cpu/cc2538/dev/vdd3-sensor.c new file mode 100644 index 000000000..678c25b8e --- /dev/null +++ b/cpu/cc2538/dev/vdd3-sensor.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, 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 cc2538-vdd3-sensor + * @{ + * + * \file + * Driver for the CC2538 VDD3 sensor + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "lib/sensors.h" +#include "dev/vdd3-sensor.h" +#include "dev/adc.h" +#include "dev/cc2538-sensors.h" + +#include +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + int raw = adc_get(SOC_ADC_ADCCON_CH_VDD_3, SOC_ADC_ADCCON_REF_INT, + SOC_ADC_ADCCON_DIV_512); + + if(type == CC2538_SENSORS_VALUE_TYPE_RAW) { + return raw; + } else if(type == CC2538_SENSORS_VALUE_TYPE_CONVERTED) { + return raw * (3 * 1190) / (2047 << 4); + } + + return CC2538_SENSORS_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(vdd3_sensor, VDD3_SENSOR, value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc2538/dev/vdd3-sensor.h b/cpu/cc2538/dev/vdd3-sensor.h new file mode 100644 index 000000000..aa0fcf94c --- /dev/null +++ b/cpu/cc2538/dev/vdd3-sensor.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, 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 cc2538-sensors + * @{ + * + * \defgroup cc2538-vdd3-sensor CC2538 VDD3 Sensor + * + * Driver for the CC2538 VDD3 sensor + * + * This driver can return the raw as well as the converted value of the sensor + * reading. This is controlled by the type argument of the sensor driver's + * value() function. The choices for the type argument are: + * - REMOTE_SENSORS_VALUE_TYPE_RAW (value() returns the raw reading) + * - REMOTE_SENSORS_VALUE_TYPE_CONVERTED (value() returns mV) + * @{ + * + * \file + * Header file for the CC2538 VDD3 Sensor Driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef VDD3_SENSOR_H_ +#define VDD3_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +/** + * \name VDD3 sensors + * @{ + */ +#define VDD3_SENSOR "VDD3" +/** @} */ +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor vdd3_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* VDD3_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc2538/lpm.c b/cpu/cc2538/lpm.c index 6270e51b7..91d67acc9 100644 --- a/cpu/cc2538/lpm.c +++ b/cpu/cc2538/lpm.c @@ -78,8 +78,8 @@ static unsigned long irq_energest = 0; #if LPM_CONF_STATS rtimer_clock_t lpm_stats[3]; -#define LPM_STATS_INIT() do { memset(lpm_stats, 0, sizeof(lpm_stats)); \ - } while(0) +#define LPM_STATS_INIT() \ + do { memset(lpm_stats, 0, sizeof(lpm_stats)); } while(0) #define LPM_STATS_ADD(pm, val) do { lpm_stats[pm] += val; } while(0) #else #define LPM_STATS_INIT() @@ -101,7 +101,7 @@ static uint8_t max_pm; #ifdef LPM_CONF_PERIPH_PERMIT_PM1_FUNCS_MAX #define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX LPM_CONF_PERIPH_PERMIT_PM1_FUNCS_MAX #else -#define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX 2 +#define LPM_PERIPH_PERMIT_PM1_FUNCS_MAX 3 #endif static lpm_periph_permit_pm1_func_t @@ -154,7 +154,7 @@ enter_pm0(void) static void select_32_mhz_xosc(void) { - /*First, make sure there is no ongoing clock source change */ + /* First, make sure there is no ongoing clock source change */ while((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SOURCE_CHANGE) != 0); /* Turn on the 32 MHz XOSC and source the system clock on it. */ @@ -163,8 +163,15 @@ select_32_mhz_xosc(void) /* Wait for the switch to take place */ while((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_OSC) != 0); - /* Power down the unused oscillator. */ - REG(SYS_CTRL_CLOCK_CTRL) |= SYS_CTRL_CLOCK_CTRL_OSC_PD; + /* Power down the unused oscillator and restore divisors (silicon errata) */ + REG(SYS_CTRL_CLOCK_CTRL) = (REG(SYS_CTRL_CLOCK_CTRL) +#if SYS_CTRL_SYS_DIV == SYS_CTRL_CLOCK_CTRL_SYS_DIV_32MHZ + & ~SYS_CTRL_CLOCK_CTRL_SYS_DIV +#endif +#if SYS_CTRL_IO_DIV == SYS_CTRL_CLOCK_CTRL_IO_DIV_32MHZ + & ~SYS_CTRL_CLOCK_CTRL_IO_DIV +#endif + ) | SYS_CTRL_CLOCK_CTRL_OSC_PD; } /*---------------------------------------------------------------------------*/ static void @@ -172,9 +179,19 @@ select_16_mhz_rcosc(void) { /* * Power up both oscillators in order to speed up the transition to the 32-MHz - * XOSC after wake up. + * XOSC after wake up. In addition, consider CC2538 silicon errata: + * "Possible Incorrect Value of Clock Dividers after PM2 and PM3" and + * set system clock divisor / I/O clock divisor to 16 MHz in case they run + * at full speed (=32 MHz) */ - REG(SYS_CTRL_CLOCK_CTRL) &= ~SYS_CTRL_CLOCK_CTRL_OSC_PD; + REG(SYS_CTRL_CLOCK_CTRL) = (REG(SYS_CTRL_CLOCK_CTRL) +#if SYS_CTRL_SYS_DIV == SYS_CTRL_CLOCK_CTRL_SYS_DIV_32MHZ + | SYS_CTRL_CLOCK_CTRL_SYS_DIV_16MHZ +#endif +#if SYS_CTRL_IO_DIV == SYS_CTRL_CLOCK_CTRL_IO_DIV_32MHZ + | SYS_CTRL_CLOCK_CTRL_IO_DIV_16MHZ +#endif + ) & ~SYS_CTRL_CLOCK_CTRL_OSC_PD; /*First, make sure there is no ongoing clock source change */ while((REG(SYS_CTRL_CLOCK_STA) & SYS_CTRL_CLOCK_STA_SOURCE_CHANGE) != 0); diff --git a/cpu/cc2538/spi-arch.h b/cpu/cc2538/spi-arch.h index 46d8d3bf4..137220b2f 100644 --- a/cpu/cc2538/spi-arch.h +++ b/cpu/cc2538/spi-arch.h @@ -1,5 +1,9 @@ /* * Copyright (c) 2013, University of Michigan. + * + * Copyright (c) 2015, Weptech elektronik GmbH + * Author: Ulf Knoblich, ulf.knoblich@weptech.de + * * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,66 +38,144 @@ * Header file for the cc2538 SPI driver, including macros for the * implementation of the low-level SPI primitives such as waiting for the TX * FIFO to be ready, inserting into the TX FIFO, etc. + * + * It supports the usage of SSI_NUM_INSTANCES instances by providing new + * functions calls like + * + * - spix_init(uint8_t instance) + * - spix_enable(uint8_t instance) + * - spix_disable(uint8_t instance) + * - spix_set_mode(unit8_t instance, ...) + * + * and new macros like + * + * - SPIX_WAITFORTxREADY(x) + * - SPIX_WAITFOREOTx(x) + * - SPIX_WAITFOREORx(x) + * - SPIX_FLUSH(x) + * + * Some of the old functions and macros are still supported. + * When using these deprecated functions, the SSI module to use + * has to be be selected by means of the macro SPI_CONF_DEFAULT_INSTANCE. + * + * This SPI driver depends on the following defines: + * + * For the SSI0 module: + * + * - SPI0_CKL_PORT + * - SPI0_CLK_PIN + * - SPI0_TX_PORT + * - SPI0_TX_PIN + * - SPI0_RX_PORT + * - SPI0_RX_PIN + * + * For the SSI1 module: + * + * - SPI1_CKL_PORT + * - SPI1_CLK_PIN + * - SPI1_TX_PORT + * - SPI1_TX_PIN + * - SPI1_RX_PORT + * - SPI1_RX_PIN */ #ifndef SPI_ARCH_H_ #define SPI_ARCH_H_ +#include "contiki.h" + #include "dev/ssi.h" - -#define SPI_WAITFORTxREADY() do { \ - while(!(REG(SSI0_BASE + SSI_SR) & SSI_SR_TNF)); \ -} while(0) - -#define SPI_TXBUF REG(SSI0_BASE + SSI_DR) - -#define SPI_RXBUF REG(SSI0_BASE + SSI_DR) - -#define SPI_WAITFOREOTx() do { \ - while(REG(SSI0_BASE + SSI_SR) & SSI_SR_BSY); \ -} while(0) - -#define SPI_WAITFOREORx() do { \ - while(!(REG(SSI0_BASE + SSI_SR) & SSI_SR_RNE)); \ -} while(0) - -#ifdef SPI_FLUSH -#error "You must include spi-arch.h before spi.h for the CC2538." +/*---------------------------------------------------------------------------*/ +/* The SPI instance to use when using the deprecated SPI API. */ +#ifdef SPI_CONF_DEFAULT_INSTANCE +#if SPI_CONF_DEFAULT_INSTANCE > (SSI_INSTANCE_COUNT - 1) +#error Invalid SPI_CONF_DEFAULT_INSTANCE: valid values are 0 and 1 +#else +#define SPI_DEFAULT_INSTANCE SPI_CONF_DEFAULT_INSTANCE +#endif +#endif +/*---------------------------------------------------------------------------*/ +/* Default values for the clock rate divider */ +#ifdef SPI0_CONF_CPRS_CPSDVSR +#define SPI0_CPRS_CPSDVSR SPI0_CONF_CPRS_CPSDVSR +#else +#define SPI0_CPRS_CPSDVSR 2 #endif -#define SPI_FLUSH() do { \ - SPI_WAITFOREORx(); \ - while (REG(SSI0_BASE + SSI_SR) & SSI_SR_RNE) { \ - SPI_RXBUF; \ - } \ -} while(0) -#define SPI_CS_CLR(port, pin) do { \ - GPIO_CLR_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); \ +#ifdef SPI1_CONF_CPRS_CPSDVSR +#define SPI1_CPRS_CPSDVSR SPI1_CONF_CPRS_CPSDVSR +#else +#define SPI1_CPRS_CPSDVSR 2 +#endif +/*---------------------------------------------------------------------------*/ +/* New API macros */ +#define SPIX_WAITFORTxREADY(spi) do { \ + while(!(REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_TNF)) ; \ } while(0) - -#define SPI_CS_SET(port, pin) do { \ - GPIO_SET_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); \ +#define SPIX_BUF(spi) REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_DR) +#define SPIX_WAITFOREOTx(spi) do { \ + while(REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_BSY) ; \ } while(0) +#define SPIX_WAITFOREORx(spi) do { \ + while(!(REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_RNE)) ; \ +} while(0) +#define SPIX_FLUSH(spi) do { \ + while(REG(CC_CONCAT3(SSI, spi, _BASE) + SSI_SR) & SSI_SR_RNE) { \ + SPIX_BUF(spi); \ + } \ +} while(0) +#define SPIX_CS_CLR(port, pin) do { \ + GPIO_CLR_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); \ +} while(0) +#define SPIX_CS_SET(port, pin) do { \ + GPIO_SET_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); \ +} while(0) +/*---------------------------------------------------------------------------*/ +/* Deprecated macros provided for compatibility reasons */ +#ifdef SPI_DEFAULT_INSTANCE +#define SPI_WAITFORTxREADY() SPIX_WAITFORTxREADY(SPI_DEFAULT_INSTANCE) +#define SPI_TXBUF SPIX_BUF(SPI_DEFAULT_INSTANCE) +#define SPI_RXBUF SPI_TXBUF +#define SPI_WAITFOREOTx() SPIX_WAITFOREOTx(SPI_DEFAULT_INSTANCE) +#define SPI_WAITFOREORx() SPIX_WAITFOREORx(SPI_DEFAULT_INSTANCE) +#ifdef SPI_FLUSH +#error You must include spi-arch.h before spi.h for the CC2538 +#else +#define SPI_FLUSH() SPIX_FLUSH(SPI_DEFAULT_INSTANCE) +#endif +#define SPI_CS_CLR(port, pin) SPIX_CS_CLR(port, pin) +#define SPI_CS_SET(port, pin) SPIX_CS_SET(port, pin) +#endif /* #ifdef SPI_DEFAULT_INSTANCE */ /*---------------------------------------------------------------------------*/ /** \name Arch-specific SPI functions * @{ */ /** - * \brief Configure a GPIO to be the chip select pin + * \brief Initialize the SPI bus for the instance given + * + * This sets the mode to Motorola SPI with the following format options: + * Clock phase: 1; data captured on second (rising) edge + * Clock polarity: 1; clock is high when idle + * Data size: 8 bits + * + * Use spix_set_mode() to change the spi mode. */ -void spi_cs_init(uint8_t port, uint8_t pin); - -/** \brief Enables the SPI peripheral - */ -void spi_enable(void); - -/** \brief Disables the SPI peripheral - * \note Call this function to save power when the SPI is unused. - */ -void spi_disable(void); +void spix_init(uint8_t spi); /** - * \brief Configure the SPI data and clock polarity and the data size. + * \brief Enables the SPI peripheral for the instance given + */ +void spix_enable(uint8_t spi); + +/** + * \brief Disables the SPI peripheral for the instance given + * \note Call this function to save power when the SPI is unused. + */ +void spix_disable(uint8_t spi); + +/** + * \brief Configure the SPI data and clock polarity and the data size for the + * instance given * * This function configures the SSI peripheral to use a particular SPI * configuration that a slave device requires. It should always be called @@ -101,6 +183,7 @@ void spi_disable(void); * * See section 19.4.4 in the CC2538 user guide for more information. * + * \param spi The SSI instance to use. * \param frame_format Set the SSI frame format. Use SSI_CR0_FRF_MOTOROLA, * SSI_CR0_FRF_TI, or SSI_CR0_FRF_MICROWIRE. * \param clock_polarity In Motorola mode, set whether the clock is high or low @@ -110,8 +193,17 @@ void spi_disable(void); * \param data_size The number of bits in each "byte" of data. Must be * between 4 and 16, inclusive. */ -void spi_set_mode(uint32_t frame_format, uint32_t clock_polarity, - uint32_t clock_phase, uint32_t data_size); +void spix_set_mode(uint8_t spi, uint32_t frame_format, + uint32_t clock_polarity, uint32_t clock_phase, + uint32_t data_size); + +/** + * \brief Configure a GPIO to be the chip select pin. + * + * Even if this function does not depend on the SPI instance used, we rename + * it to reflect the new naming convention. + */ +void spix_cs_init(uint8_t port, uint8_t pin); /** @} */ diff --git a/platform/cc2538dk/startup-gcc.c b/cpu/cc2538/startup-gcc.c similarity index 90% rename from platform/cc2538dk/startup-gcc.c rename to cpu/cc2538/startup-gcc.c index ce3db6dde..2aa82894e 100644 --- a/platform/cc2538dk/startup-gcc.c +++ b/cpu/cc2538/startup-gcc.c @@ -30,22 +30,24 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** - * \addtogroup cc2538dk + * \addtogroup cc2538 * @{ * * \file - * Startup code for the cc2538dk platform, to be used when building with gcc + * Startup code for the cc2538 chip, to be used when building with gcc */ #include "contiki.h" #include "reg.h" #include "flash-cca.h" #include "sys-ctrl.h" -#include "uart.h" +#include "rom-util.h" #include /*---------------------------------------------------------------------------*/ extern int main(void); /*---------------------------------------------------------------------------*/ +#define WEAK_ALIAS(x) __attribute__ ((weak, alias(#x))) +/*---------------------------------------------------------------------------*/ /* System handlers provided here */ void reset_handler(void); void nmi_handler(void); @@ -62,6 +64,10 @@ void cc2538_rf_rx_tx_isr(void); void cc2538_rf_err_isr(void); void udma_isr(void); void udma_err_isr(void); +void usb_isr(void) WEAK_ALIAS(default_handler); +void uart0_isr(void) WEAK_ALIAS(default_handler); +void uart1_isr(void) WEAK_ALIAS(default_handler); +void crypto_isr(void); /* Boot Loader Backdoor selection */ #if FLASH_CCA_CONF_BOOTLDR_BACKDOOR @@ -73,35 +79,19 @@ void udma_err_isr(void); #define FLASH_CCA_BOOTLDR_CFG_ACTIVE_LEVEL 0 #endif -#if ( (FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN < 0) || (FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN > 7) ) +#if ((FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN < 0) || (FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN > 7)) #error Invalid boot loader backdoor pin. Please set FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN between 0 and 7 (indicating PA0 - PA7). #endif -#define FLASH_CCA_BOOTLDR_CFG ( FLASH_CCA_BOOTLDR_CFG_ENABLE \ +#define FLASH_CCA_BOOTLDR_CFG (FLASH_CCA_BOOTLDR_CFG_ENABLE \ | FLASH_CCA_BOOTLDR_CFG_ACTIVE_LEVEL \ - | (FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN << FLASH_CCA_BOOTLDR_CFG_PORT_A_PIN_S) ) + | (FLASH_CCA_CONF_BOOTLDR_BACKDOOR_PORT_A_PIN << FLASH_CCA_BOOTLDR_CFG_PORT_A_PIN_S)) #else #define FLASH_CCA_BOOTLDR_CFG FLASH_CCA_BOOTLDR_CFG_DISABLE #endif - -/* Link in the USB ISR only if USB is enabled */ -#if USB_SERIAL_CONF_ENABLE -void usb_isr(void); -#else -#define usb_isr default_handler -#endif - -/* Likewise for the UART[01] ISRs */ -#if UART_CONF_ENABLE -void uart0_isr(void); -void uart1_isr(void); -#else /* UART_CONF_ENABLE */ -#define uart0_isr default_handler -#define uart1_isr default_handler -#endif /* UART_CONF_ENABLE */ /*---------------------------------------------------------------------------*/ /* Allocate stack space */ -static unsigned long stack[512]; +static unsigned long stack[512] __attribute__ ((section(".stack"))); /*---------------------------------------------------------------------------*/ /* Linker construct indicating .text section location */ extern uint8_t _text[0]; @@ -280,18 +270,18 @@ void(*const vectors[])(void) = usb_isr, /* 156 USB */ cc2538_rf_rx_tx_isr, /* 157 RFCORE RX/TX */ cc2538_rf_err_isr, /* 158 RFCORE Error */ - default_handler, /* 159 AES */ + crypto_isr, /* 159 AES */ default_handler, /* 160 PKA */ rtimer_isr, /* 161 SM Timer */ default_handler, /* 162 MACTimer */ }; /*---------------------------------------------------------------------------*/ /* Linker constructs indicating .data and .bss segment locations */ -extern unsigned long _etext; -extern unsigned long _data; -extern unsigned long _edata; -extern unsigned long _bss; -extern unsigned long _ebss; +extern uint8_t _ldata; +extern uint8_t _data; +extern uint8_t _edata; +extern uint8_t _bss; +extern uint8_t _ebss; /*---------------------------------------------------------------------------*/ /* Weak interrupt handlers. */ void @@ -310,26 +300,13 @@ default_handler(void) void reset_handler(void) { - unsigned long *pul_src, *pul_dst; - REG(SYS_CTRL_EMUOVR) = 0xFF; /* Copy the data segment initializers from flash to SRAM. */ - pul_src = &_etext; - - for(pul_dst = &_data; pul_dst < &_edata;) { - *pul_dst++ = *pul_src++; - } + rom_util_memcpy(&_data, &_ldata, &_edata - &_data); /* Zero-fill the bss segment. */ - __asm(" ldr r0, =_bss\n" - " ldr r1, =_ebss\n" - " mov r2, #0\n" - " .thumb_func\n" - "zero_loop:\n" - " cmp r0, r1\n" - " it lt\n" - " strlt r2, [r0], #4\n" " blt zero_loop"); + rom_util_memset(&_bss, 0, &_ebss - &_bss); /* call the application's entry point. */ main(); diff --git a/cpu/cc26xx/Makefile.cc26xx b/cpu/cc26xx/Makefile.cc26xx index a339bd9f1..7c09c75ee 100644 --- a/cpu/cc26xx/Makefile.cc26xx +++ b/cpu/cc26xx/Makefile.cc26xx @@ -6,34 +6,26 @@ OBJCOPY = arm-none-eabi-objcopy OBJDUMP = arm-none-eabi-objdump NM = arm-none-eabi-nm SIZE = arm-none-eabi-size +SREC_CAT = srec_cat -### TI CC26xxware out-of-tree -### TI_CC26XXWARE is the home directory of the cc26xxware -### It MUST be provided as a path relative to $(CONTIKI) -### For example, if -### CONTIKI = /home/user/contiki -### and TI_CC26XXWARE is stored in -### /home/user/cc26xxware -### then set -### TI_CC26XXWARE = ../cc26xxware -ifndef TI_CC26XXWARE - $(error TI_CC26XXWARE not defined. Please see the README) -endif +CPU_ABS_PATH = cpu/cc26xx +TI_CC26XXWARE_PATH = lib/cc26xxware +TI_CC26XXWARE = $(CONTIKI_CPU)/$(TI_CC26XXWARE_PATH) -### cc26xxware sources will be added to the MODULES list -TI_CC26XXWARE_SRC = $(TI_CC26XXWARE)/driverlib +### cc26xxware sources under driverlib will be added to the MODULES list +TI_CC26XXWARE_SRC = $(CPU_ABS_PATH)/$(TI_CC26XXWARE_PATH)/driverlib ### The directory with startup sources will be added to the CONTIKI_CPU_DIRS ### and the sources therein are added to the sources list explicitly. They are ### also listed explicitly in the linker command (through TARGET_STARTFILES), ### to make sure they always get linked in the image -TI_CC26XXWARE_STARTUP = ../../$(TI_CC26XXWARE)/startup_files +TI_CC26XXWARE_STARTUP_DIR = $(TI_CC26XXWARE_PATH)/startup_files TI_CC26XXWARE_STARTUP_SRCS = ccfg.c startup_gcc.c -### MODULES will add some of these to the include pach, but we need to add +### MODULES will add some of these to the include path, but we need to add ### them earlier to prevent filename clashes with Contiki core files -CFLAGS += -I$(CONTIKI)/$(TI_CC26XXWARE) -I$(CONTIKI)/$(TI_CC26XXWARE_SRC) -CFLAGS += -I$(CONTIKI)/$(TI_CC26XXWARE)/inc +CFLAGS += -I$(TI_CC26XXWARE) -I$(CONTIKI)/$(TI_CC26XXWARE_SRC) +CFLAGS += -I$(TI_CC26XXWARE)/inc MODULES += $(TI_CC26XXWARE_SRC) LDSCRIPT = $(CONTIKI_CPU)/cc26xx.ld @@ -70,7 +62,7 @@ endif CLEAN += symbols.c symbols.h *.d *.elf *.hex ### CPU-dependent directories -CONTIKI_CPU_DIRS = . dev dev/rfc-api $(TI_CC26XXWARE_STARTUP) +CONTIKI_CPU_DIRS = . dev dev/rfc-api $(TI_CC26XXWARE_STARTUP_DIR) ### Use the existing debug I/O in cpu/arm/common CONTIKI_CPU_DIRS += ../arm/common/dbg-io @@ -80,7 +72,7 @@ CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c cc26xx-rtc.c uart.c CONTIKI_CPU_SOURCEFILES += cc26xx-rf.c contiki-watchdog.c CONTIKI_CPU_SOURCEFILES += putchar.c ieee-addr.c batmon-sensor.c CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c cc26xx-uart.c lpm.c -CONTIKI_CPU_SOURCEFILES += gpio-interrupt.c +CONTIKI_CPU_SOURCEFILES += gpio-interrupt.c oscillators.c DEBUG_IO_SOURCEFILES += dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c @@ -106,9 +98,12 @@ CUSTOM_RULE_LINK=1 $(TRACE_LD) $(Q)$(LD) $(LDFLAGS) ${filter-out $(LDSCRIPT) %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -lm -o $@ -%.hex: %.elf +%.i16hex: %.elf $(OBJCOPY) -O ihex $< $@ +%.hex: %.i16hex + $(SREC_CAT) $< -intel -o $@ -intel + %.bin: %.elf $(OBJCOPY) $(OBJCOPY_FLAGS) $< $@ diff --git a/cpu/cc26xx/cc26xx.ld b/cpu/cc26xx/cc26xx.ld index 27c39c6c5..5902161c3 100644 --- a/cpu/cc26xx/cc26xx.ld +++ b/cpu/cc26xx/cc26xx.ld @@ -35,14 +35,14 @@ ENTRY(ResetISR) MEMORY { - /* Flash Size 128 KB minus the CCA area below (76 bytes) */ - FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x0001FFAC + /* Flash Size 128 KB minus the CCA area below (88 bytes) */ + FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x0001FFA8 /* * Customer Configuration Area and Bootloader Backdoor configuration - * in flash, up to 80 bytes + * in flash, up to 88 bytes */ - FLASH_CCFG (RX) : ORIGIN = 0x0001FFAC, LENGTH = 84 + FLASH_CCFG (RX) : ORIGIN = 0x0001FFA8, LENGTH = 88 /* RAM Size 20KB (PG2.1) */ SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 0x00005000 diff --git a/cpu/cc26xx/clock.c b/cpu/cc26xx/clock.c index c96158b48..701971e16 100644 --- a/cpu/cc26xx/clock.c +++ b/cpu/cc26xx/clock.c @@ -79,8 +79,14 @@ clock_init(void) * Here, we configure GPT0 Timer A, which we subsequently use in * clock_delay_usec * - * First, enable GPT0 in run mode. We don't need it in sleep mode + * We need to access registers, so firstly power up the PD and then enable + * the clock to GPT0. */ + if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) != + PRCM_DOMAIN_POWER_ON) { + power_domain_on(); + } + ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0); ti_lib_prcm_load_set(); while(!ti_lib_prcm_load_get()); @@ -155,11 +161,19 @@ clock_wait(clock_time_t i) void clock_delay_usec(uint16_t len) { + uint32_t clock_status; + if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) != PRCM_DOMAIN_POWER_ON) { power_domain_on(); } + clock_status = HWREG(PRCM_BASE + PRCM_O_GPTCLKGR) & PRCM_GPIOCLKGR_CLK_EN; + + ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + ti_lib_timer_load_set(GPT0_BASE, TIMER_B, len); ti_lib_timer_enable(GPT0_BASE, TIMER_B); @@ -168,6 +182,12 @@ clock_delay_usec(uint16_t len) * function, hence the direct register access here */ while(HWREG(GPT0_BASE + GPT_O_CTL) & GPT_CTL_TBEN); + + if(clock_status == 0) { + ti_lib_prcm_peripheral_run_disable(PRCM_PERIPH_TIMER0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + } } /*---------------------------------------------------------------------------*/ /** diff --git a/cpu/cc26xx/dev/batmon-sensor.c b/cpu/cc26xx/dev/batmon-sensor.c index 8131307a0..3af7a578a 100644 --- a/cpu/cc26xx/dev/batmon-sensor.c +++ b/cpu/cc26xx/dev/batmon-sensor.c @@ -61,28 +61,25 @@ static int enabled = SENSOR_STATUS_DISABLED; * \brief Returns a reading from the sensor * \param type BATMON_SENSOR_TYPE_TEMP or BATMON_SENSOR_TYPE_VOLT * - * \return The raw sensor reading, not converted to human-readable form + * \return The value as returned by the respective CC26xxware function */ static int value(int type) { - uint32_t tmp_value; - if(enabled == SENSOR_STATUS_DISABLED) { PRINTF("Sensor Disabled\n"); return 0; } if(type == BATMON_SENSOR_TYPE_TEMP) { - tmp_value = ti_lib_aon_batmon_temperature_get(); + return (int)ti_lib_aon_batmon_temperature_get_deg_c(); } else if(type == BATMON_SENSOR_TYPE_VOLT) { - tmp_value = ti_lib_aon_batmon_battery_voltage_get(); + return (int)ti_lib_aon_batmon_battery_voltage_get(); } else { PRINTF("Invalid type\n"); - return 0; } - return (int)tmp_value; + return 0; } /*---------------------------------------------------------------------------*/ /** @@ -101,7 +98,6 @@ configure(int type, int enable) switch(type) { case SENSORS_HW_INIT: ti_lib_aon_batmon_enable(); - ti_lib_aon_batmon_measurement_cycle_set(AON_BATMON_CYCLE_32); enabled = SENSOR_STATUS_ENABLED; break; case SENSORS_ACTIVE: diff --git a/cpu/cc26xx/dev/cc26xx-rf.c b/cpu/cc26xx/dev/cc26xx-rf.c index 2f874ceef..34e8d492a 100644 --- a/cpu/cc26xx/dev/cc26xx-rf.c +++ b/cpu/cc26xx/dev/cc26xx-rf.c @@ -39,6 +39,7 @@ #include "contiki.h" #include "dev/radio.h" #include "dev/cc26xx-rf.h" +#include "dev/oscillators.h" #include "net/packetbuf.h" #include "net/rime/rimestats.h" #include "net/linkaddr.h" @@ -46,6 +47,7 @@ #include "sys/energest.h" #include "sys/clock.h" #include "sys/rtimer.h" +#include "sys/cc.h" #include "lpm.h" #include "ti-lib.h" /*---------------------------------------------------------------------------*/ @@ -68,6 +70,7 @@ #include #include #include +#include /*---------------------------------------------------------------------------*/ #define BUSYWAIT_UNTIL(cond, max_time) \ do { \ @@ -76,10 +79,6 @@ while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \ } while(0) /*---------------------------------------------------------------------------*/ -#ifndef MIN -#define MIN(n, m) (((n) < (m)) ? (n) : (m)) -#endif -/*---------------------------------------------------------------------------*/ #ifdef __GNUC__ #define CC_ALIGN_ATTR(n) __attribute__ ((aligned(n))) #else @@ -267,15 +266,17 @@ const output_config_t *tx_power_current = &output_power[0]; /*---------------------------------------------------------------------------*/ /* RF interrupts */ #define RX_IRQ IRQ_IEEE_RX_ENTRY_DONE -#define TX_IRQ IRQ_IEEE_TX_FRAME #define TX_ACK_IRQ IRQ_IEEE_TX_ACK #define ERROR_IRQ IRQ_INTERNAL_ERROR +/* Those IRQs are enabled all the time */ +#define ENABLED_IRQS (RX_IRQ + ERROR_IRQ) + /* - * We don't really care about TX ISR, we just use it to bring the CM3 out - * of sleep, which it enters while the RF is TXing + * We only enable this right before starting frame TX, so we can sleep while + * the TX is ongoing */ -#define ENABLED_IRQS (RX_IRQ + TX_IRQ + ERROR_IRQ) +#define LAST_FG_CMD_DONE IRQ_LAST_FG_COMMAND_DONE #define cc26xx_rf_cpe0_isr RFCCPE0IntHandler #define cc26xx_rf_cpe1_isr RFCCPE1IntHandler @@ -391,80 +392,12 @@ static int on(void); static int off(void); static void setup_interrupts(void); /*---------------------------------------------------------------------------*/ -/* Select the HF XOSC as the source for the HF clock, but don't switch yet */ -static void -request_hf_xosc(void) -{ - /* Enable OSC DIG interface to change clock sources */ - ti_lib_osc_interface_enable(); - - /* 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); - - if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_XOSC_HF) { - /* - * Request to switch to the crystal to enable radio operation. It takes a - * while for the XTAL to be ready so instead of performing the actual - * switch, we return and we do other stuff while the XOSC is getting ready. - */ - ti_lib_osc_clock_source_set(OSC_SRC_CLK_MF | OSC_SRC_CLK_HF, OSC_XOSC_HF); - } - - /* Disable OSC DIG interface */ - ti_lib_osc_interface_disable(); -} -/*---------------------------------------------------------------------------*/ -/* - * Switch to the XOSC. This will block until the XOSC is ready, so this must - * be preceded by a call to select_hf_xosc() - */ -static void -switch_to_hf_xosc(void) -{ - /* Enable OSC DIG interface to change clock sources */ - ti_lib_osc_interface_enable(); - - /* 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); - - 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(); - } - - /* Disable OSC DIG interface */ - ti_lib_osc_interface_disable(); -} -/*---------------------------------------------------------------------------*/ -static void -switch_to_hf_rc_osc(void) -{ - /* Enable OSC DIG interface to change clock sources */ - ti_lib_osc_interface_enable(); - - /* 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); - - /* 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); - - /* Check to not enable HF RC oscillator if already enabled */ - if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_RCOSC_HF) { - /* Switch the HF clock source (cc26xxware executes this from ROM) */ - ti_lib_osc_hf_source_switch(); - } - ti_lib_osc_interface_disable(); -} -/*---------------------------------------------------------------------------*/ static uint8_t rf_is_accessible(void) { if(ti_lib_prcm_rf_ready() && ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE) == - PRCM_DOMAIN_POWER_ON) { + PRCM_DOMAIN_POWER_ON) { return 1; } return 0; @@ -496,16 +429,19 @@ static uint_fast8_t rf_send_cmd(uint32_t cmd, uint32_t *status) { uint32_t timeout_count = 0; + bool interrupts_disabled; /* * Make sure ContikiMAC doesn't turn us off from within an interrupt while * we are accessing RF Core registers */ - ti_lib_int_master_disable(); + interrupts_disabled = ti_lib_int_master_disable(); if(!rf_is_accessible()) { PRINTF("rf_send_cmd: RF was off\n"); - ti_lib_int_master_enable(); + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } return RF_CMD_ERROR; } @@ -514,12 +450,16 @@ rf_send_cmd(uint32_t cmd, uint32_t *status) *status = HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDSTA); if(++timeout_count > 50000) { PRINTF("rf_send_cmd: Timeout\n"); - ti_lib_int_master_enable(); + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } return RF_CMD_ERROR; } } while(*status == RF_CMD_STATUS_PENDING); - ti_lib_int_master_enable(); + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } /* * If we reach here the command is no longer pending. It is either completed @@ -976,8 +916,8 @@ static int power_up(void) { uint32_t cmd_status; + bool interrupts_disabled = ti_lib_int_master_disable(); - ti_lib_int_master_disable(); ti_lib_int_pend_clear(INT_RF_CPE0); ti_lib_int_pend_clear(INT_RF_CPE1); ti_lib_int_disable(INT_RF_CPE0); @@ -1000,7 +940,10 @@ power_up(void) HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0; ti_lib_int_enable(INT_RF_CPE0); ti_lib_int_enable(INT_RF_CPE1); - ti_lib_int_master_enable(); + + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } /* Let CPE boot */ HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = RF_CORE_CLOCKS_MASK; @@ -1020,7 +963,7 @@ power_up(void) static void power_down(void) { - ti_lib_int_master_disable(); + bool interrupts_disabled = ti_lib_int_master_disable(); ti_lib_int_disable(INT_RF_CPE0); ti_lib_int_disable(INT_RF_CPE1); @@ -1043,7 +986,9 @@ power_down(void) ti_lib_int_pend_clear(INT_RF_CPE1); ti_lib_int_enable(INT_RF_CPE0); ti_lib_int_enable(INT_RF_CPE1); - ti_lib_int_master_enable(); + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } } /*---------------------------------------------------------------------------*/ static int @@ -1158,6 +1103,8 @@ cc26xx_rf_cpe0_isr(void) static void setup_interrupts(void) { + bool interrupts_disabled; + /* We are already turned on by the caller, so this should not happen */ if(!rf_is_accessible()) { PRINTF("setup_interrupts: No access\n"); @@ -1165,7 +1112,7 @@ setup_interrupts(void) } /* Disable interrupts */ - ti_lib_int_master_disable(); + interrupts_disabled = ti_lib_int_master_disable(); /* Set all interrupt channels to CPE0 channel, error to CPE1 */ HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEISL) = ERROR_IRQ; @@ -1180,7 +1127,10 @@ setup_interrupts(void) ti_lib_int_pend_clear(INT_RF_CPE1); ti_lib_int_enable(INT_RF_CPE0); ti_lib_int_enable(INT_RF_CPE1); - ti_lib_int_master_enable(); + + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } } /*---------------------------------------------------------------------------*/ static uint8_t @@ -1197,7 +1147,7 @@ request(void) return LPM_MODE_MAX_SUPPORTED; } /*---------------------------------------------------------------------------*/ -LPM_MODULE(cc26xx_rf_lpm_module, request, NULL, NULL); +LPM_MODULE(cc26xx_rf_lpm_module, request, NULL, NULL, LPM_DOMAIN_NONE); /*---------------------------------------------------------------------------*/ static int init(void) @@ -1295,6 +1245,10 @@ transmit(unsigned short transmit_len) GET_FIELD(cmd_immediate_buf, CMD_IEEE_TX, payloadLen) = transmit_len; GET_FIELD(cmd_immediate_buf, CMD_IEEE_TX, pPayload) = tx_buf; + /* Enable the LAST_FG_COMMAND_DONE interrupt, which will wake us up */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS + + LAST_FG_CMD_DONE; + ret = rf_send_cmd((uint32_t)cmd_immediate_buf, &cmd_status); if(ret) { @@ -1335,9 +1289,11 @@ transmit(unsigned short transmit_len) ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); ENERGEST_ON(ENERGEST_TYPE_LISTEN); - if(was_off) { - off(); - } + /* + * Disable LAST_FG_COMMAND_DONE interrupt. We don't really care about it + * except when we are transmitting + */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS; return ret; } @@ -1522,7 +1478,7 @@ 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. */ - request_hf_xosc(); + oscillators_request_hf_xosc(); /* * If we are in the middle of a BLE operation, we got called by ContikiMAC @@ -1560,7 +1516,7 @@ on(void) * 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/ */ - switch_to_hf_xosc(); + oscillators_switch_to_hf_xosc(); if(rf_radio_setup(RF_MODE_IEEE) != RF_CMD_OK) { PRINTF("on: radio_setup() failed\n"); @@ -1589,7 +1545,7 @@ off(void) power_down(); /* Switch HF clock source to the RCOSC to preserve power */ - switch_to_hf_rc_osc(); + oscillators_switch_to_hf_rc(); /* We pulled the plug, so we need to restore the status manually */ GET_FIELD(cmd_ieee_rx_buf, radioOp, status) = IDLE; @@ -1985,6 +1941,7 @@ PROCESS_THREAD(cc26xx_rf_ble_beacon_process, ev, data) uint8_t was_on; int j; uint32_t cmd_status; + bool interrupts_disabled; PROCESS_BEGIN(); @@ -2015,9 +1972,11 @@ PROCESS_THREAD(cc26xx_rf_ble_beacon_process, ev, data) * Under ContikiMAC, some IEEE-related operations will be called from an * interrupt context. We need those to see that we are in BLE mode. */ - ti_lib_int_master_disable(); + interrupts_disabled = ti_lib_int_master_disable(); ble_mode_on = 1; - ti_lib_int_master_enable(); + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } /* * Send BLE_ADV_MESSAGES beacon bursts. Each burst on all three @@ -2053,7 +2012,7 @@ PROCESS_THREAD(cc26xx_rf_ble_beacon_process, ev, data) } } else { /* Request the HF XOSC to source the HF clock. */ - request_hf_xosc(); + oscillators_request_hf_xosc(); /* We were off: Boot the CPE */ if(power_up() != RF_CMD_OK) { @@ -2071,7 +2030,7 @@ PROCESS_THREAD(cc26xx_rf_ble_beacon_process, ev, data) } /* Trigger a switch to the XOSC, so that we can use the FS */ - switch_to_hf_xosc(); + oscillators_switch_to_hf_xosc(); } /* Enter BLE mode */ @@ -2110,13 +2069,17 @@ PROCESS_THREAD(cc26xx_rf_ble_beacon_process, ev, data) power_down(); /* Switch HF clock source to the RCOSC to preserve power */ - switch_to_hf_rc_osc(); + oscillators_switch_to_hf_rc(); } etimer_set(&ble_adv_et, BLE_ADV_DUTY_CYCLE); - ti_lib_int_master_disable(); + interrupts_disabled = ti_lib_int_master_disable(); + ble_mode_on = 0; - ti_lib_int_master_enable(); + + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } /* Wait unless this is the last burst */ if(i < BLE_ADV_MESSAGES - 1) { @@ -2124,9 +2087,13 @@ PROCESS_THREAD(cc26xx_rf_ble_beacon_process, ev, data) } } - ti_lib_int_master_disable(); + interrupts_disabled = ti_lib_int_master_disable(); + ble_mode_on = 0; - ti_lib_int_master_enable(); + + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } } PROCESS_END(); } diff --git a/cpu/cc26xx/dev/cc26xx-rf.h b/cpu/cc26xx/dev/cc26xx-rf.h index 4087a037d..a278e085d 100644 --- a/cpu/cc26xx/dev/cc26xx-rf.h +++ b/cpu/cc26xx/dev/cc26xx-rf.h @@ -66,7 +66,7 @@ #define CC26XX_RF_AUTOACK 1 #endif /* CC26XX_RF_CONF_AUTOACK */ -#if defined (CC26XX_RF_CONF_BLE_SUPPORT) && (CC26XX_MODEL_CPU_VARIANT == 2650) +#if (CC26XX_RF_CONF_BLE_SUPPORT) && (CC26XX_MODEL_CPU_VARIANT == 2650) #define CC26XX_RF_BLE_SUPPORT CC26XX_RF_CONF_BLE_SUPPORT #else #define CC26XX_RF_BLE_SUPPORT 0 diff --git a/cpu/cc26xx/dev/cc26xx-rtc.c b/cpu/cc26xx/dev/cc26xx-rtc.c index b06aebd22..e9c01a7b5 100644 --- a/cpu/cc26xx/dev/cc26xx-rtc.c +++ b/cpu/cc26xx/dev/cc26xx-rtc.c @@ -44,6 +44,7 @@ #include "ti-lib.h" #include +#include /*---------------------------------------------------------------------------*/ #define cc26xx_rtc_isr(...) AONRTCIntHandler(__VA_ARGS__) /*---------------------------------------------------------------------------*/ @@ -54,9 +55,11 @@ void cc26xx_rtc_init(void) { uint32_t compare_value; + bool interrupts_disabled; /* Disable and clear interrupts */ - ti_lib_int_master_disable(); + interrupts_disabled = ti_lib_int_master_disable(); + ti_lib_aon_rtc_disable(); ti_lib_aon_rtc_event_clear(AON_RTC_CH0); @@ -65,22 +68,25 @@ cc26xx_rtc_init(void) /* Setup the wakeup event */ ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU0, AON_EVENT_RTC0); ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU1, AON_EVENT_RTC2); + ti_lib_aon_rtc_combined_event_config(AON_RTC_CH0 | AON_RTC_CH2); /* Configure channel 2 in continuous compare, 128 ticks / sec */ + ti_lib_aon_rtc_inc_value_ch2_set(RTIMER_SECOND / CLOCK_SECOND); + ti_lib_aon_rtc_mode_ch2_set(AON_RTC_MODE_CH2_CONTINUOUS); compare_value = (RTIMER_SECOND / CLOCK_SECOND) + ti_lib_aon_rtc_current_compare_value_get(); ti_lib_aon_rtc_compare_value_set(AON_RTC_CH2, compare_value); - ti_lib_aon_rtc_inc_value_ch2_set(RTIMER_SECOND / CLOCK_SECOND); - ti_lib_aon_rtc_mode_ch2_set(AON_RTC_MODE_CH2_CONTINUOUS); - /* Enable event generation for channels 0 and 2 and enable the RTC */ - ti_lib_aon_rtc_combined_event_config(AON_RTC_CH0 | AON_RTC_CH2); + /* Enable channel 2 and the RTC */ ti_lib_aon_rtc_channel_enable(AON_RTC_CH2); - ti_lib_aon_rtc_enable(); ti_lib_int_enable(INT_AON_RTC); - ti_lib_int_master_enable(); + + /* Re-enable interrupts */ + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } } /*---------------------------------------------------------------------------*/ rtimer_clock_t @@ -91,7 +97,7 @@ cc26xx_rtc_get_next_trigger() if(HWREG(AON_RTC_BASE + AON_RTC_O_CHCTL) & AON_RTC_CHCTL_CH0_EN) { rtimer_clock_t ch0 = ti_lib_aon_rtc_compare_value_get(AON_RTC_CH2); - return RTIMER_CLOCK_LT(ch0 ,ch2) ? ch0 : ch2; + return RTIMER_CLOCK_LT(ch0, ch2) ? ch0 : ch2; } return ch2; diff --git a/cpu/cc26xx/dev/cc26xx-uart.c b/cpu/cc26xx/dev/cc26xx-uart.c index 5a45bb03b..5d6c5403d 100644 --- a/cpu/cc26xx/dev/cc26xx-uart.c +++ b/cpu/cc26xx/dev/cc26xx-uart.c @@ -40,6 +40,7 @@ #include "sys/energest.h" #include +#include /*---------------------------------------------------------------------------*/ /* Which events to trigger a UART interrupt */ #define CC26XX_UART_RX_INTERRUPT_TRIGGERS (UART_INT_RX | UART_INT_RT) @@ -53,35 +54,98 @@ /*---------------------------------------------------------------------------*/ static int (*input_handler)(unsigned char c); /*---------------------------------------------------------------------------*/ -static void -power_domain_on(void) +static bool +usable(void) { + if(BOARD_IOID_UART_RX == IOID_UNUSED || + BOARD_IOID_UART_TX == IOID_UNUSED || + CC26XX_UART_CONF_ENABLE == 0) { + return false; + } + + return true; +} +/*---------------------------------------------------------------------------*/ +static void +power_and_clock(void) +{ + /* Power on the SERIAL PD */ ti_lib_prcm_power_domain_on(PRCM_DOMAIN_SERIAL); while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) != PRCM_DOMAIN_POWER_ON); + + /* Enable UART clock in active mode */ + ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_UART0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); +} +/*---------------------------------------------------------------------------*/ +/* + * Returns 0 if either the SERIAL PD is off, or the PD is on but the run mode + * clock is gated. If this function would return 0, accessing UART registers + * will return a precise bus fault. If this function returns 1, it is safe to + * access UART registers. + * + * This function only checks the 'run mode' clock gate, since it can only ever + * be called with the MCU in run mode. + */ +static bool +accessible(void) +{ + /* First, check the PD */ + if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) + != PRCM_DOMAIN_POWER_ON) { + return false; + } + + /* Then check the 'run mode' clock gate */ + if(!(HWREG(PRCM_BASE + PRCM_O_UARTCLKGR) & PRCM_UARTCLKGR_CLK_EN)) { + return false; + } + + return true; } /*---------------------------------------------------------------------------*/ static void -configure_baud_rate(void) +disable_interrupts(void) { + /* Acknowledge UART interrupts */ + ti_lib_int_disable(INT_UART0); + + /* Disable all UART module interrupts */ + ti_lib_uart_int_disable(UART0_BASE, CC26XX_UART_INTERRUPT_ALL); + + /* Clear all UART interrupts */ + ti_lib_uart_int_clear(UART0_BASE, CC26XX_UART_INTERRUPT_ALL); +} +/*---------------------------------------------------------------------------*/ +static void +enable_interrupts(void) +{ + /* Clear all UART interrupts */ + ti_lib_uart_int_clear(UART0_BASE, CC26XX_UART_INTERRUPT_ALL); + + /* Enable RX-related interrupts only if we have an input handler */ + if(input_handler) { + /* Configure which interrupts to generate: FIFO level or after RX timeout */ + ti_lib_uart_int_enable(UART0_BASE, CC26XX_UART_RX_INTERRUPT_TRIGGERS); + + /* Acknowledge UART interrupts */ + ti_lib_int_enable(INT_UART0); + } +} +/*---------------------------------------------------------------------------*/ +static void +configure(void) +{ + uint32_t ctl_val = UART_CTL_UARTEN | UART_CTL_TXE; /* - * Configure the UART for 115,200, 8-N-1 operation. - * This function uses SysCtrlClockGet() to get the system clock - * frequency. This could be also be a variable or hard coded value - * instead of a function call. + * Make sure the TX pin is output / high before assigning it to UART control + * to avoid falling edge glitches */ - ti_lib_uart_config_set_exp_clk(UART0_BASE, - ti_lib_sys_ctrl_peripheral_clock_get( - PRCM_PERIPH_UART0, - SYSCTRL_SYSBUS_ON), - CC26XX_UART_CONF_BAUD_RATE, - (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | - UART_CONFIG_PAR_NONE)); -} -/*---------------------------------------------------------------------------*/ -static void -configure_registers(void) -{ + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_UART_TX); + ti_lib_gpio_pin_write(BOARD_UART_TX, 1); + /* * Map UART signals to the correct GPIO pins and configure them as * hardware controlled. @@ -89,7 +153,11 @@ configure_registers(void) ti_lib_ioc_pin_type_uart(UART0_BASE, BOARD_IOID_UART_RX, BOARD_IOID_UART_TX, BOARD_IOID_UART_CTS, BOARD_IOID_UART_RTS); - configure_baud_rate(); + /* Configure the UART for 115,200, 8-N-1 operation. */ + ti_lib_uart_config_set_exp_clk(UART0_BASE, ti_lib_sys_ctrl_clock_get(), + CC26XX_UART_CONF_BAUD_RATE, + (UART_CONFIG_WLEN_8 | UART_CONFIG_STOP_ONE | + UART_CONFIG_PAR_NONE)); /* * Generate an RX interrupt at FIFO 1/2 full. @@ -97,116 +165,138 @@ configure_registers(void) */ ti_lib_uart_fifo_level_set(UART0_BASE, UART_FIFO_TX7_8, UART_FIFO_RX4_8); - /* Configure which interrupts to generate: FIFO level or after RX timeout */ - ti_lib_uart_int_enable(UART0_BASE, CC26XX_UART_RX_INTERRUPT_TRIGGERS); -} -/*---------------------------------------------------------------------------*/ -static void -uart_on(void) -{ - power_domain_on(); + /* Enable FIFOs */ + HWREG(UART0_BASE + UART_O_LCRH) |= UART_LCRH_FEN; - /* Configure baud rate and enable */ - if((HWREG(UART0_BASE + UART_O_CTL) & UART_CTL_UARTEN) == 0) { - configure_registers(); - - /* Enable UART */ - ti_lib_uart_enable(UART0_BASE); + if(input_handler) { + ctl_val += UART_CTL_RXE; } -} -/*---------------------------------------------------------------------------*/ -static uint8_t -lpm_permit_max_pm_handler(void) -{ - return LPM_MODE_MAX_SUPPORTED; + + /* Enable TX, RX (conditionally), and the UART. */ + HWREG(UART0_BASE + UART_O_CTL) = ctl_val; } /*---------------------------------------------------------------------------*/ static void lpm_drop_handler(uint8_t mode) { - /* Do nothing if the PD is off */ - if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) - != PRCM_DOMAIN_POWER_ON) { - return; + /* + * First, wait for any outstanding TX to complete. If we have an input + * handler, the SERIAL PD will be kept on and the UART module clock will + * be enabled under sleep as well as deep sleep. In theory, this means that + * we shouldn't lose any outgoing bytes, but we actually do on occasion. + * This byte loss may (or may not) be related to the freezing of IO latches + * between MCU and AON when we drop to deep sleep. This here is essentially a + * workaround + */ + if(accessible() == true) { + while(ti_lib_uart_busy(UART0_BASE)); } - /* Wait for outstanding TX to complete */ - while(ti_lib_uart_busy(UART0_BASE)); - /* - * Check our clock gate under Deep Sleep. If it's off, we can shut down. If - * it's on, this means that some other code module wants UART functionality - * during deep sleep, so we stay enabled + * If we have a registered input_handler then we need to retain RX + * capability. Thus, if this is not a shutdown notification and we have an + * input handler, we do nothing */ - if((HWREG(PRCM_BASE + PRCM_O_UARTCLKGDS) & 1) == 0) { - ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_UART_RX); - ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_UART_TX); - - ti_lib_uart_disable(UART0_BASE); - } -} -/*---------------------------------------------------------------------------*/ -static void -lpm_wakeup_handler(void) -{ - uart_on(); -} -/*---------------------------------------------------------------------------*/ -/* Declare a data structure to register with LPM. */ -LPM_MODULE(uart_module, lpm_permit_max_pm_handler, - lpm_drop_handler, lpm_wakeup_handler); -/*---------------------------------------------------------------------------*/ -void -cc26xx_uart_init() -{ - /* Exit without initialising if ports are misconfigured */ - if(BOARD_IOID_UART_RX == IOID_UNUSED || - BOARD_IOID_UART_TX == IOID_UNUSED) { + if((mode != LPM_MODE_SHUTDOWN) && (input_handler != NULL)) { return; } - /* Enable the serial domain and wait for domain to be on */ - power_domain_on(); + /* + * If we reach here, we either don't care about staying awake or we have + * received a shutdown notification + * + * Only touch UART registers if the module is powered and clocked + */ + if(accessible() == true) { + /* Disable the module */ + ti_lib_uart_disable(UART0_BASE); - /* Enable the UART clock when running and sleeping */ - ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_UART0); + /* Disable all UART interrupts and clear all flags */ + disable_interrupts(); + } - /* Apply clock settings and wait for them to take effect */ + /* + * Always stop the clock in run mode. Also stop in Sleep and Deep Sleep if + * this is a request for full shutdown + */ + ti_lib_prcm_peripheral_run_disable(PRCM_PERIPH_UART0); + if(mode == LPM_MODE_SHUTDOWN) { + ti_lib_prcm_peripheral_sleep_disable(PRCM_PERIPH_UART0); + ti_lib_prcm_peripheral_deep_sleep_disable(PRCM_PERIPH_UART0); + } ti_lib_prcm_load_set(); while(!ti_lib_prcm_load_get()); - /* Disable Interrupts */ - ti_lib_int_master_disable(); + /* Set pins to low leakage configuration in preparation for deep sleep */ + lpm_pin_set_default_state(BOARD_IOID_UART_TX); + lpm_pin_set_default_state(BOARD_IOID_UART_RX); + lpm_pin_set_default_state(BOARD_IOID_UART_CTS); + lpm_pin_set_default_state(BOARD_IOID_UART_RTS); +} +/*---------------------------------------------------------------------------*/ +/* Declare a data structure to register with LPM. */ +LPM_MODULE(uart_module, NULL, lpm_drop_handler, NULL, LPM_DOMAIN_NONE); +/*---------------------------------------------------------------------------*/ +static void +enable(void) +{ + power_and_clock(); /* Make sure the peripheral is disabled */ ti_lib_uart_disable(UART0_BASE); - /* Disable all UART module interrupts */ - ti_lib_uart_int_disable(UART0_BASE, CC26XX_UART_INTERRUPT_ALL); + /* Disable all UART interrupts and clear all flags */ + disable_interrupts(); - configure_registers(); + /* Setup pins, Baud rate and FIFO levels */ + configure(); - /* Acknowledge UART interrupts */ - ti_lib_int_enable(INT_UART0); + /* Enable UART interrupts */ + enable_interrupts(); +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_uart_init() +{ + bool interrupts_disabled; - /* Re-enable processor interrupts */ - ti_lib_int_master_enable(); + /* Return early if disabled by user conf or if ports are misconfigured */ + if(usable() == false) { + return; + } - /* Enable UART */ - ti_lib_uart_enable(UART0_BASE); + /* Disable Interrupts */ + interrupts_disabled = ti_lib_int_master_disable(); /* Register ourselves with the LPM module */ lpm_register_module(&uart_module); + + /* Only TX and EN to start with. RX will be enabled only if needed */ + input_handler = NULL; + + /* + * init() won't actually fire up the UART. We turn it on only when (and if) + * it gets requested, either to enable input or to send out a character + * + * Thus, we simply re-enable processor interrupts here + */ + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } } /*---------------------------------------------------------------------------*/ void cc26xx_uart_write_byte(uint8_t c) { - if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) - != PRCM_DOMAIN_POWER_ON) { + /* Return early if disabled by user conf or if ports are misconfigured */ + if(usable() == false) { return; } + if(accessible() == false) { + enable(); + } + ti_lib_uart_char_put(UART0_BASE, c); } /*---------------------------------------------------------------------------*/ @@ -214,9 +304,52 @@ void cc26xx_uart_set_input(int (*input)(unsigned char c)) { input_handler = input; + + /* Return early if disabled by user conf or if ports are misconfigured */ + if(usable() == false) { + return; + } + + if(input == NULL) { + /* Let the SERIAL PD power down */ + uart_module.domain_lock = LPM_DOMAIN_NONE; + + /* Disable module clocks under sleep and deep sleep */ + ti_lib_prcm_peripheral_sleep_disable(PRCM_PERIPH_UART0); + ti_lib_prcm_peripheral_deep_sleep_disable(PRCM_PERIPH_UART0); + } else { + /* Request the SERIAL PD to stay on during deep sleep */ + uart_module.domain_lock = LPM_DOMAIN_SERIAL; + + /* Enable module clocks under sleep and deep sleep */ + ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_UART0); + ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_UART0); + } + + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + enable(); + return; } /*---------------------------------------------------------------------------*/ +uint8_t +cc26xx_uart_busy(void) +{ + /* Return early if disabled by user conf or if ports are misconfigured */ + if(usable() == false) { + return UART_IDLE; + } + + /* If the UART is not accessible, it is not busy */ + if(accessible() == false) { + return UART_IDLE; + } + + return ti_lib_uart_busy(UART0_BASE); +} +/*---------------------------------------------------------------------------*/ void cc26xx_uart_isr(void) { @@ -225,6 +358,8 @@ cc26xx_uart_isr(void) ENERGEST_ON(ENERGEST_TYPE_IRQ); + power_and_clock(); + /* Read out the masked interrupt status */ flags = ti_lib_uart_int_status(UART0_BASE, true); diff --git a/cpu/cc26xx/dev/cc26xx-uart.h b/cpu/cc26xx/dev/cc26xx-uart.h index 4647b9339..8ff04502f 100644 --- a/cpu/cc26xx/dev/cc26xx-uart.h +++ b/cpu/cc26xx/dev/cc26xx-uart.h @@ -63,9 +63,32 @@ void cc26xx_uart_write_byte(uint8_t b); /** * \brief Assigns a callback to be called when the UART receives a byte * \param input A pointer to the function + * + * If \e input is NULL, the UART driver will assume that RX functionality is + * not required and it will be disabled. It will also disable the module's + * clocks under sleep and deep sleep and allow the SERIAL PD to be powered off. + * + * If \e input is not NULL, the UART driver will assume that RX is in fact + * required and it will be enabled. The module's clocks will be enabled under + * sleep and deep sleep and the driver will not allow the SERIAL PD to turn + * off during deep sleep, so that the UART can still receive bytes. + * + * \note This has a significant impact on overall energy consumption, so you + * should only enabled UART RX input when it's actually required. */ void cc26xx_uart_set_input(int (*input)(unsigned char c)); +/** + * \brief Returns the UART busy status + * \return UART_IDLE or UART_BUSY + * + * ti_lib_uart_busy() will access UART registers. It is our responsibility + * to first make sure the UART is accessible before calling it. Hence this + * wrapper. + * + * Return values are defined in CC26xxware's uart.h + */ +uint8_t cc26xx_uart_busy(void); /** @} */ /*---------------------------------------------------------------------------*/ #endif /* CC26XX_UART_H_ */ diff --git a/cpu/cc26xx/dev/contiki-watchdog.c b/cpu/cc26xx/dev/contiki-watchdog.c index 8241b5045..2c833c9d4 100644 --- a/cpu/cc26xx/dev/contiki-watchdog.c +++ b/cpu/cc26xx/dev/contiki-watchdog.c @@ -54,7 +54,7 @@ void watchdog_init(void) { - ti_lib_wathdog_reload_set(0xFFFFF); + ti_lib_watchdog_reload_set(0xFFFFF); } /*---------------------------------------------------------------------------*/ /** @@ -63,7 +63,7 @@ watchdog_init(void) void watchdog_start(void) { - ti_lib_wathdog_reset_enable(); + ti_lib_watchdog_reset_enable(); } /*---------------------------------------------------------------------------*/ /** @@ -72,7 +72,7 @@ watchdog_start(void) void watchdog_periodic(void) { - ti_lib_wathdog_int_clear(); + ti_lib_watchdog_int_clear(); } /*---------------------------------------------------------------------------*/ /** diff --git a/cpu/cc26xx/dev/oscillators.c b/cpu/cc26xx/dev/oscillators.c new file mode 100644 index 000000000..06f97a92a --- /dev/null +++ b/cpu/cc26xx/dev/oscillators.c @@ -0,0 +1,172 @@ +/* + * 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-oscillators + * @{ + * + * \file + * Implementation of CC26xxware oscillator control wrappers. + */ +/*---------------------------------------------------------------------------*/ +#include "ti-lib.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(); + + /* Switch LF clock source to the LF XOSC if required */ + if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_XOSC_LF) { + ti_lib_osc_clock_source_set(OSC_SRC_CLK_LF, OSC_XOSC_LF); + + /* Wait for LF clock source to become XOSC_LF */ + while(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_XOSC_LF); + + /* Disable the LF clock qualifiers */ + ti_lib_ddi_16_bit_field_write(AUX_DDI0_OSC_BASE, DDI_0_OSC_O_CTL0, + DDI_0_OSC_CTL0_BYPASS_XOSC_LF_CLK_QUAL_M | + DDI_0_OSC_CTL0_BYPASS_RCOSC_LF_CLK_QUAL_M, + DDI_0_OSC_CTL0_BYPASS_RCOSC_LF_CLK_QUAL_S, + 0x3); + } + + /* Restore the SMPH clock and disable the OSC interface */ + osc_interface_dis(smph_clk_state); +} +/*---------------------------------------------------------------------------*/ +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(); + + /* Switch LF clock source to the LF XOSC if required */ + if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_RCOSC_LF) { + ti_lib_osc_clock_source_set(OSC_SRC_CLK_LF, OSC_RCOSC_LF); + + /* Wait for LF clock source to become XOSC_LF */ + 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); +} +/*---------------------------------------------------------------------------*/ +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(); + + if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_XOSC_HF) { + /* + * Request to switch to the crystal to enable radio operation. It takes a + * while for the XTAL to be ready so instead of performing the actual + * switch, we return and we do other stuff while the XOSC is getting ready. + */ + 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); +} +/*---------------------------------------------------------------------------*/ +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(); + + 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); +} +/*---------------------------------------------------------------------------*/ +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(); + + /* 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); + + /* Check to not enable HF RC oscillator if already enabled */ + if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_HF) != OSC_RCOSC_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); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/dev/oscillators.h b/cpu/cc26xx/dev/oscillators.h new file mode 100644 index 000000000..2de1b5bb7 --- /dev/null +++ b/cpu/cc26xx/dev/oscillators.h @@ -0,0 +1,101 @@ +/* + * 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 + * @{ + * + * \defgroup cc26xx-oscillators CC26XX oscillator control + * + * Wrapper around those CC26xxware OSC functions that we need in Contiki. + * + * All CC26xxware OSC control requires access to the semaphore module within + * AUX. Thus, in addition to enabling the oscillator interface, we need to + * start the clock to SMPH and restore it to its previous state when we are + * done. + * @{ + * + * \file + * Header file for the CC26XX oscillator control + */ +/*---------------------------------------------------------------------------*/ +#ifndef OSCILLATORS_H_ +#define OSCILLATORS_H_ +/*---------------------------------------------------------------------------*/ +/** + * \brief Set the LF clock source to be the LF XOSC + * + * This function is only called once as soon as the system starts. + * + * Do not switch the LF clock source to the RC OSC for normal system operation + * See CC26xx Errata (swrz058) + */ +void oscillators_select_lf_xosc(void); + +/** + * \brief Set the LF clock source to be the LF RCOSC + * + * This function is only called once, when the systen transitions to a full + * shutdown + * + * Do not switch the LF clock source to the RC OSC for normal system operation + * See CC26xx Errata (swrz058) + */ +void oscillators_select_lf_rcosc(void); + +/** + * \brief Requests the HF XOSC as the source for the HF clock, but does not + * perform the actual switch. + * + * This triggers the startup sequence of the HF XOSC and returns so the CPU + * can perform other tasks while the XOSC is starting. + * + * The XOSC is requested as the source for the HF as well as the MF clock. + */ +void oscillators_request_hf_xosc(void); + +/** + * \brief Performs the switch to the XOSC + * + * This function must be preceded by a call to oscillators_request_hf_xosc() + */ +void oscillators_switch_to_hf_xosc(void); + +/** + * \brief Switches MF and HF clock source to be the HF RC OSC + */ +void oscillators_switch_to_hf_rc(void); +/*---------------------------------------------------------------------------*/ +#endif /* OSCILLATORS_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/lib/cc26xxware b/cpu/cc26xx/lib/cc26xxware new file mode 160000 index 000000000..420ae3682 --- /dev/null +++ b/cpu/cc26xx/lib/cc26xxware @@ -0,0 +1 @@ +Subproject commit 420ae3682c11619c1340697632b2dc49f7e53037 diff --git a/cpu/cc26xx/lpm.c b/cpu/cc26xx/lpm.c index 0322f940c..a0d633472 100644 --- a/cpu/cc26xx/lpm.c +++ b/cpu/cc26xx/lpm.c @@ -49,6 +49,7 @@ #include "dev/leds.h" #include "dev/watchdog.h" #include "dev/cc26xx-rtc.h" +#include "dev/oscillators.h" /*---------------------------------------------------------------------------*/ #if ENERGEST_CONF_ON static unsigned long irq_energest = 0; @@ -64,9 +65,6 @@ static unsigned long irq_energest = 0; /*---------------------------------------------------------------------------*/ LIST(modules_list); /*---------------------------------------------------------------------------*/ -/* Control what power domains we are allow to run under what mode */ -LIST(power_domain_locks_list); - /* PDs that may stay on in deep sleep */ #define LOCKABLE_DOMAINS ((uint32_t)(PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH)) /*---------------------------------------------------------------------------*/ @@ -76,49 +74,48 @@ LIST(power_domain_locks_list); */ #define STANDBY_MIN_DURATION (RTIMER_SECOND >> 8) /*---------------------------------------------------------------------------*/ -/* Variables used by the power on/off (Power mode: SHUTDOWN) functionality */ -static uint8_t shutdown_requested; -static uint32_t pin; -/*---------------------------------------------------------------------------*/ void -lpm_pd_lock_obtain(lpm_power_domain_lock_t *lock, uint32_t domains) -{ - /* We only accept locks for specific PDs */ - domains &= LOCKABLE_DOMAINS; - - if(domains == 0) { - return; - } - - lock->domains = domains; - - list_add(power_domain_locks_list, lock); -} -/*---------------------------------------------------------------------------*/ -void -lpm_pd_lock_release(lpm_power_domain_lock_t *lock) -{ - lock->domains = 0; - - list_remove(power_domain_locks_list, lock); -} -/*---------------------------------------------------------------------------*/ -void -lpm_shutdown(uint32_t wakeup_pin) -{ - shutdown_requested = 1; - pin = wakeup_pin; -} -/*---------------------------------------------------------------------------*/ -static void -shutdown_now(void) +lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on) { lpm_registered_module_t *module; - int i; - rtimer_clock_t t0; - uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | IOC_IOPULL_UP | - IOC_WAKE_ON_LOW; + int i, j; + uint32_t io_cfg = (IOC_STD_INPUT & ~IOC_IOPULL_M) | io_pull | + wake_on; + /* This procedure may not be interrupted */ + ti_lib_int_master_disable(); + + /* Disable the RTC */ + ti_lib_aon_rtc_disable(); + 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); + + /* Reset AON even fabric to default wakeup sources */ + for(i = AON_EVENT_MCU_WU0; i <= AON_EVENT_MCU_WU3; i++) { + ti_lib_aon_event_mcu_wake_up_set(i, AON_EVENT_NULL); + } + for(i = AON_EVENT_AUX_WU0; i <= AON_EVENT_AUX_WU2; i++) { + ti_lib_aon_event_aux_wake_up_set(i, AON_EVENT_NULL); + } + + ti_lib_sys_ctrl_aon_sync(); + + watchdog_periodic(); + + /* fade away....... */ + j = 1000; + + for(i = j; i > 0; --i) { + leds_on(LEDS_ALL); + clock_delay_usec(i); + leds_off(LEDS_ALL); + clock_delay_usec(j - i); + } + + leds_off(LEDS_ALL); + + /* Notify all modules that we're shutting down */ for(module = list_head(modules_list); module != NULL; module = module->next) { if(module->shutdown) { @@ -126,34 +123,74 @@ shutdown_now(void) } } - leds_off(LEDS_ALL); + /* Configure the wakeup trigger */ + ti_lib_gpio_dir_mode_set((1 << wakeup_pin), GPIO_DIR_MODE_IN); + ti_lib_ioc_port_configure_set(wakeup_pin, IOC_PORT_GPIO, io_cfg); - for(i = 0; i < 5; i++) { - t0 = RTIMER_NOW(); - leds_toggle(LEDS_ALL); - while(RTIMER_CLOCK_LT(RTIMER_NOW(), (t0 + (RTIMER_SECOND >> 3)))); - } + /* Freeze I/O latches in AON */ + ti_lib_aon_ioc_freeze_enable(); - leds_off(LEDS_ALL); + /* Turn off RFCORE, SERIAL and PERIPH PDs. This will happen immediately */ + ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_SERIAL | + PRCM_DOMAIN_PERIPH); - ti_lib_gpio_dir_mode_set((1 << pin), GPIO_DIR_MODE_IN); - ti_lib_ioc_port_configure_set(pin, IOC_PORT_GPIO, io_cfg); + oscillators_switch_to_hf_rc(); + oscillators_select_lf_rcosc(); - ti_lib_pwr_ctrl_state_set(LPM_MODE_SHUTDOWN); + /* 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); + + /* Disable SRAM and AUX retentions */ + ti_lib_aon_wuc_mcu_sram_config(0); + ti_lib_aon_wuc_aux_sram_config(false); + + /* + * Request CPU, SYSBYS and VIMS PD off. + * This will only happen when the CM3 enters deep sleep + */ + ti_lib_prcm_power_domain_off(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); + + /* + * Request MCU VD power off. + * This will only happen when the CM3 enters deep sleep + */ + ti_lib_prcm_mcu_power_off(); + + /* Set MCU wakeup to immediate and disable virtual power off */ + ti_lib_aon_wuc_mcu_wake_up_config(MCU_IMM_WAKE_UP); + ti_lib_aon_wuc_mcu_power_off_config(MCU_VIRT_PWOFF_DISABLE); + + /* Latch the IOs in the padring and enable I/O pad sleep mode */ + ti_lib_pwr_ctrl_io_freeze_enable(); + + /* Turn off VIMS cache, CRAM and TRAM - possibly not required */ + ti_lib_prcm_cache_retention_disable(); + ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF); + + /* Enable shutdown and sync AON */ + ti_lib_aon_wuc_shut_down_enable(); + ti_lib_sys_ctrl_aon_sync(); + + /* Deep Sleep */ + ti_lib_prcm_deep_sleep(); } /*---------------------------------------------------------------------------*/ /* - * We'll get called on three occasions: - * - While running - * - While sleeping - * - While deep sleeping - * - * For the former two, we don't need to do anything. For the latter, we - * notify all modules that we're back on and rely on them to restore clocks + * Notify all modules that we're back on and rely on them to restore clocks * and power domains as required. */ -void -lpm_wake_up() +static void +wake_up(void) { lpm_registered_module_t *module; @@ -177,13 +214,13 @@ lpm_wake_up() /* Turn on cache again */ ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_ENABLED); - ti_lib_prcm_retention_enable(PRCM_DOMAIN_VIMS); + ti_lib_prcm_cache_retention_enable(); ti_lib_aon_ioc_freeze_disable(); ti_lib_sys_ctrl_aon_sync(); - /* Power up AUX and allow it to go to sleep */ - ti_lib_aon_wuc_aux_wakeup_event(AONWUC_AUX_ALLOW_SLEEP); + /* Check operating conditions, optimally choose DCDC versus GLDO */ + ti_lib_sys_ctrl_dcdc_voltage_conditional_control(); /* Notify all registered modules that we've just woken up */ for(module = list_head(modules_list); module != NULL; @@ -198,16 +235,11 @@ void lpm_drop() { lpm_registered_module_t *module; - lpm_power_domain_lock_t *lock; uint8_t max_pm = LPM_MODE_MAX_SUPPORTED; uint8_t module_pm; uint32_t domains = LOCKABLE_DOMAINS; - if(shutdown_requested) { - shutdown_now(); - } - if(RTIMER_CLOCK_LT(cc26xx_rtc_get_next_trigger(), RTIMER_NOW() + STANDBY_MIN_DURATION)) { lpm_sleep(); @@ -244,26 +276,21 @@ lpm_drop() * 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); } - } - /* - * Iterate PD locks to see what we can and cannot turn off. - * - * 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(lock = list_head(power_domain_locks_list); lock != NULL; - lock = lock->next) { /* Clear the bits specified in the lock */ - domains &= ~lock->domains; + domains &= ~module->domain_lock; } /* Pat the dog: We don't want it to shout right after we wake up */ @@ -289,6 +316,20 @@ lpm_drop() 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); @@ -297,19 +338,9 @@ lpm_drop() ti_lib_aon_wuc_mcu_sram_config(MCU_RAM0_RETENTION | MCU_RAM1_RETENTION | MCU_RAM2_RETENTION | MCU_RAM3_RETENTION); - /* Enable retention on the CPU domain */ - ti_lib_prcm_retention_enable(PRCM_DOMAIN_CPU); - /* Disable retention of AUX RAM */ ti_lib_aon_wuc_aux_sram_config(false); - /* Disable retention in the RFCORE RAM */ - HWREG(PRCM_BASE + PRCM_O_RAMRETEN) &= ~PRCM_RAMRETEN_RFC; - - /* Disable retention of VIMS RAM (TRAM and CRAM) */ - //TODO: This can probably be removed, we are calling ti_lib_prcm_retention_disable(PRCM_DOMAIN_VIMS); further down - HWREG(PRCM_BASE + PRCM_O_RAMRETEN) &= ~PRCM_RAMRETEN_VIMS_M; - /* * Always turn off RFCORE, CPU, SYSBUS and VIMS. RFCORE should be off * already @@ -323,13 +354,13 @@ lpm_drop() /* 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() & AONWUC_AUX_POWER_ON); + 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(false); /* - * If both PERIPH and SERIAL PDs are off, request the uLDO for as the power + * If both PERIPH and SERIAL PDs are off, request the uLDO as the power * source while in deep sleep. */ if(domains == LOCKABLE_DOMAINS) { @@ -350,7 +381,7 @@ lpm_drop() * until right before deep sleep to be able to use the cache for as long * as possible. */ - ti_lib_prcm_retention_disable(PRCM_DOMAIN_VIMS); + ti_lib_prcm_cache_retention_disable(); ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF); /* Deep Sleep */ @@ -362,7 +393,7 @@ lpm_drop() * the chip properly, and then we will enable the global interrupt without * unpending events so the handlers can fire */ - lpm_wake_up(); + wake_up(); ti_lib_int_master_enable(); } @@ -396,10 +427,26 @@ lpm_register_module(lpm_registered_module_t *module) } /*---------------------------------------------------------------------------*/ void +lpm_unregister_module(lpm_registered_module_t *module) +{ + list_remove(modules_list, module); +} +/*---------------------------------------------------------------------------*/ +void lpm_init() { list_init(modules_list); - list_init(power_domain_locks_list); +} +/*---------------------------------------------------------------------------*/ +void +lpm_pin_set_default_state(uint32_t ioid) +{ + if(ioid == IOID_UNUSED) { + return; + } + + ti_lib_ioc_port_configure_set(ioid, IOC_PORT_GPIO, IOC_STD_OUTPUT); + ti_lib_gpio_dir_mode_set((1 << ioid), GPIO_DIR_MODE_IN); } /*---------------------------------------------------------------------------*/ /** diff --git a/cpu/cc26xx/lpm.h b/cpu/cc26xx/lpm.h index 85c20e77b..8b701baff 100644 --- a/cpu/cc26xx/lpm.h +++ b/cpu/cc26xx/lpm.h @@ -49,17 +49,22 @@ #include /*---------------------------------------------------------------------------*/ -#define LPM_MODE_SLEEP PWRCTRL_ACTIVE -#define LPM_MODE_DEEP_SLEEP PWRCTRL_POWER_DOWN -#define LPM_MODE_SHUTDOWN PWRCTRL_SHUTDOWN +#define LPM_MODE_SLEEP 1 +#define LPM_MODE_DEEP_SLEEP 2 +#define LPM_MODE_SHUTDOWN 3 #define LPM_MODE_MAX_SUPPORTED LPM_MODE_DEEP_SLEEP /*---------------------------------------------------------------------------*/ +#define LPM_DOMAIN_NONE 0 +#define LPM_DOMAIN_SERIAL PRCM_DOMAIN_SERIAL +#define LPM_DOMAIN_PERIPH PRCM_DOMAIN_PERIPH +/*---------------------------------------------------------------------------*/ typedef struct lpm_registered_module { struct lpm_registered_module *next; uint8_t (*request_max_pm)(void); void (*shutdown)(uint8_t mode); void (*wakeup)(void); + uint32_t domain_lock; } lpm_registered_module_t; /*---------------------------------------------------------------------------*/ /** @@ -78,46 +83,14 @@ typedef struct lpm_registered_module { * woken up. This can be used to e.g. turn a peripheral back on. This * function is in charge of turning power domains back on. This * function will normally be called within an interrupt context. + * \param l Power domain locks, if any are required. The module can request + * that the SERIAL or PERIPH PD be kept powered up at the transition + * to deep sleep. This field can be a bitwise OR of LPM_DOMAIN_x, so + * if required multiple domains can be kept powered. */ -#define LPM_MODULE(n, m, s, w) static lpm_registered_module_t n = \ - { NULL, m, s, w } +#define LPM_MODULE(n, m, s, w, l) static lpm_registered_module_t n = \ + { NULL, m, s, w, l } /*---------------------------------------------------------------------------*/ -/** - * - * \brief Data type used to control whether a PD will get shut down when the - * CM3 drops to deep sleep - * - * Modules using these facilities must allocate a variable of this type, but - * they must not try to manipulate it directly. Instead, the respective - * functions must be used - * - * \sa lpm_pd_lock_obtain(), lpm_pd_lock_release() - */ -typedef struct lpm_power_domain_lock { - struct lpm_power_domain_lock *next; - uint32_t domains; -} lpm_power_domain_lock_t; -/*---------------------------------------------------------------------------*/ -/** - * \brief Prohibit a PD from turning off in standby mode - * \param lock A pointer to a lpm_power_domain_lock_t - * \param domains Bitwise OR from PRCM_DOMAIN_PERIPH, PRCM_DOMAIN_SERIAL - * - * The caller is responsible for allocating lpm_power_domain_lock_t - * - * Only the domains listed above can be locked / released, but a single lock - * can be used for multiple domains - */ -void lpm_pd_lock_obtain(lpm_power_domain_lock_t *lock, uint32_t domains); - -/** - * \brief Permit a PD to turn off in standby mode - * \param pd A pointer to a previously used lock - * - * \sa lpm_pd_lock_obtain() - */ -void lpm_pd_lock_release(lpm_power_domain_lock_t *pd); - /** * \brief Drop the cortex to sleep / deep sleep and shut down peripherals * @@ -134,17 +107,11 @@ void lpm_sleep(void); /** * \brief Put the chip in shutdown power mode * \param wakeup_pin The GPIO pin which will wake us up. Must be IOID_0 etc... + * \param io_pull Pull configuration for the shutdown pin: IOC_NO_IOPULL, + * IOC_IOPULL_UP or IOC_IOPULL_DOWN + * \param wake_on High or Low (IOC_WAKE_ON_LOW or IOC_WAKE_ON_HIGH) */ -void lpm_shutdown(uint32_t wakeup_pin); - -/** - * \brief Wake up from sleep mode - * - * This function must be called at the start of any interrupt context which - * may bring us out of sleep. Current interrupts do this already, but make sure - * to do the same when adding new ISRs - */ -void lpm_wake_up(void); +void lpm_shutdown(uint32_t wakeup_pin, uint32_t io_pull, uint32_t wake_on); /** * \brief Register a module for LPM notifications. @@ -159,10 +126,31 @@ void lpm_wake_up(void); */ void lpm_register_module(lpm_registered_module_t *module); +/** + * \brief Unregister a module from LPM notifications. + * \param module A pointer to the data structure with the module definition + * + * When a previously registered module is no longer interested in LPM + * notifications, this function can be used to unregister it. + */ +void lpm_unregister_module(lpm_registered_module_t *module); + /** * \brief Initialise the low-power mode management module */ void lpm_init(void); + +/** + * \brief Sets an IOID to a default state + * \param ioid IOID_0... + * + * This will set ioid to sw control, input, no pull. Input buffer and output + * driver will both be disabled + * + * The function will do nothing if ioid == IOID_UNUSED, so the caller does not + * have to check board configuration before calling this. + */ +void lpm_pin_set_default_state(uint32_t ioid); /*---------------------------------------------------------------------------*/ #endif /* LPM_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/cpu/cc26xx/putchar.c b/cpu/cc26xx/putchar.c index 0f91deea5..7cbd1901a 100644 --- a/cpu/cc26xx/putchar.c +++ b/cpu/cc26xx/putchar.c @@ -29,6 +29,7 @@ */ /*---------------------------------------------------------------------------*/ #include "cc26xx-uart.h" +#include "ti-lib.h" #include /*---------------------------------------------------------------------------*/ @@ -47,9 +48,16 @@ puts(const char *str) return 0; } for(i = 0; i < strlen(str); i++) { - putchar(str[i]); + cc26xx_uart_write_byte(str[i]); } - putchar('\n'); + cc26xx_uart_write_byte('\n'); + + /* + * Wait for the line to go out. This is to prevent garbage when used between + * UART on/off cycles + */ + while(cc26xx_uart_busy() == UART_BUSY); + return i; } /*---------------------------------------------------------------------------*/ @@ -62,9 +70,16 @@ dbg_send_bytes(const unsigned char *s, unsigned int len) if(i >= len) { break; } - putchar(*s++); + cc26xx_uart_write_byte(*s++); i++; } + + /* + * Wait for the buffer to go out. This is to prevent garbage when used + * between UART on/off cycles + */ + while(cc26xx_uart_busy() == UART_BUSY); + return i; } /*---------------------------------------------------------------------------*/ diff --git a/cpu/cc26xx/slip-arch.c b/cpu/cc26xx/slip-arch.c index 268c84548..ebd6f91c8 100644 --- a/cpu/cc26xx/slip-arch.c +++ b/cpu/cc26xx/slip-arch.c @@ -58,6 +58,10 @@ slip_arch_writeb(unsigned char c) void slip_arch_init(unsigned long ubr) { + /* + * Enable an input handler. In doing so, the driver will make sure that UART + * RX stays operational during deep sleep + */ cc26xx_uart_set_input(slip_input_byte); } /*---------------------------------------------------------------------------*/ diff --git a/cpu/cc26xx/ti-lib.h b/cpu/cc26xx/ti-lib.h index df5e2cf39..ff707cfae 100644 --- a/cpu/cc26xx/ti-lib.h +++ b/cpu/cc26xx/ti-lib.h @@ -57,12 +57,7 @@ #define ti_lib_aon_batmon_enable(...) AONBatMonEnable(__VA_ARGS__) #define ti_lib_aon_batmon_disable(...) AONBatMonDisable(__VA_ARGS__) -#define ti_lib_aon_batmon_measurement_cycle_set(...) AONBatMonMeasurementCycleSet(__VA_ARGS__) -#define ti_lib_aon_batmon_measurement_cycle_get(...) AONBatMonMeasurementCycleGet(__VA_ARGS__) -#define ti_lib_aon_batmon_battery_trim_set(...) AONBatMonBatteryTrimSet(__VA_ARGS__) -#define ti_lib_aon_batmon_temperature_trim_set(...) AONBatMonTemperatureTrimSet(__VA_ARGS__) -#define ti_lib_aon_batmon_temperature_get(...) AONBatMonTemperatureGet(__VA_ARGS__) -#define ti_lib_aon_batmon_temp_get_deg(...) AON_BatmonTempGetDegC(__VA_ARGS__) +#define ti_lib_aon_batmon_temperature_get_deg_c(...) AONBatMonTemperatureGetDegC(__VA_ARGS__) #define ti_lib_aon_batmon_battery_voltage_get(...) AONBatMonBatteryVoltageGet(__VA_ARGS__) #define ti_lib_aon_batmon_new_battery_measure_ready(...) AONBatMonNewBatteryMeasureReady(__VA_ARGS__) #define ti_lib_aon_batmon_new_temp_measure_ready(...) AONBatMonNewTempMeasureReady(__VA_ARGS__) @@ -123,21 +118,19 @@ #define ti_lib_aon_wuc_mcu_power_down_config(...) AONWUCMcuPowerDownConfig(__VA_ARGS__) #define ti_lib_aon_wuc_mcu_power_off_config(...) AONWUCMcuPowerOffConfig(__VA_ARGS__) #define ti_lib_aon_wuc_mcu_sram_config(...) AONWUCMcuSRamConfig(__VA_ARGS__) -#define ti_lib_aon_wuc_aux_clock_config_set(...) AONWUCAuxClockConfigSet(__VA_ARGS__) #define ti_lib_aon_wuc_aux_clock_config_get(...) AONWUCAuxClockConfigGet(__VA_ARGS__) #define ti_lib_aon_wuc_aux_power_down_config(...) AONWUCAuxPowerDownConfig(__VA_ARGS__) -#define ti_lib_aon_wuc_aux_power_off_config(...) AONWUCAuxPowerOffConfig(__VA_ARGS__) #define ti_lib_aon_wuc_aux_wake_up_config(...) AONWUCAuxWakeUpConfig(__VA_ARGS__) #define ti_lib_aon_wuc_aux_sram_config(...) AONWUCAuxSRamConfig(__VA_ARGS__) #define ti_lib_aon_wuc_aux_wakeup_event(...) AONWUCAuxWakeupEvent(__VA_ARGS__) #define ti_lib_aon_wuc_aux_image_valid(...) AONWUCAuxImageValid(__VA_ARGS__) #define ti_lib_aon_wuc_aux_image_invalid(...) AONWUCAuxImageInvalid(__VA_ARGS__) #define ti_lib_aon_wuc_aux_reset(...) AONWUCAuxReset(__VA_ARGS__) -#define ti_lib_aon_wuc_power_status(...) AONWUCPowerStatus(__VA_ARGS__) +#define ti_lib_aon_wuc_power_status_get(...) AONWUCPowerStatusGet(__VA_ARGS__) #define ti_lib_aon_wuc_shut_down_enable(...) AONWUCShutDownEnable(__VA_ARGS__) #define ti_lib_aon_wuc_domain_power_down_enable(...) AONWUCDomainPowerDownEnable(__VA_ARGS__) #define ti_lib_aon_wuc_domain_power_down_disable(...) AONWUCDomainPowerDownDisable(__VA_ARGS__) -#define ti_lib_aon_wuc_mcu_reset_status(...) AONWUCMcuResetStatus(__VA_ARGS__) +#define ti_lib_aon_wuc_mcu_reset_status_get(...) AONWUCMcuResetStatusGet(__VA_ARGS__) #define ti_lib_aon_wuc_mcu_reset_clear(...) AONWUCMcuResetClear(__VA_ARGS__) #define ti_lib_aon_wuc_recharge_ctrl_config_set(...) AONWUCRechargeCtrlConfigSet(__VA_ARGS__) #define ti_lib_aon_wuc_recharge_ctrl_config_get(...) AONWUCRechargeCtrlConfigGet(__VA_ARGS__) @@ -148,7 +141,7 @@ #include "driverlib/aux_wuc.h" #define ti_lib_aux_wuc_clock_enable(...) AUXWUCClockEnable(__VA_ARGS__) -#define ti_lib_aux_wuc_clock_disble(...) AUXWUCClockDisable(__VA_ARGS__) +#define ti_lib_aux_wuc_clock_disable(...) AUXWUCClockDisable(__VA_ARGS__) #define ti_lib_aux_wuc_clock_status(...) AUXWUCClockStatus(__VA_ARGS__) #define ti_lib_aux_wuc_clock_freq_req(...) AUXWUCClockFreqReq(__VA_ARGS__) #define ti_lib_aux_wuc_power_ctrl(...) AUXWUCPowerCtrl(__VA_ARGS__) @@ -173,10 +166,6 @@ #define ti_lib_aux_adi_ddi_safe_write(...) AuxAdiDdiSafeWrite(__VA_ARGS__) #define ti_lib_aux_adi_ddi_safe_read(...) AuxAdiDdiSafeRead(__VA_ARGS__) -#define ti_lib_ddi_status_get(...) DDIStatusGet(__VA_ARGS__) -#define ti_lib_ddi_config_set(...) DDIConfigSet(__VA_ARGS__) -#define ti_lib_ddi_sync(...) DDISync(__VA_ARGS__) -#define ti_lib_ddi_protect(...) DDIProtect(__VA_ARGS__) #define ti_lib_ddi_32_reg_write(...) DDI32RegWrite(__VA_ARGS__) #define ti_lib_ddi_32_reg_read(...) DDI32RegRead(__VA_ARGS__) #define ti_lib_ddi_32_bits_set(...) DDI32BitsSet(__VA_ARGS__) @@ -256,7 +245,6 @@ #define ti_lib_ioc_port_configure_set(...) IOCPortConfigureSet(__VA_ARGS__) #define ti_lib_ioc_port_configure_get(...) IOCPortConfigureGet(__VA_ARGS__) #define ti_lib_ioc_io_shutdown_set(...) IOCIOShutdownSet(__VA_ARGS__) -#define ti_lib_ioc_io_jtag_set(...) IOCIOJTagSet(__VA_ARGS__) #define ti_lib_ioc_io_mode_set(...) IOCIOModeSet(__VA_ARGS__) #define ti_lib_ioc_io_port_pull_set(...) IOCIOPortPullSet(__VA_ARGS__) #define ti_lib_ioc_io_hyst_set(...) IOCIOHystSet(__VA_ARGS__) @@ -303,8 +291,6 @@ #define ti_lib_prcm_mcu_power_off(...) PRCMMcuPowerOff(__VA_ARGS__) #define ti_lib_prcm_mcu_power_off_cancel(...) PRCMMcuPowerOffCancel(__VA_ARGS__) #define ti_lib_prcm_mcu_uldo_configure(...) PRCMMcuUldoConfigure(__VA_ARGS__) -#define ti_lib_prcm_clock_configure_set(...) PRCMClockConfigureSet(__VA_ARGS__) -#define ti_lib_prcm_clock_configure_get(...) PRCMClockConfigureGet(__VA_ARGS__) #define ti_lib_prcm_audio_clock_enable(...) PRCMAudioClockEnable(__VA_ARGS__) #define ti_lib_prcm_audio_clock_disable(...) PRCMAudioClockDisable(__VA_ARGS__) #define ti_lib_prcm_audio_clock_config_set(...) PRCMAudioClockConfigSet(__VA_ARGS__) @@ -326,8 +312,8 @@ #define ti_lib_prcm_wdt_reset_status(...) PRCMWdtResetStatus(__VA_ARGS__) #define ti_lib_prcm_sleep(...) PRCMSleep(__VA_ARGS__) #define ti_lib_prcm_deep_sleep(...) PRCMDeepSleep(__VA_ARGS__) -#define ti_lib_prcm_retention_enable(...) PRCMRetentionEnable(__VA_ARGS__) -#define ti_lib_prcm_retention_disable(...) PRCMRetentionDisable(__VA_ARGS__) +#define ti_lib_prcm_cache_retention_enable(...) PRCMCacheRetentionEnable(__VA_ARGS__) +#define ti_lib_prcm_cache_retention_disable(...) PRCMCacheRetentionDisable(__VA_ARGS__) /*---------------------------------------------------------------------------*/ /* sys_ctrl.h */ #include "driverlib/pwr_ctrl.h" @@ -335,7 +321,6 @@ #define ti_lib_pwr_ctrl_state_set(...) PowerCtrlStateSet(__VA_ARGS__) #define ti_lib_pwr_ctrl_source_set(...) PowerCtrlSourceSet(__VA_ARGS__) #define ti_lib_pwr_ctrl_source_get(...) PowerCtrlSourceGet(__VA_ARGS__) -#define ti_lib_pwr_ctrl_io_config_set(...) PowerCtrlIoConfigSet(__VA_ARGS__) #define ti_lib_pwr_ctrl_reset_source_get(...) PowerCtrlResetSourceGet(__VA_ARGS__) #define ti_lib_pwr_ctrl_reset_source_clear(...) PowerCtrlResetSourceClear(__VA_ARGS__) #define ti_lib_pwr_ctrl_io_freeze_enable(...) PowerCtrlIOFreezeEnable(__VA_ARGS__) @@ -371,7 +356,6 @@ #define ti_lib_rom_aon_rtc_current_compare_value_get ROM_AONRTCCurrentCompareValueGet /* AON_WUC API */ -#define ti_lib_rom_aon_wuc_aux_clock_config_set ROM_AONWUCAuxClockConfigSet #define ti_lib_rom_aon_wuc_aux_s_ram_config ROM_AONWUCAuxSRamConfig #define ti_lib_rom_aon_wuc_aux_wakeup_event ROM_AONWUCAuxWakeupEvent #define ti_lib_rom_aon_wuc_aux_reset ROM_AONWUCAuxReset @@ -449,8 +433,6 @@ /* PRCM API */ #define ti_lib_rom_prcm_inf_clock_configure_set ROM_PRCMInfClockConfigureSet #define ti_lib_rom_prcm_inf_clock_configure_get ROM_PRCMInfClockConfigureGet -#define ti_lib_rom_prcm_clock_configure_set ROM_PRCMClockConfigureSet -#define ti_lib_rom_prcm_clock_configure_get ROM_PRCMClockConfigureGet #define ti_lib_rom_prcm_audio_clock_config_set ROM_PRCMAudioClockConfigSet #define ti_lib_rom_prcm_power_domain_on ROM_PRCMPowerDomainOn #define ti_lib_rom_prcm_power_domain_off ROM_PRCMPowerDomainOff @@ -462,8 +444,6 @@ #define ti_lib_rom_prcm_peripheral_deep_sleep_disable ROM_PRCMPeripheralDeepSleepDisable #define ti_lib_rom_prcm_power_domain_status ROM_PRCMPowerDomainStatus #define ti_lib_rom_prcm_deep_sleep ROM_PRCMDeepSleep -#define ti_lib_rom_prcm_retention_enable ROM_PRCMRetentionEnable -#define ti_lib_rom_prcm_retention_disable ROM_PRCMRetentionDisable /* SMPH API */ #define ti_lib_rom_smph_acquire ROM_SMPHAcquire @@ -517,6 +497,29 @@ #define ti_lib_rom_vims_configure ROM_VIMSConfigure #define ti_lib_rom_vims_mode_set ROM_VIMSModeSet #define ti_lib_rom_vims_mode_get ROM_VIMSModeGet + +/* HAPI */ +#define ti_lib_hapi_crc32(a, b, c) HapiCrc32(a, b, c) +#define ti_lib_hapi_get_chip_id() HapiGetChipId() +#define ti_lib_hapi_reset_device() HapiResetDevice() +#define ti_lib_hapi_fletcher32(a, b, c) HapiFletcher32(a, b, c) +#define ti_lib_hapi_min_value(a, b) HapiMinValue(a,b) +#define ti_lib_hapi_max_value(a, b) HapiMaxValue(a,b) +#define ti_lib_hapi_mean_value(a, b) HapiMeanValue(a,b) +#define ti_lib_hapi_stand_deviation_value(a, b) HapiStandDeviationValue(a,b) +#define ti_lib_hapi_reset_peripheral(a) HapiResetPeripheral(a) +#define ti_lib_hapi_reset_domain(a) HapiResetDomain(a) +#define ti_lib_hapi_hf_source_safe_switch() HapiHFSourceSafeSwitch() +#define ti_lib_hapi_select_comp_a_input(a) HapiSelectCompAInput(a) +#define ti_lib_hapi_select_comp_a_ref(a) HapiSelectCompARef(a) +#define ti_lib_hapi_select_adc_comp_b_input(a) HapiSelectADCCompBInput(a) +#define ti_lib_hapi_select_comp_b_ref(a) HapiSelectCompBRef(a) +#define ti_lib_hapi_get_flash_size() HapiGetFlashSize() +#define ti_lib_hapi_sector_erase(a) HapiSectorErase(a) +#define ti_lib_hapi_program_flash(a, b, c) HapiProgramFlash(a, b, c) +#define ti_lib_hapi_get_flash_size() HapiGetFlashSize() +#define ti_lib_hapi_sector_erase(a) HapiSectorErase(a) +#define ti_lib_hapi_program_flash(a, b, c) HapiProgramFlash(a, b, c) /*---------------------------------------------------------------------------*/ /* sys_ctrl.h */ #include "driverlib/sys_ctrl.h" @@ -526,11 +529,13 @@ #define ti_lib_sys_ctrl_standby(...) SysCtrlStandby(__VA_ARGS__) #define ti_lib_sys_ctrl_shutdown(...) SysCtrlShutdown(__VA_ARGS__) #define ti_lib_sys_ctrl_clock_get(...) SysCtrlClockGet(__VA_ARGS__) -#define ti_lib_sys_ctrl_peripheral_clock_get(...) SysCtrlPeripheralClockGet(__VA_ARGS__) #define ti_lib_sys_ctrl_aon_sync(...) SysCtrlAonSync(__VA_ARGS__) #define ti_lib_sys_ctrl_aon_update(...) SysCtrlAonUpdate(__VA_ARGS__) #define ti_lib_sys_ctrl_set_recharge_before_power_down(...) SysCtrlSetRechargeBeforePowerDown(__VA_ARGS__) #define ti_lib_sys_ctrl_adjust_recharge_after_power_down(...) SysCtrlAdjustRechargeAfterPowerDown(__VA_ARGS__) +#define ti_lib_sys_ctrl_dcdc_voltage_conditional_control(...) SysCtrl_DCDC_VoltageConditionalControl(__VA_ARGS__) +#define ti_lib_sys_ctrl_reset_source_get(...) SysCtrlResetSourceGet(__VA_ARGS__) +#define ti_lib_sys_ctrl_system_reset(...) SysCtrlSystemReset(__VA_ARGS__) /*---------------------------------------------------------------------------*/ /* ssi.h */ #include "driverlib/ssi.h" @@ -595,6 +600,10 @@ #define ti_lib_timer_int_status(...) TimerIntStatus(__VA_ARGS__) #define ti_lib_timer_int_clear(...) TimerIntClear(__VA_ARGS__) #define ti_lib_timer_synchronize(...) TimerSynchronize(__VA_ARGS__) +#define ti_lib_timer_ccp_combine_enable(...) TimerCcpCombineEnable(__VA_ARGS__) +#define ti_lib_timer_ccp_combine_disable(...) TimerCcpCombineDisable(__VA_ARGS__) +#define ti_lib_timer_match_update_mode(...) TimerMatchUpdateMode(__VA_ARGS__) +#define ti_lib_timer_interval_load_mode(...) TimerIntervalLoadMode(__VA_ARGS__) /*---------------------------------------------------------------------------*/ /* uart.h */ #include "driverlib/uart.h" @@ -627,8 +636,8 @@ #define ti_lib_uart_dma_disable(...) UARTDMADisable(__VA_ARGS__) #define ti_lib_uart_rx_error_get(...) UARTRxErrorGet(__VA_ARGS__) #define ti_lib_uart_rx_error_clear(...) UARTRxErrorClear(__VA_ARGS__) -#define ti_lib_uart_tx_int_mode_set(...) UARTTxIntModeSet(__VA_ARGS__) -#define ti_lib_uart_tx_int_mode_get(...) UARTTxIntModeGet(__VA_ARGS__) +#define ti_lib_uart_hw_flow_control_en(...) UARTHwFlowControlEnable(__VA_ARGS__) +#define ti_lib_uart_hw_flow_control_dis(...) UARTHwFlowControlDisable(__VA_ARGS__) /*---------------------------------------------------------------------------*/ /* vims.h */ #include "driverlib/vims.h" @@ -640,24 +649,24 @@ /* watchdog.h */ #include "driverlib/watchdog.h" -#define ti_lib_wathdog_running(...) WatchdogRunning(__VA_ARGS__) -#define ti_lib_wathdog_enable(...) WatchdogEnable(__VA_ARGS__) -#define ti_lib_wathdog_reset_enable(...) WatchdogResetEnable(__VA_ARGS__) -#define ti_lib_wathdog_reset_disable(...) WatchdogResetDisable(__VA_ARGS__) -#define ti_lib_wathdog_lock(...) WatchdogLock(__VA_ARGS__) -#define ti_lib_wathdog_unlock(...) WatchdogUnlock(__VA_ARGS__) -#define ti_lib_wathdog_lock_state(...) WatchdogLockState(__VA_ARGS__) -#define ti_lib_wathdog_reload_set(...) WatchdogReloadSet(__VA_ARGS__) -#define ti_lib_wathdog_reload_get(...) WatchdogReloadGet(__VA_ARGS__) -#define ti_lib_wathdog_value_get(...) WatchdogValueGet(__VA_ARGS__) -#define ti_lib_wathdog_int_register(...) WatchdogIntRegister(__VA_ARGS__) -#define ti_lib_wathdog_int_unregister(...) WatchdogIntUnregister(__VA_ARGS__) -#define ti_lib_wathdog_int_enable(...) WatchdogIntEnable(__VA_ARGS__) -#define ti_lib_wathdog_int_status(...) WatchdogIntStatus(__VA_ARGS__) -#define ti_lib_wathdog_int_clear(...) WatchdogIntClear(__VA_ARGS__) -#define ti_lib_wathdog_int_type_set(...) WatchdogIntTypeSet(__VA_ARGS__) -#define ti_lib_wathdog_stall_enable(...) WatchdogStallEnable(__VA_ARGS__) -#define ti_lib_wathdog_stall_disable(...) WatchdogStallDisable(__VA_ARGS__) +#define ti_lib_watchdog_running(...) WatchdogRunning(__VA_ARGS__) +#define ti_lib_watchdog_enable(...) WatchdogEnable(__VA_ARGS__) +#define ti_lib_watchdog_reset_enable(...) WatchdogResetEnable(__VA_ARGS__) +#define ti_lib_watchdog_reset_disable(...) WatchdogResetDisable(__VA_ARGS__) +#define ti_lib_watchdog_lock(...) WatchdogLock(__VA_ARGS__) +#define ti_lib_watchdog_unlock(...) WatchdogUnlock(__VA_ARGS__) +#define ti_lib_watchdog_lock_state(...) WatchdogLockState(__VA_ARGS__) +#define ti_lib_watchdog_reload_set(...) WatchdogReloadSet(__VA_ARGS__) +#define ti_lib_watchdog_reload_get(...) WatchdogReloadGet(__VA_ARGS__) +#define ti_lib_watchdog_value_get(...) WatchdogValueGet(__VA_ARGS__) +#define ti_lib_watchdog_int_register(...) WatchdogIntRegister(__VA_ARGS__) +#define ti_lib_watchdog_int_unregister(...) WatchdogIntUnregister(__VA_ARGS__) +#define ti_lib_watchdog_int_enable(...) WatchdogIntEnable(__VA_ARGS__) +#define ti_lib_watchdog_int_status(...) WatchdogIntStatus(__VA_ARGS__) +#define ti_lib_watchdog_int_clear(...) WatchdogIntClear(__VA_ARGS__) +#define ti_lib_watchdog_int_type_set(...) WatchdogIntTypeSet(__VA_ARGS__) +#define ti_lib_watchdog_stall_enable(...) WatchdogStallEnable(__VA_ARGS__) +#define ti_lib_watchdog_stall_disable(...) WatchdogStallDisable(__VA_ARGS__) /*---------------------------------------------------------------------------*/ #endif /* TI_LIB_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/cpu/mc1322x/doc/rest-tutorial.md b/cpu/mc1322x/doc/rest-tutorial.md deleted file mode 100644 index c3c3e05f9..000000000 --- a/cpu/mc1322x/doc/rest-tutorial.md +++ /dev/null @@ -1,172 +0,0 @@ -Contiki REST/CoAP Quickstart using Econotags -====================================== - -Contiki has an implementation of the IETF CORE (Constrained RESTful -Environments) working group's CoAP layer (Constrained Application -Protocol). CoAP is a RESTful application layer that uses HTTP-like -methods (GET, POST, PUT, DELETE) to interact with constrained -networks. CoAP operates over UDP and supports reliable transmission. - -This tutorial will show you how to run Contiki's CoAP demo on Redwire -Econotags using an RPL border-router. - -1) Run a RPL border-router and tunnel ---------------------------------------------------------------- - -See [the RPL -HOWTO](http://mc1322x.devl.org/repos/contiki-mc1322x/cpu/mc1322x/doc/rpl-tutorial.md) -for details about running a RPL border-router. - -2) Build and run the `rest-server-example` on a second Econotag ----------------------------------------- - -__The following must be done on the contiki-mc1322x.git tree__ - - git clone git://git.devl.org/git/malvira/contiki-mc1322x.git - -__Contiki CVS is currently down and the new SCM system hasn't been set -up yet. The necessary changes will be pushed as soon as the new SCM is -available. - 6 Februrary 2011__ - -To build the rest-server-example: - - cd contiki-mc1322x/examples/rest-example - make TARGET=redbee-econotag - -This will produce the binary image -`rest-server-example_redbee-econotag.bin`, which you can load directly -on to an mc1322x and execute. - - mc1322x-load.pl -f rest-server-example_redbee-econotag.bin -t /dev/ttyUSB3 - -Then press the reset button to connect to the bootloader. - -In this example, we are loading the CoAP server on to the econotag on `/dev/ttyUSB3` - -You should see boot up messages similar to this: - - CONNECT - Size: 62096 bytes - Sending rest-server-example_redbee-econotag.bin - done sending files. - performing ring osc cal - crm_status: 0xc0000 - sys_cntl: 0x18 - ring osc cal complete - cal_count: 0x17e17e0 - cal factor: 100 - hib_wake_secs: 2000 - loading rime address from flash. - Rime started with address 00:50:C2:AB:C0:00:00:23 - nullmac nullrdc, channel check rate 100 Hz, radio channel 26 - Tentative link-local IPv6 address - fe80:0000:0000:0000:0250:c2ab:c000:0023 - Tentative global IPv6 address aaaa:0000:0000:0000:0250:c2ab:c000:0023 - Starting 'Rest Server Example' - COAP Server - -The last line indicates that the server will be using -COAP. As an alternative, you can build the server to use HTTP instead with: - - make TARGET=redbee-econotag WITH_COAP=0 - -3) Download and install the `Copper` Firefox Plugin ------------------------------------------------------ - -The `Copper` Plugin for Firefox provides the `coap:` URL access method -as well as an interface to easily send `coap` requests. - -Download and install the plugin from here: - -+ [Copper plugin homepage](http://people.inf.ethz.ch/~mkovatsc/) -+ Install link:[copper-0.3.0pre2.xpi](http://people.inf.ethz.ch/~mkovatsc/resources/copper/copper-0.3.0pre2.xpi) - -4) Open Copper --------------- - -Open a new Firefox tab and click on the orange CU button in the lower -right. - -[![Open CU](http://mc1322x.devl.org/files/coap-blanktab-t.png)](http://mc1322x.devl.org/files/coap-blanktab.png) - -The initial CU screen will look like this: - -[![CU startup](http://mc1322x.devl.org/files/coap-opencu-t.png)](http://mc1322x.devl.org/files/coap-opencu.png) - -Type in the the URL of the coap node with the default port number of -"61616": - -[![CU startup](http://mc1322x.devl.org/files/coap-url-t.png)](http://mc1322x.devl.org/files/coap-url.png) - -+ Don't forget the brackets ( [ ] ) in the URL - -+ Make sure to use the IPv6 address of your coap server. You can get - this from the boot up messages or from the webpage served by your - border-router. - -+ You must always press Enter after changing the URL. - -5) GET `.well-known/core` resources ------------------------------------- - -Now click on the red "./well-known/core" button: this changes the URL -to the `.well-known/core` resource. - -Then click GET to perform a get. You should see an acknowledgement -that the GET was successful (returns 200 OK). The payload should -return: - - ;n="HelloWorld",;n="LedControl",;n="Light - -Which is are the well-known resources that this node advertises; see -the [COAP -specification](https://datatracker.ietf.org/doc/draft-ietf-core-coap/) -for details. - -[![Open CU](http://mc1322x.devl.org/files/coap-wellknown-t.png)](http://mc1322x.devl.org/files/coap-wellknown.png) - -6) PUT,POST the `led` resource state ------------------------------------- - -You can PUT or POST to change the state of the LED. - -Type in the following URL and press enter: - - coap://[aaaa::250:c2ff:fea8:c48e]:61616/led?color=green - -Be sure to use the proper IP address. For this URL: we will perform -actions on the `led` resource with a query string of `color=green`. - -In the payload, type: - - mode=on - -That is the payload that will be PUT or POSTed. The COAP server -detects the mode string and activates the LED accordingly (with the -color chosen by the query string). - -Then click PUT or POST to perform the request. - -[![CU startup](http://mc1322x.devl.org/files/coap-led-t.png)](http://mc1322x.devl.org/files/coap-led.png) - -You should get a successful return code (200 OK) and the green LED -should turn on. If you PUT/POST `mode=off` the led will turn off. - -The econotag only has two LEDs: a green and a red. The red LED is used -to indicate radio transmission by default and so cannot be used in -this demo. The Coniki blue LED is connected to GPIO 43. You can toggle -it, but you won't see anything unless you hook something up to this -pin. - -7) Other resources ------------------- - -The `rest-server-example` also provides `helloworld` and `light` as -GETtable resources. - - coap://[aaaa::250:c2ff:fea8:c48e]:61616/helloworld - coap://[aaaa::250:c2ff:fea8:c48e]:61616/light - -The econotag does not have a light sensor. The light resource will -always return 0. At a latter date, this sensor will be connected to -one of the ADC pins. diff --git a/cpu/msp430/Makefile.msp430 b/cpu/msp430/Makefile.msp430 index 264538611..2090c2465 100644 --- a/cpu/msp430/Makefile.msp430 +++ b/cpu/msp430/Makefile.msp430 @@ -4,6 +4,8 @@ ifdef nodeid CFLAGS += -DNODEID=$(nodeid) endif +CFLAGS += -gstabs+ + .SUFFIXES: ### Define the CPU directory diff --git a/cpu/rl78/adf7023/ADF7023.c b/cpu/rl78/adf7023/ADF7023.c index c8f30be38..a82c1638d 100644 --- a/cpu/rl78/adf7023/ADF7023.c +++ b/cpu/rl78/adf7023/ADF7023.c @@ -45,6 +45,7 @@ #include "sfrs-ext.h" #include "contiki.h" /* for clock_wait() and CLOCK_SECOND. */ +#include "sys/cc.h" /******************************************************************************/ /*************************** Macros Definitions *******************************/ @@ -91,9 +92,6 @@ while(condition) { body; break_loop(); } \ } while(0) -#undef MIN -#define MIN(x, y) (((x) < (y)) ? (x) : (y)) - /******************************************************************************/ /************************ Variables Definitions *******************************/ /******************************************************************************/ diff --git a/dev/cc2420/cc2420.c b/dev/cc2420/cc2420.c index 970f9dca7..d455e02df 100644 --- a/dev/cc2420/cc2420.c +++ b/dev/cc2420/cc2420.c @@ -658,11 +658,13 @@ cc2420_transmit(unsigned short payload_len) { rtimer_clock_t sfd_timestamp; sfd_timestamp = cc2420_sfd_start_time; +#if PACKETBUF_WITH_PACKET_TYPE if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) { /* Write timestamp to last two bytes of packet in TXFIFO. */ write_ram((uint8_t *) &sfd_timestamp, CC2420RAM_TXFIFO + payload_len - 1, 2, WRITE_RAM_IN_ORDER); } +#endif } if(!(get_status() & BV(CC2420_TX_ACTIVE))) { diff --git a/dev/cc2520/cc2520.c b/dev/cc2520/cc2520.c index 249bc6ad6..b6c0e43fa 100644 --- a/dev/cc2520/cc2520.c +++ b/dev/cc2520/cc2520.c @@ -438,11 +438,13 @@ cc2520_transmit(unsigned short payload_len) { rtimer_clock_t sfd_timestamp; sfd_timestamp = cc2520_sfd_start_time; +#if PACKETBUF_WITH_PACKET_TYPE if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) { /* Write timestamp to last two bytes of packet in TXFIFO. */ CC2520_WRITE_RAM(&sfd_timestamp, CC2520RAM_TXFIFO + payload_len - 1, 2); } +#endif } if(!(status() & BV(CC2520_TX_ACTIVE))) { diff --git a/doc/Doxyfile b/doc/Doxyfile index 7379f5c06..a9c714d73 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -807,7 +807,7 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = */cpu/cc26xx/lib/* # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the diff --git a/doc/examples.txt b/doc/examples.txt index 5b2789278..10c175034 100644 --- a/doc/examples.txt +++ b/doc/examples.txt @@ -11,7 +11,6 @@ /** \example example-mesh.c */ /** \example example-multihop.c */ /** \example example-rucb.c */ -/** \example example-rudolph0.c */ /** \example example-rudolph1.c */ /** \example example-rudolph2.c */ /** \example example-runicast.c */ diff --git a/examples/cc2538dk/cc2538-demo.c b/examples/cc2538dk/cc2538-demo.c index 9210968c2..e50dd3937 100644 --- a/examples/cc2538dk/cc2538-demo.c +++ b/examples/cc2538dk/cc2538-demo.c @@ -69,8 +69,9 @@ #include "sys/rtimer.h" #include "dev/leds.h" #include "dev/uart.h" +#include "dev/cc2538-sensors.h" #include "dev/button-sensor.h" -#include "dev/adc-sensor.h" +#include "dev/als-sensor.h" #include "dev/watchdog.h" #include "dev/serial-line.h" #include "dev/sys-ctrl.h" @@ -114,8 +115,6 @@ rt_callback(struct rtimer *t, void *ptr) /*---------------------------------------------------------------------------*/ PROCESS_THREAD(cc2538_demo_process, ev, data) { - int16_t value; - PROCESS_EXITHANDLER(broadcast_close(&bc)) PROCESS_BEGIN(); @@ -134,15 +133,13 @@ PROCESS_THREAD(cc2538_demo_process, ev, data) printf("-----------------------------------------\n" "Counter = 0x%08x\n", counter); - value = adc_sensor.value(ADC_SENSOR_VDD_3); - printf("VDD = %d mV\n", value * (3 * 1190) / (2047 << 4)); + printf("VDD = %d mV\n", + vdd3_sensor.value(CC2538_SENSORS_VALUE_TYPE_CONVERTED)); - value = adc_sensor.value(ADC_SENSOR_TEMP); printf("Temperature = %d mC\n", - 25000 + ((value >> 4) - 1422) * 10000 / 42); + cc2538_temp_sensor.value(CC2538_SENSORS_VALUE_TYPE_CONVERTED)); - value = adc_sensor.value(ADC_SENSOR_ALS); - printf("Ambient light sensor = %d raw\n", value); + printf("Ambient light sensor = %d raw\n", als_sensor.value(0)); etimer_set(&et, CLOCK_SECOND); rtimer_set(&rt, RTIMER_NOW() + LEDS_OFF_HYSTERISIS, 1, diff --git a/examples/cc2538dk/crypto/Makefile b/examples/cc2538dk/crypto/Makefile new file mode 100644 index 000000000..513e37676 --- /dev/null +++ b/examples/cc2538dk/crypto/Makefile @@ -0,0 +1,6 @@ +CONTIKI_PROJECT = ccm-test sha256-test + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../.. +include $(CONTIKI)/Makefile.include diff --git a/examples/cc2538dk/crypto/Makefile.target b/examples/cc2538dk/crypto/Makefile.target new file mode 100644 index 000000000..777593c88 --- /dev/null +++ b/examples/cc2538dk/crypto/Makefile.target @@ -0,0 +1 @@ +TARGET = cc2538dk diff --git a/examples/cc2538dk/crypto/ccm-test.c b/examples/cc2538dk/crypto/ccm-test.c new file mode 100644 index 000000000..64c4fcf18 --- /dev/null +++ b/examples/cc2538dk/crypto/ccm-test.c @@ -0,0 +1,733 @@ +/* + * Original file: + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.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-examples + * @{ + * + * \defgroup cc2538-ccm-test cc2538dk AES-CCM Test Project + * + * AES-CCM access example for CC2538 on SmartRF06EB. + * + * This example shows how AES-CCM should be used. The example also verifies + * the AES-CCM functionality. + * + * @{ + * + * \file + * Example demonstrating AES-CCM on the cc2538dk platform + */ +#include "contiki.h" +#include "sys/rtimer.h" +#include "dev/rom-util.h" +#include "dev/ccm.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +PROCESS(ccm_test_process, "ccm test process"); +AUTOSTART_PROCESSES(&ccm_test_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(ccm_test_process, ev, data) +{ + static const char *const str_res[] = { + "success", + "invalid param", + "NULL error", + "resource in use", + "DMA bus error", + "keystore read error", + "keystore write error", + "authentication failed" + }; + static const uint8_t keys128[][16] = { + { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, + 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf } + }; + static const uint8_t keys192[][24] = { + { 0x26, 0x51, 0x1f, 0xb5, 0x1f, 0xcf, 0xa7, 0x5c, + 0xb4, 0xb4, 0x4d, 0xa7, 0x5a, 0x6e, 0x5a, 0x0e, + 0xb8, 0xd9, 0xc8, 0xf3, 0xb9, 0x06, 0xf8, 0x86 }, + { 0x08, 0x6e, 0x29, 0x67, 0xcd, 0xe9, 0x9e, 0x90, + 0xfa, 0xae, 0xa8, 0xa9, 0x4e, 0x16, 0x8b, 0xf0, + 0xe0, 0x66, 0xc5, 0x03, 0xa8, 0x49, 0xa9, 0xf3 }, + { 0xce, 0xb0, 0x09, 0xae, 0xa4, 0x45, 0x44, 0x51, + 0xfe, 0xad, 0xf0, 0xe6, 0xb3, 0x6f, 0x45, 0x55, + 0x5d, 0xd0, 0x47, 0x23, 0xba, 0xa4, 0x48, 0xe8 }, + { 0x11, 0xfd, 0x45, 0x74, 0x3d, 0x94, 0x6e, 0x6d, + 0x37, 0x34, 0x1f, 0xec, 0x49, 0x94, 0x7e, 0x8c, + 0x70, 0x48, 0x24, 0x94, 0xa8, 0xf0, 0x7f, 0xcc } + }; + static const uint8_t keys256[][32] = { + { 0x26, 0x51, 0x1f, 0xb5, 0x1f, 0xcf, 0xa7, 0x5c, + 0xb4, 0xb4, 0x4d, 0xa7, 0x5a, 0x6e, 0x5a, 0x0e, + 0xb8, 0xd9, 0xc8, 0xf3, 0xb9, 0x06, 0xf8, 0x86, + 0xdf, 0x3b, 0xa3, 0xe6, 0xda, 0x3a, 0x13, 0x89 }, + { 0xc6, 0xc1, 0x4c, 0x65, 0x5e, 0x52, 0xc8, 0xa4, + 0xc7, 0xe8, 0xd5, 0x4e, 0x97, 0x4d, 0x69, 0x8e, + 0x1f, 0x21, 0xee, 0x3b, 0xa7, 0x17, 0xa0, 0xad, + 0xfa, 0x61, 0x36, 0xd0, 0x26, 0x68, 0xc4, 0x76 }, + { 0x55, 0x35, 0x21, 0xa7, 0x65, 0xab, 0x0c, 0x3f, + 0xd2, 0x03, 0x65, 0x4e, 0x99, 0x16, 0x33, 0x0e, + 0x18, 0x9b, 0xdf, 0x95, 0x1f, 0xee, 0xe9, 0xb4, + 0x4b, 0x10, 0xda, 0x20, 0x8f, 0xee, 0x7a, 0xcf }, + { 0x90, 0x74, 0xb1, 0xae, 0x4c, 0xa3, 0x34, 0x2f, + 0xe5, 0xbf, 0x6f, 0x14, 0xbc, 0xf2, 0xf2, 0x79, + 0x04, 0xf0, 0xb1, 0x51, 0x79, 0xd9, 0x5a, 0x65, + 0x4f, 0x61, 0xe6, 0x99, 0x69, 0x2e, 0x6f, 0x71 } + }; + static const struct { + const void *keys; + uint8_t key_size; + uint8_t count; + } keys[] = { + { keys128, AES_KEY_STORE_SIZE_KEY_SIZE_128, + sizeof(keys128) / sizeof(keys128[0]) }, + { keys192, AES_KEY_STORE_SIZE_KEY_SIZE_192, + sizeof(keys192) / sizeof(keys192[0]) }, + { keys256, AES_KEY_STORE_SIZE_KEY_SIZE_256, + sizeof(keys256) / sizeof(keys256[0]) } + }; + static struct { + bool encrypt; + uint8_t len_len; + uint8_t key_size_index; + uint8_t key_area; + uint8_t nonce[13]; + uint8_t adata[32]; + uint16_t adata_len; + uint8_t mdata[40]; + uint16_t mdata_len; + uint8_t mic[16]; + uint8_t mic_len; + uint8_t expected[40]; + } vectors[] = { + { + true, /* encrypt */ + 2, /* len_len */ + 0, /* key_size_index */ + 0, /* key_area */ + { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, + 0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */ + {}, /* adata */ + 0, /* adata_len */ + { 0x14, 0xaa, 0xbb, 0x00, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, /* mdata */ + 20, /* mdata_len */ + {}, /* mic */ + 0, /* mic_len */ + { 0x92, 0xe8, 0xad, 0xca, 0x53, 0x81, 0xbf, 0xd0, + 0x5b, 0xdd, 0xf3, 0x61, 0x09, 0x09, 0x82, 0xe6, + 0x2c, 0x61, 0x01, 0x4e } /* expected */ + }, { + true, /* encrypt */ + 2, /* len_len */ + 0, /* key_size_index */ + 1, /* key_area */ + { 0xac, 0xde, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x05, 0x02 }, /* nonce */ + { 0x08, 0xd0, 0x84, 0x21, 0x43, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x48, 0xde, 0xac, 0x02, 0x05, 0x00, + 0x00, 0x00, 0x55, 0xcf, 0x00, 0x00, 0x51, 0x52, + 0x53, 0x54 }, /* adata */ + 26, /* adata_len */ + {}, /* mdata */ + 0, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 8, /* mic_len */ + { 0x22, 0x3b, 0xc1, 0xec, 0x84, 0x1a, 0xb5, 0x53 } /* expected */ + }, { + true, /* encrypt */ + 2, /* len_len */ + 0, /* key_size_index */ + 0, /* key_area */ + { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, + 0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */ + { 0x69, 0x98, 0x03, 0x33, 0x63, 0xbb, 0xaa, 0x01, + 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x03 }, /* adata */ + 15, /* adata_len */ + { 0x14, 0xaa, 0xbb, 0x00, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f }, /* mdata */ + 20, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 4, /* mic_len */ + { 0x92, 0xe8, 0xad, 0xca, 0x53, 0x81, 0xbf, 0xd0, + 0x5b, 0xdd, 0xf3, 0x61, 0x09, 0x09, 0x82, 0xe6, + 0x2c, 0x61, 0x01, 0x4e, 0x7b, 0x34, 0x4f, 0x09 } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + 0, /* key_size_index */ + 0, /* key_area */ + { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, + 0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */ + {}, /* adata */ + 0, /* adata_len */ + { 0x92, 0xe8, 0xad, 0xca, 0x53, 0x81, 0xbf, 0xd0, + 0x5b, 0xdd, 0xf3, 0x61, 0x09, 0x09, 0x82, 0xe6, + 0x2c, 0x61, 0x01, 0x4e }, /* mdata */ + 20, /* mdata_len */ + {}, /* mic */ + 0, /* mic_len */ + { 0x14, 0xaa, 0xbb, 0x00, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + 0, /* key_size_index */ + 1, /* key_area */ + { 0xac, 0xde, 0x48, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x05, 0x02 }, /* nonce */ + { 0x08, 0xd0, 0x84, 0x21, 0x43, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x48, 0xde, 0xac, 0x02, 0x05, 0x00, + 0x00, 0x00, 0x55, 0xcf, 0x00, 0x00, 0x51, 0x52, + 0x53, 0x54 }, /* adata */ + 26, /* adata_len */ + { 0x22, 0x3b, 0xc1, 0xec, 0x84, 0x1a, 0xb5, 0x53 }, /* mdata */ + 8, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 8, /* mic_len */ + {} /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + 0, /* key_size_index */ + 0, /* key_area */ + { 0x00, 0x00, 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, + 0x00, 0x00, 0x00, 0x00, 0x05 }, /* nonce */ + { 0x69, 0x98, 0x03, 0x33, 0x63, 0xbb, 0xaa, 0x01, + 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x03 }, /* adata */ + 15, /* adata_len */ + { 0x92, 0xe8, 0xad, 0xca, 0x53, 0x81, 0xbf, 0xd0, + 0x5b, 0xdd, 0xf3, 0x61, 0x09, 0x09, 0x82, 0xe6, + 0x2c, 0x61, 0x01, 0x4e, 0x7b, 0x34, 0x4f, 0x09 }, /* mdata */ + 24, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 4, /* mic_len */ + { 0x14, 0xaa, 0xbb, 0x00, 0x00, 0x01, 0x02, 0x03, + 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, + 0x0c, 0x0d, 0x0e, 0x0f } /* expected */ + }, { + true, /* encrypt */ + 2, /* len_len */ + 1, /* key_size_index */ + 0, /* key_area */ + { 0x15, 0xb3, 0x69, 0x88, 0x96, 0x99, 0xb6, 0xde, + 0x1f, 0xa3, 0xee, 0x73, 0xe5 }, /* nonce */ + {}, /* adata */ + 0, /* adata_len */ + { 0x39, 0xf0, 0x8a, 0x2a, 0xf1, 0xd8, 0xda, 0x62, + 0x12, 0x55, 0x06, 0x39, 0xb9, 0x1f, 0xb2, 0x57, + 0x3e, 0x39, 0xa8, 0xeb, 0x5d, 0x80, 0x1d, 0xe8 }, /* mdata */ + 24, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x63, 0x42, 0xb8, 0x70, 0x0e, 0xde, 0xc9, 0x7a, + 0x96, 0x0e, 0xb1, 0x6e, 0x7c, 0xb1, 0xeb, 0x44, + 0x12, 0xfb, 0x4e, 0x26, 0x3d, 0xdd, 0x22, 0x06, + 0xb0, 0x90, 0x15, 0x5d, 0x34, 0xa7, 0x6c, 0x83, + 0x24, 0xe5, 0x55, 0x0c, 0x3e, 0xf4, 0x26, 0xed } /* expected */ + }, { + true, /* encrypt */ + 2, /* len_len */ + 1, /* key_size_index */ + 2, /* key_area */ + { 0x92, 0x95, 0x42, 0xcd, 0x69, 0x0f, 0x1b, 0xab, + 0xcf, 0x16, 0x96, 0xcb, 0x03 }, /* nonce */ + { 0x58, 0xf7, 0x0b, 0xab, 0x24, 0xe0, 0xa6, 0x13, + 0x7e, 0x5c, 0xd3, 0xeb, 0x18, 0x65, 0x6f, 0x2b, + 0x5c, 0xcd, 0xdc, 0x3f, 0x53, 0x8a, 0x00, 0x00, + 0xc6, 0x51, 0x90, 0xe4, 0xa3, 0x66, 0x8e, 0x71 }, /* adata */ + 32, /* adata_len */ + {}, /* mdata */ + 0, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x3b, 0xf9, 0xd9, 0x3a, 0xf6, 0xff, 0xac, 0x9a, + 0xc8, 0x4c, 0xd3, 0x20, 0x2d, 0x4e, 0x0c, 0xc8 } /* expected */ + }, { + true, /* encrypt */ + 8, /* len_len */ + 1, /* key_size_index */ + 4, /* key_area */ + { 0x76, 0x40, 0x43, 0xc4, 0x94, 0x60, 0xb7 }, /* nonce */ + { 0x6e, 0x80, 0xdd, 0x7f, 0x1b, 0xad, 0xf3, 0xa1, + 0xc9, 0xab, 0x25, 0xc7, 0x5f, 0x10, 0xbd, 0xe7, + 0x8c, 0x23, 0xfa, 0x0e, 0xb8, 0xf9, 0xaa, 0xa5, + 0x3a, 0xde, 0xfb, 0xf4, 0xcb, 0xf7, 0x8f, 0xe4 }, /* adata */ + 32, /* adata_len */ + { 0xc8, 0xd2, 0x75, 0xf9, 0x19, 0xe1, 0x7d, 0x7f, + 0xe6, 0x9c, 0x2a, 0x1f, 0x58, 0x93, 0x9d, 0xfe, + 0x4d, 0x40, 0x37, 0x91, 0xb5, 0xdf, 0x13, 0x10 }, /* mdata */ + 24, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x8a, 0x0f, 0x3d, 0x82, 0x29, 0xe4, 0x8e, 0x74, + 0x87, 0xfd, 0x95, 0xa2, 0x8a, 0xd3, 0x92, 0xc8, + 0x0b, 0x36, 0x81, 0xd4, 0xfb, 0xc7, 0xbb, 0xfd, + 0x2d, 0xd6, 0xef, 0x1c, 0x45, 0xd4, 0xcc, 0xb7, + 0x23, 0xdc, 0x07, 0x44, 0x14, 0xdb, 0x50, 0x6d } /* expected */ + }, { + true, /* encrypt */ + 2, /* len_len */ + 1, /* key_size_index */ + 6, /* key_area */ + { 0xc6, 0xae, 0xeb, 0xcb, 0x14, 0x6c, 0xfa, 0xfa, + 0xae, 0x66, 0xf7, 0x8a, 0xab }, /* nonce */ + { 0x7d, 0xc8, 0xc5, 0x21, 0x44, 0xa7, 0xcb, 0x65, + 0xb3, 0xe5, 0xa8, 0x46, 0xe8, 0xfd, 0x7e, 0xae, + 0x37, 0xbf, 0x69, 0x96, 0xc2, 0x99, 0xb5, 0x6e, + 0x49, 0x14, 0x4e, 0xbf, 0x43, 0xa1, 0x77, 0x0f }, /* adata */ + 32, /* adata_len */ + { 0xee, 0x7e, 0x60, 0x75, 0xba, 0x52, 0x84, 0x6d, + 0xe5, 0xd6, 0x25, 0x49, 0x59, 0xa1, 0x8a, 0xff, + 0xc4, 0xfa, 0xf5, 0x9c, 0x8e, 0xf6, 0x34, 0x89 }, /* mdata */ + 24, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 4, /* mic_len */ + { 0x13, 0x7d, 0x9d, 0xa5, 0x9b, 0xaf, 0x5c, 0xbf, + 0xd4, 0x66, 0x20, 0xc5, 0xf2, 0x98, 0xfc, 0x76, + 0x6d, 0xe1, 0x0a, 0xc6, 0x8e, 0x77, 0x4e, 0xdf, + 0x1f, 0x2c, 0x5b, 0xad } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + 1, /* key_size_index */ + 0, /* key_area */ + { 0x15, 0xb3, 0x69, 0x88, 0x96, 0x99, 0xb6, 0xde, + 0x1f, 0xa3, 0xee, 0x73, 0xe5 }, /* nonce */ + {}, /* adata */ + 0, /* adata_len */ + { 0x63, 0x42, 0xb8, 0x70, 0x0e, 0xde, 0xc9, 0x7a, + 0x96, 0x0e, 0xb1, 0x6e, 0x7c, 0xb1, 0xeb, 0x44, + 0x12, 0xfb, 0x4e, 0x26, 0x3d, 0xdd, 0x22, 0x06, + 0xb0, 0x90, 0x15, 0x5d, 0x34, 0xa7, 0x6c, 0x83, + 0x24, 0xe5, 0x55, 0x0c, 0x3e, 0xf4, 0x26, 0xed }, /* mdata */ + 40, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x39, 0xf0, 0x8a, 0x2a, 0xf1, 0xd8, 0xda, 0x62, + 0x12, 0x55, 0x06, 0x39, 0xb9, 0x1f, 0xb2, 0x57, + 0x3e, 0x39, 0xa8, 0xeb, 0x5d, 0x80, 0x1d, 0xe8 } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + 1, /* key_size_index */ + 2, /* key_area */ + { 0x92, 0x95, 0x42, 0xcd, 0x69, 0x0f, 0x1b, 0xab, + 0xcf, 0x16, 0x96, 0xcb, 0x03 }, /* nonce */ + { 0x58, 0xf7, 0x0b, 0xab, 0x24, 0xe0, 0xa6, 0x13, + 0x7e, 0x5c, 0xd3, 0xeb, 0x18, 0x65, 0x6f, 0x2b, + 0x5c, 0xcd, 0xdc, 0x3f, 0x53, 0x8a, 0x00, 0x00, + 0xc6, 0x51, 0x90, 0xe4, 0xa3, 0x66, 0x8e, 0x71 }, /* adata */ + 32, /* adata_len */ + { 0x3b, 0xf9, 0xd9, 0x3a, 0xf6, 0xff, 0xac, 0x9a, + 0xc8, 0x4c, 0xd3, 0x20, 0x2d, 0x4e, 0x0c, 0xc8 }, /* mdata */ + 16, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + {} /* expected */ + }, { + false, /* decrypt */ + 8, /* len_len */ + 1, /* key_size_index */ + 4, /* key_area */ + { 0x76, 0x40, 0x43, 0xc4, 0x94, 0x60, 0xb7 }, /* nonce */ + { 0x6e, 0x80, 0xdd, 0x7f, 0x1b, 0xad, 0xf3, 0xa1, + 0xc9, 0xab, 0x25, 0xc7, 0x5f, 0x10, 0xbd, 0xe7, + 0x8c, 0x23, 0xfa, 0x0e, 0xb8, 0xf9, 0xaa, 0xa5, + 0x3a, 0xde, 0xfb, 0xf4, 0xcb, 0xf7, 0x8f, 0xe4 }, /* adata */ + 32, /* adata_len */ + { 0x8a, 0x0f, 0x3d, 0x82, 0x29, 0xe4, 0x8e, 0x74, + 0x87, 0xfd, 0x95, 0xa2, 0x8a, 0xd3, 0x92, 0xc8, + 0x0b, 0x36, 0x81, 0xd4, 0xfb, 0xc7, 0xbb, 0xfd, + 0x2d, 0xd6, 0xef, 0x1c, 0x45, 0xd4, 0xcc, 0xb7, + 0x23, 0xdc, 0x07, 0x44, 0x14, 0xdb, 0x50, 0x6d }, /* mdata */ + 40, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0xc8, 0xd2, 0x75, 0xf9, 0x19, 0xe1, 0x7d, 0x7f, + 0xe6, 0x9c, 0x2a, 0x1f, 0x58, 0x93, 0x9d, 0xfe, + 0x4d, 0x40, 0x37, 0x91, 0xb5, 0xdf, 0x13, 0x10 } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + 1, /* key_size_index */ + 6, /* key_area */ + { 0xc6, 0xae, 0xeb, 0xcb, 0x14, 0x6c, 0xfa, 0xfa, + 0xae, 0x66, 0xf7, 0x8a, 0xab }, /* nonce */ + { 0x7d, 0xc8, 0xc5, 0x21, 0x44, 0xa7, 0xcb, 0x65, + 0xb3, 0xe5, 0xa8, 0x46, 0xe8, 0xfd, 0x7e, 0xae, + 0x37, 0xbf, 0x69, 0x96, 0xc2, 0x99, 0xb5, 0x6e, + 0x49, 0x14, 0x4e, 0xbf, 0x43, 0xa1, 0x77, 0x0f }, /* adata */ + 32, /* adata_len */ + { 0x13, 0x7d, 0x9d, 0xa5, 0x9b, 0xaf, 0x5c, 0xbf, + 0xd4, 0x66, 0x20, 0xc5, 0xf2, 0x98, 0xfc, 0x76, + 0x6d, 0xe1, 0x0a, 0xc6, 0x8e, 0x77, 0x4e, 0xdf, + 0x1f, 0x2c, 0x5b, 0xad }, /* mdata */ + 28, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 4, /* mic_len */ + { 0xee, 0x7e, 0x60, 0x75, 0xba, 0x52, 0x84, 0x6d, + 0xe5, 0xd6, 0x25, 0x49, 0x59, 0xa1, 0x8a, 0xff, + 0xc4, 0xfa, 0xf5, 0x9c, 0x8e, 0xf6, 0x34, 0x89 } /* expected */ + }, { + true, /* encrypt */ + 2, /* len_len */ + 2, /* key_size_index */ + 0, /* key_area */ + { 0x72, 0xa6, 0x0f, 0x34, 0x5a, 0x19, 0x78, 0xfb, + 0x40, 0xf2, 0x8a, 0x2f, 0xa4 }, /* nonce */ + {}, /* adata */ + 0, /* adata_len */ + { 0x30, 0xd5, 0x6f, 0xf2, 0xa2, 0x5b, 0x83, 0xfe, + 0xe7, 0x91, 0x11, 0x0f, 0xca, 0xea, 0x48, 0xe4, + 0x1d, 0xb7, 0xc7, 0xf0, 0x98, 0xa8, 0x10, 0x00 }, /* mdata */ + 24, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x55, 0xf0, 0x68, 0xc0, 0xbb, 0xba, 0x8b, 0x59, + 0x80, 0x13, 0xdd, 0x18, 0x41, 0xfd, 0x74, 0x0f, + 0xda, 0x29, 0x02, 0x32, 0x21, 0x48, 0xab, 0x5e, + 0x93, 0x57, 0x53, 0xe6, 0x01, 0xb7, 0x9d, 0xb4, + 0xae, 0x73, 0x0b, 0x6a, 0xe3, 0x50, 0x07, 0x31 } /* expected */ + }, { + true, /* encrypt */ + 2, /* len_len */ + 2, /* key_size_index */ + 2, /* key_area */ + { 0x29, 0x1e, 0x91, 0xb1, 0x9d, 0xe5, 0x18, 0xcd, + 0x78, 0x06, 0xde, 0x44, 0xf6 }, /* nonce */ + { 0xb4, 0xf8, 0x32, 0x69, 0x44, 0xa4, 0x5d, 0x95, + 0xf9, 0x18, 0x87, 0xc2, 0xa6, 0xac, 0x36, 0xb6, + 0x0e, 0xea, 0x5e, 0xde, 0xf8, 0x4c, 0x1c, 0x35, + 0x81, 0x46, 0xa6, 0x66, 0xb6, 0x87, 0x83, 0x35 }, /* adata */ + 32, /* adata_len */ + {}, /* mdata */ + 0, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0xca, 0x48, 0x2c, 0x67, 0x4b, 0x59, 0x90, 0x46, + 0xcc, 0x7d, 0x7e, 0xe0, 0xd0, 0x0e, 0xec, 0x1e } /* expected */ + }, { + true, /* encrypt */ + 8, /* len_len */ + 2, /* key_size_index */ + 4, /* key_area */ + { 0xaa, 0xa2, 0x3f, 0x10, 0x16, 0x47, 0xd8 }, /* nonce */ + { 0xa3, 0x55, 0xd4, 0xc6, 0x11, 0x81, 0x2e, 0x5f, + 0x92, 0x58, 0xd7, 0x18, 0x8b, 0x3d, 0xf8, 0x85, + 0x14, 0x77, 0x09, 0x4f, 0xfc, 0x2a, 0xf2, 0xcf, + 0x0c, 0x86, 0x70, 0xdb, 0x90, 0x3f, 0xbb, 0xe0 }, /* adata */ + 32, /* adata_len */ + { 0x64, 0x4e, 0xb3, 0x4b, 0x9a, 0x12, 0x6e, 0x43, + 0x7b, 0x5e, 0x01, 0x5e, 0xea, 0x14, 0x1c, 0xa1, + 0xa8, 0x80, 0x20, 0xf2, 0xd5, 0xd6, 0xcc, 0x2c }, /* mdata */ + 24, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x27, 0xed, 0x90, 0x66, 0x81, 0x74, 0xeb, 0xf8, + 0x24, 0x1a, 0x3c, 0x74, 0xb3, 0x5e, 0x12, 0x46, + 0xb6, 0x61, 0x7e, 0x41, 0x23, 0x57, 0x8f, 0x15, + 0x3b, 0xdb, 0x67, 0x06, 0x2a, 0x13, 0xef, 0x4e, + 0x98, 0x6f, 0x5b, 0xb3, 0xd0, 0xbb, 0x43, 0x07 } /* expected */ + }, { + true, /* encrypt */ + 2, /* len_len */ + 2, /* key_size_index */ + 6, /* key_area */ + { 0x2e, 0x1e, 0x01, 0x32, 0x46, 0x85, 0x00, 0xd4, + 0xbd, 0x47, 0x86, 0x25, 0x63 }, /* nonce */ + { 0x3c, 0x5f, 0x54, 0x04, 0x37, 0x0a, 0xbd, 0xcb, + 0x1e, 0xdd, 0xe9, 0x9d, 0xe6, 0x0d, 0x06, 0x82, + 0xc6, 0x00, 0xb0, 0x34, 0xe0, 0x63, 0xb7, 0xd3, + 0x23, 0x77, 0x23, 0xda, 0x70, 0xab, 0x75, 0x52 }, /* adata */ + 32, /* adata_len */ + { 0x23, 0x90, 0x29, 0xf1, 0x50, 0xbc, 0xcb, 0xd6, + 0x7e, 0xdb, 0xb6, 0x7f, 0x8a, 0xe4, 0x56, 0xb4, + 0xea, 0x06, 0x6a, 0x4b, 0xee, 0xe0, 0x65, 0xf9 }, /* mdata */ + 24, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 4, /* mic_len */ + { 0x9c, 0x8d, 0x5d, 0xd2, 0x27, 0xfd, 0x9f, 0x81, + 0x23, 0x76, 0x01, 0x83, 0x0a, 0xfe, 0xe4, 0xf0, + 0x11, 0x56, 0x36, 0xc8, 0xe5, 0xd5, 0xfd, 0x74, + 0x3c, 0xb9, 0xaf, 0xed } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + 2, /* key_size_index */ + 0, /* key_area */ + { 0x72, 0xa6, 0x0f, 0x34, 0x5a, 0x19, 0x78, 0xfb, + 0x40, 0xf2, 0x8a, 0x2f, 0xa4 }, /* nonce */ + {}, /* adata */ + 0, /* adata_len */ + { 0x55, 0xf0, 0x68, 0xc0, 0xbb, 0xba, 0x8b, 0x59, + 0x80, 0x13, 0xdd, 0x18, 0x41, 0xfd, 0x74, 0x0f, + 0xda, 0x29, 0x02, 0x32, 0x21, 0x48, 0xab, 0x5e, + 0x93, 0x57, 0x53, 0xe6, 0x01, 0xb7, 0x9d, 0xb4, + 0xae, 0x73, 0x0b, 0x6a, 0xe3, 0x50, 0x07, 0x31 }, /* mdata */ + 40, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x30, 0xd5, 0x6f, 0xf2, 0xa2, 0x5b, 0x83, 0xfe, + 0xe7, 0x91, 0x11, 0x0f, 0xca, 0xea, 0x48, 0xe4, + 0x1d, 0xb7, 0xc7, 0xf0, 0x98, 0xa8, 0x10, 0x00 } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + 2, /* key_size_index */ + 2, /* key_area */ + { 0x29, 0x1e, 0x91, 0xb1, 0x9d, 0xe5, 0x18, 0xcd, + 0x78, 0x06, 0xde, 0x44, 0xf6 }, /* nonce */ + { 0xb4, 0xf8, 0x32, 0x69, 0x44, 0xa4, 0x5d, 0x95, + 0xf9, 0x18, 0x87, 0xc2, 0xa6, 0xac, 0x36, 0xb6, + 0x0e, 0xea, 0x5e, 0xde, 0xf8, 0x4c, 0x1c, 0x35, + 0x81, 0x46, 0xa6, 0x66, 0xb6, 0x87, 0x83, 0x35 }, /* adata */ + 32, /* adata_len */ + { 0xca, 0x48, 0x2c, 0x67, 0x4b, 0x59, 0x90, 0x46, + 0xcc, 0x7d, 0x7e, 0xe0, 0xd0, 0x0e, 0xec, 0x1e }, /* mdata */ + 16, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + {} /* expected */ + }, { + false, /* decrypt */ + 8, /* len_len */ + 2, /* key_size_index */ + 4, /* key_area */ + { 0xaa, 0xa2, 0x3f, 0x10, 0x16, 0x47, 0xd8 }, /* nonce */ + { 0xa3, 0x55, 0xd4, 0xc6, 0x11, 0x81, 0x2e, 0x5f, + 0x92, 0x58, 0xd7, 0x18, 0x8b, 0x3d, 0xf8, 0x85, + 0x14, 0x77, 0x09, 0x4f, 0xfc, 0x2a, 0xf2, 0xcf, + 0x0c, 0x86, 0x70, 0xdb, 0x90, 0x3f, 0xbb, 0xe0 }, /* adata */ + 32, /* adata_len */ + { 0x27, 0xed, 0x90, 0x66, 0x81, 0x74, 0xeb, 0xf8, + 0x24, 0x1a, 0x3c, 0x74, 0xb3, 0x5e, 0x12, 0x46, + 0xb6, 0x61, 0x7e, 0x41, 0x23, 0x57, 0x8f, 0x15, + 0x3b, 0xdb, 0x67, 0x06, 0x2a, 0x13, 0xef, 0x4e, + 0x98, 0x6f, 0x5b, 0xb3, 0xd0, 0xbb, 0x43, 0x07 }, /* mdata */ + 40, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 16, /* mic_len */ + { 0x64, 0x4e, 0xb3, 0x4b, 0x9a, 0x12, 0x6e, 0x43, + 0x7b, 0x5e, 0x01, 0x5e, 0xea, 0x14, 0x1c, 0xa1, + 0xa8, 0x80, 0x20, 0xf2, 0xd5, 0xd6, 0xcc, 0x2c } /* expected */ + }, { + false, /* decrypt */ + 2, /* len_len */ + 2, /* key_size_index */ + 6, /* key_area */ + { 0x2e, 0x1e, 0x01, 0x32, 0x46, 0x85, 0x00, 0xd4, + 0xbd, 0x47, 0x86, 0x25, 0x63 }, /* nonce */ + { 0x3c, 0x5f, 0x54, 0x04, 0x37, 0x0a, 0xbd, 0xcb, + 0x1e, 0xdd, 0xe9, 0x9d, 0xe6, 0x0d, 0x06, 0x82, + 0xc6, 0x00, 0xb0, 0x34, 0xe0, 0x63, 0xb7, 0xd3, + 0x23, 0x77, 0x23, 0xda, 0x70, 0xab, 0x75, 0x52 }, /* adata */ + 32, /* adata_len */ + { 0x9c, 0x8d, 0x5d, 0xd2, 0x27, 0xfd, 0x9f, 0x81, + 0x23, 0x76, 0x01, 0x83, 0x0a, 0xfe, 0xe4, 0xf0, + 0x11, 0x56, 0x36, 0xc8, 0xe5, 0xd5, 0xfd, 0x74, + 0x3c, 0xb9, 0xaf, 0xed }, /* mdata */ + 28, /* mdata_len */ + { 0x00, 0x00, 0x00, 0x00 }, /* mic */ + 4, /* mic_len */ + { 0x23, 0x90, 0x29, 0xf1, 0x50, 0xbc, 0xcb, 0xd6, + 0x7e, 0xdb, 0xb6, 0x7f, 0x8a, 0xe4, 0x56, 0xb4, + 0xea, 0x06, 0x6a, 0x4b, 0xee, 0xe0, 0x65, 0xf9 } /* expected */ + } + }; + static int i; + static uint8_t key_size_index = -1, ret; + static rtimer_clock_t time, time2, total_time; + + PROCESS_BEGIN(); + + puts("-----------------------------------------\n" + "Initializing cryptoprocessor..."); + crypto_init(); + + for(i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) { + if(key_size_index != vectors[i].key_size_index) { + key_size_index = vectors[i].key_size_index; + printf("-----------------------------------------\n" + "Filling %d-bit key store...\n", 128 + (key_size_index << 6)); + time = RTIMER_NOW(); + ret = aes_load_keys(keys[key_size_index].keys, + keys[key_size_index].key_size, keys[key_size_index].count, 0); + time = RTIMER_NOW() - time; + printf("aes_load_keys(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + PROCESS_PAUSE(); + if(ret != CRYPTO_SUCCESS) { + break; + } + } + + printf("-----------------------------------------\n" + "Test vector #%d: %s\n" + "len_len=%d key_area=%d\n" + "adata_len=%d mdata_len=%d mic_len=%d\n", + i, vectors[i].encrypt ? "encrypt" : "decrypt", + vectors[i].len_len, vectors[i].key_area, + vectors[i].adata_len, vectors[i].mdata_len, vectors[i].mic_len); + + time = RTIMER_NOW(); + if(vectors[i].encrypt) { + ret = ccm_auth_encrypt_start(vectors[i].len_len, vectors[i].key_area, + vectors[i].nonce, vectors[i].adata, + vectors[i].adata_len, vectors[i].mdata, + vectors[i].mdata_len, vectors[i].mic_len, + &ccm_test_process); + time2 = RTIMER_NOW(); + time = time2 - time; + total_time = time; + if(ret == CRYPTO_SUCCESS) { + PROCESS_WAIT_EVENT_UNTIL(ccm_auth_encrypt_check_status()); + time2 = RTIMER_NOW() - time2; + total_time += time2; + } + printf("ccm_auth_encrypt_start(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + if(ret != CRYPTO_SUCCESS) { + PROCESS_PAUSE(); + continue; + } + printf("ccm_auth_encrypt_check_status() wait: %lu us\n", + (uint32_t)((uint64_t)time2 * 1000000 / RTIMER_SECOND)); + + time = RTIMER_NOW(); + ret = ccm_auth_encrypt_get_result(vectors[i].mic, vectors[i].mic_len); + time = RTIMER_NOW() - time; + total_time += time; + printf("ccm_auth_encrypt_get_result(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + PROCESS_PAUSE(); + if(ret != CRYPTO_SUCCESS) { + continue; + } + + if(rom_util_memcmp(vectors[i].mdata, vectors[i].expected, + vectors[i].mdata_len)) { + puts("Encrypted message does not match expected one"); + } else { + puts("Encrypted message OK"); + } + + if(rom_util_memcmp(vectors[i].mic, + vectors[i].expected + vectors[i].mdata_len, + vectors[i].mic_len)) { + puts("MIC does not match expected one"); + } else { + puts("MIC OK"); + } + } else { + ret = ccm_auth_decrypt_start(vectors[i].len_len, vectors[i].key_area, + vectors[i].nonce, vectors[i].adata, + vectors[i].adata_len, vectors[i].mdata, + vectors[i].mdata_len, vectors[i].mic_len, + &ccm_test_process); + time2 = RTIMER_NOW(); + time = time2 - time; + total_time = time; + if(ret == CRYPTO_SUCCESS) { + PROCESS_WAIT_EVENT_UNTIL(ccm_auth_decrypt_check_status()); + time2 = RTIMER_NOW() - time2; + total_time += time2; + } + printf("ccm_auth_decrypt_start(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + if(ret != CRYPTO_SUCCESS) { + PROCESS_PAUSE(); + continue; + } + printf("ccm_auth_decrypt_check_status() wait: %lu us\n", + (uint32_t)((uint64_t)time2 * 1000000 / RTIMER_SECOND)); + + time = RTIMER_NOW(); + ret = ccm_auth_decrypt_get_result(vectors[i].mdata, vectors[i].mdata_len, + vectors[i].mic, vectors[i].mic_len); + time = RTIMER_NOW() - time; + total_time += time; + printf("ccm_auth_decrypt_get_result(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + PROCESS_PAUSE(); + if(ret != CRYPTO_SUCCESS) { + continue; + } + + if(rom_util_memcmp(vectors[i].mdata, vectors[i].expected, + vectors[i].mdata_len - vectors[i].mic_len)) { + puts("Decrypted message does not match expected one"); + } else { + puts("Decrypted message OK"); + } + } + + printf("Total duration: %lu us\n", + (uint32_t)((uint64_t)total_time * 1000000 / RTIMER_SECOND)); + } + + puts("-----------------------------------------\n" + "Disabling cryptoprocessor..."); + crypto_disable(); + + puts("Done!"); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/examples/cc2538dk/crypto/sha256-test.c b/examples/cc2538dk/crypto/sha256-test.c new file mode 100644 index 000000000..f690ed27d --- /dev/null +++ b/examples/cc2538dk/crypto/sha256-test.c @@ -0,0 +1,261 @@ +/* + * Original file: + * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Port to Contiki: + * Copyright (c) 2013, ADVANSEE - http://www.advansee.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-examples + * @{ + * + * \defgroup cc2538-sha256-test cc2538dk SHA-256 Test Project + * + * SHA-256 access example for CC2538 on SmartRF06EB. + * + * This example shows how SHA-256 should be used. The example also verifies + * the SHA-256 functionality. + * + * @{ + * + * \file + * Example demonstrating SHA-256 on the cc2538dk platform + */ +#include "contiki.h" +#include "sys/rtimer.h" +#include "dev/rom-util.h" +#include "dev/sha256.h" + +#include +#include +#include +#include +/*---------------------------------------------------------------------------*/ +PROCESS(sha256_test_process, "sha256 test process"); +AUTOSTART_PROCESSES(&sha256_test_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(sha256_test_process, ev, data) +{ + static const char *const str_res[] = { + "success", + "invalid param", + "NULL error", + "resource in use", + "DMA bus error" + }; + static const struct { + const char *data[3]; + uint8_t sha256[32]; + } vectors[] = { + { /* Simple */ + { + "abc", + NULL, + NULL + }, { + 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad + } + }, { /* Simple */ + { + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + NULL, + NULL, + }, { + 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 + } + }, { /* Message of length 130 */ + { + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklabcd" + "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn", + NULL, + NULL + }, { + 0x15, 0xd2, 0x3e, 0xea, 0x57, 0xb3, 0xd4, 0x61, + 0xbf, 0x38, 0x91, 0x12, 0xab, 0x4c, 0x43, 0xce, + 0x85, 0xe1, 0x68, 0x23, 0x8a, 0xaa, 0x54, 0x8e, + 0xc8, 0x6f, 0x0c, 0x9d, 0x65, 0xf9, 0xb9, 0x23 + } + }, { /* Message of length 128 */ + { + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklabcd" + "efghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl", + NULL, + NULL + }, { + 0xf8, 0xa3, 0xf2, 0x26, 0xfc, 0x42, 0x10, 0xe9, + 0x0d, 0x13, 0x0c, 0x7f, 0x41, 0xf2, 0xbe, 0x66, + 0x45, 0x53, 0x85, 0xd2, 0x92, 0x0a, 0xda, 0x78, + 0x15, 0xf8, 0xf7, 0x95, 0xd9, 0x44, 0x90, 0x5f + } + }, { /* Message of length 64 */ + { + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl", + NULL, + NULL + }, { + 0x2f, 0xcd, 0x5a, 0x0d, 0x60, 0xe4, 0xc9, 0x41, + 0x38, 0x1f, 0xcc, 0x4e, 0x00, 0xa4, 0xbf, 0x8b, + 0xe4, 0x22, 0xc3, 0xdd, 0xfa, 0xfb, 0x93, 0xc8, + 0x09, 0xe8, 0xd1, 0xe2, 0xbf, 0xff, 0xae, 0x8e + } + }, { /* Message of length 66 */ + { + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmn", + NULL, + NULL + }, { + 0x92, 0x90, 0x1c, 0x85, 0x82, 0xe3, 0x1c, 0x05, + 0x69, 0xb5, 0x36, 0x26, 0x9c, 0xe2, 0x2c, 0xc8, + 0x30, 0x8b, 0xa4, 0x17, 0xab, 0x36, 0xc1, 0xbb, + 0xaf, 0x08, 0x4f, 0xf5, 0x8b, 0x18, 0xdc, 0x6a + } + }, { + { + "abcdbcdecdefde", + "fgefghfghighijhijkijkljklmklmnlmnomnopnopq", + NULL + }, { + 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 + } + }, { + { + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl", + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl", + NULL + }, { + 0xf8, 0xa3, 0xf2, 0x26, 0xfc, 0x42, 0x10, 0xe9, + 0x0d, 0x13, 0x0c, 0x7f, 0x41, 0xf2, 0xbe, 0x66, + 0x45, 0x53, 0x85, 0xd2, 0x92, 0x0a, 0xda, 0x78, + 0x15, 0xf8, 0xf7, 0x95, 0xd9, 0x44, 0x90, 0x5f + } + }, { + { + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefgh", + "ijkl", + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijkl" + }, { + 0xf8, 0xa3, 0xf2, 0x26, 0xfc, 0x42, 0x10, 0xe9, + 0x0d, 0x13, 0x0c, 0x7f, 0x41, 0xf2, 0xbe, 0x66, + 0x45, 0x53, 0x85, 0xd2, 0x92, 0x0a, 0xda, 0x78, + 0x15, 0xf8, 0xf7, 0x95, 0xd9, 0x44, 0x90, 0x5f + } + } + }; + static sha256_state_t state; + static uint8_t sha256[32]; + static int i, j; + static uint8_t ret; + static rtimer_clock_t total_time; + rtimer_clock_t time; + size_t len; + + PROCESS_BEGIN(); + + puts("-----------------------------------------\n" + "Initializing cryptoprocessor..."); + crypto_init(); + + for(i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) { + printf("-----------------------------------------\n" + "Test vector #%d:\n", i); + + time = RTIMER_NOW(); + ret = sha256_init(&state); + time = RTIMER_NOW() - time; + total_time = time; + printf("sha256_init(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + PROCESS_PAUSE(); + if(ret != CRYPTO_SUCCESS) { + continue; + } + + for(j = 0; j < sizeof(vectors[i].data) / sizeof(vectors[i].data[0]) && + vectors[i].data[j] != NULL; j++) { + len = strlen(vectors[i].data[j]); + printf("Buffer #%d (length: %u):\n", j, len); + time = RTIMER_NOW(); + ret = sha256_process(&state, vectors[i].data[j], len); + time = RTIMER_NOW() - time; + total_time += time; + printf("sha256_process(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + PROCESS_PAUSE(); + if(ret != CRYPTO_SUCCESS) { + break; + } + } + if(ret != CRYPTO_SUCCESS) { + continue; + } + + time = RTIMER_NOW(); + ret = sha256_done(&state, sha256); + time = RTIMER_NOW() - time; + total_time += time; + printf("sha256_done(): %s, %lu us\n", str_res[ret], + (uint32_t)((uint64_t)time * 1000000 / RTIMER_SECOND)); + PROCESS_PAUSE(); + if(ret != CRYPTO_SUCCESS) { + continue; + } + + if(rom_util_memcmp(sha256, vectors[i].sha256, sizeof(sha256))) { + puts("Computed SHA-256 hash does not match expected hash"); + } else { + puts("Computed SHA-256 hash OK"); + } + printf("Total duration: %lu us\n", + (uint32_t)((uint64_t)total_time * 1000000 / RTIMER_SECOND)); + } + + puts("-----------------------------------------\n" + "Disabling cryptoprocessor..."); + crypto_disable(); + + puts("Done!"); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/examples/cc2538dk/mqtt-demo/mqtt-demo.c b/examples/cc2538dk/mqtt-demo/mqtt-demo.c index 398feec68..691d4deed 100644 --- a/examples/cc2538dk/mqtt-demo/mqtt-demo.c +++ b/examples/cc2538dk/mqtt-demo/mqtt-demo.c @@ -53,7 +53,7 @@ #include "lib/sensors.h" #include "dev/button-sensor.h" #include "dev/leds.h" -#include "dev/adc-sensor.h" +#include "dev/cc2538-sensors.h" #include /*---------------------------------------------------------------------------*/ @@ -450,7 +450,6 @@ publish(void) /* Publish MQTT topic in IBM quickstart format */ int len; int remaining = APP_BUFFER_SIZE; - int16_t value; seq_nr_value++; @@ -487,9 +486,8 @@ publish(void) remaining -= len; buf_ptr += len; - value = adc_sensor.value(ADC_SENSOR_TEMP); len = snprintf(buf_ptr, remaining, ",\"On-Chip Temp (mC)\":%d", - 25000 + ((value >> 4) - 1422) * 10000 / 42); + cc2538_temp_sensor.value(CC2538_SENSORS_VALUE_TYPE_CONVERTED)); if(len < 0 || len >= remaining) { printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); @@ -498,9 +496,8 @@ publish(void) remaining -= len; buf_ptr += len; - value = adc_sensor.value(ADC_SENSOR_VDD_3); len = snprintf(buf_ptr, remaining, ",\"VDD3 (mV)\":%d", - value * (3 * 1190) / (2047 << 4)); + vdd3_sensor.value(CC2538_SENSORS_VALUE_TYPE_CONVERTED)); if(len < 0 || len >= remaining) { printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len); diff --git a/examples/cc2538dk/sniffer/netstack.c b/examples/cc2538dk/sniffer/netstack.c index 0945be888..3aeb6968e 100644 --- a/examples/cc2538dk/sniffer/netstack.c +++ b/examples/cc2538dk/sniffer/netstack.c @@ -41,5 +41,6 @@ void netstack_init(void) { NETSTACK_RADIO.init(); + NETSTACK_RADIO.on(); } /*---------------------------------------------------------------------------*/ diff --git a/examples/cc26xx/README.md b/examples/cc26xx/README.md index bd1be685b..411bc9407 100644 --- a/examples/cc26xx/README.md +++ b/examples/cc26xx/README.md @@ -6,8 +6,6 @@ boards. More specifically, the example demonstrates: * How to take sensor readings * How to use buttons and the reed relay (triggered by holding a magnet near S3 on the SensorTag). -* How to keep a power domain powered and a peripheral clocked under low power - operation * How to send out BLE advertisements. The device will periodically send out BLE beacons with the platform name as payload. Those beacons/BLE ADV packets can be captured with any BLE capable device. Two such applications for iOS are the diff --git a/examples/cc26xx/cc26xx-demo.c b/examples/cc26xx/cc26xx-demo.c index 83f78e869..1426bb983 100644 --- a/examples/cc26xx/cc26xx-demo.c +++ b/examples/cc26xx/cc26xx-demo.c @@ -77,12 +77,6 @@ * - The example also shows how to retrieve the duration of a * button press (in ticks). The driver will generate a * sensors_changed event upon button release - * - UART : Receiving an entire line of text over UART (ending - * in \\r) will cause CC26XX_DEMO_LEDS_SERIAL_IN to toggle - * This also demonstrates how a code module can influence - * low-power operation: In this example we keep the UART on - * and capable to RX even with the chip in deep sleep. - * see keep_uart_on() and the UART driver * - Reed Relay : Will toggle the sensortag buzzer on/off * * @{ @@ -100,7 +94,6 @@ #include "button-sensor.h" #include "batmon-sensor.h" #include "board-peripherals.h" -#include "lpm.h" #include "cc26xx-rf.h" #include "ti-lib.h" @@ -143,11 +136,11 @@ AUTOSTART_PROCESSES(&cc26xx_demo_process); #define SENSOR_READING_PERIOD (CLOCK_SECOND * 20) #define SENSOR_READING_RANDOM (CLOCK_SECOND << 4) -static struct ctimer bmp_timer, opt_timer, sht_timer, tmp_timer, mpu_timer; +static struct ctimer bmp_timer, opt_timer, hdc_timer, tmp_timer, mpu_timer; /*---------------------------------------------------------------------------*/ static void init_bmp_reading(void *not_used); static void init_opt_reading(void *not_used); -static void init_sht_reading(void *not_used); +static void init_hdc_reading(void *not_used); static void init_tmp_reading(void *not_used); static void init_mpu_reading(void *not_used); /*---------------------------------------------------------------------------*/ @@ -214,27 +207,27 @@ get_tmp_reading() } /*---------------------------------------------------------------------------*/ static void -get_sht_reading() +get_hdc_reading() { int value; clock_time_t next = SENSOR_READING_PERIOD + (random_rand() % SENSOR_READING_RANDOM); - value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_TEMP); + value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_TEMP); if(value != CC26XX_SENSOR_READING_ERROR) { - printf("SHT: Temp=%d.%02d C\n", value / 100, value % 100); + printf("HDC: Temp=%d.%02d C\n", value / 100, value % 100); } else { - printf("SHT: Temp Read Error\n"); + printf("HDC: Temp Read Error\n"); } - value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_HUMIDITY); + value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_HUMIDITY); if(value != CC26XX_SENSOR_READING_ERROR) { - printf("SHT: Humidity=%d.%02d %%RH\n", value / 100, value % 100); + printf("HDC: Humidity=%d.%02d %%RH\n", value / 100, value % 100); } else { - printf("SHT: Humidity Read Error\n"); + printf("HDC: Humidity Read Error\n"); } - ctimer_set(&sht_timer, next, init_sht_reading, NULL); + ctimer_set(&hdc_timer, next, init_hdc_reading, NULL); } /*---------------------------------------------------------------------------*/ static void @@ -251,8 +244,7 @@ get_light_reading() printf("OPT: Light Read Error\n"); } - SENSORS_DEACTIVATE(opt_3001_sensor); - + /* The OPT will turn itself off, so we don't need to call its DEACTIVATE */ ctimer_set(&opt_timer, next, init_opt_reading, NULL); } /*---------------------------------------------------------------------------*/ @@ -311,9 +303,9 @@ init_opt_reading(void *not_used) } /*---------------------------------------------------------------------------*/ static void -init_sht_reading(void *not_used) +init_hdc_reading(void *not_used) { - SENSORS_ACTIVATE(sht_21_sensor); + SENSORS_ACTIVATE(hdc_1000_sensor); } /*---------------------------------------------------------------------------*/ static void @@ -337,8 +329,7 @@ get_sync_sensor_readings(void) printf("-----------------------------------------\n"); value = batmon_sensor.value(BATMON_SENSOR_TYPE_TEMP); - printf("Bat: Temp=%d.%02d C (%08x)\n", value >> 2, - (value & 0x00000003) * 25, value); + printf("Bat: Temp=%d C\n", value); value = batmon_sensor.value(BATMON_SENSOR_TYPE_VOLT); printf("Bat: Volt=%d mV\n", (value * 125) >> 5); @@ -360,7 +351,7 @@ static void init_sensor_readings(void) { #if BOARD_SENSORTAG - SENSORS_ACTIVATE(sht_21_sensor); + SENSORS_ACTIVATE(hdc_1000_sensor); SENSORS_ACTIVATE(tmp_007_sensor); SENSORS_ACTIVATE(opt_3001_sensor); SENSORS_ACTIVATE(bmp_280_sensor); @@ -369,26 +360,6 @@ init_sensor_readings(void) #endif } /*---------------------------------------------------------------------------*/ -static lpm_power_domain_lock_t lock; -/*---------------------------------------------------------------------------*/ -/* - * In order to maintain UART input operation: - * - Keep the uart clocked in sleep and deep sleep - * - Keep the serial PD on in deep sleep - */ -static void -keep_uart_on(void) -{ - /* Keep the serial PD on */ - lpm_pd_lock_obtain(&lock, PRCM_DOMAIN_SERIAL); - - /* Keep the UART clock on during Sleep and Deep Sleep */ - ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_UART0); - ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_UART0); - ti_lib_prcm_load_set(); - while(!ti_lib_prcm_load_get()); -} -/*---------------------------------------------------------------------------*/ PROCESS_THREAD(cc26xx_demo_process, ev, data) { @@ -406,8 +377,6 @@ PROCESS_THREAD(cc26xx_demo_process, ev, data) get_sync_sensor_readings(); init_sensor_readings(); - keep_uart_on(); - while(1) { PROCESS_YIELD(); @@ -450,8 +419,8 @@ PROCESS_THREAD(cc26xx_demo_process, ev, data) get_bmp_reading(); } else if(ev == sensors_event && data == &opt_3001_sensor) { get_light_reading(); - } else if(ev == sensors_event && data == &sht_21_sensor) { - get_sht_reading(); + } else if(ev == sensors_event && data == &hdc_1000_sensor) { + get_hdc_reading(); } else if(ev == sensors_event && data == &tmp_007_sensor) { get_tmp_reading(); } else if(ev == sensors_event && data == &mpu_9250_sensor) { @@ -462,8 +431,6 @@ PROCESS_THREAD(cc26xx_demo_process, ev, data) button_select_sensor.value(BUTTON_SENSOR_VALUE_DURATION)); #endif } - } else if(ev == serial_line_event_message) { - leds_toggle(CC26XX_DEMO_LEDS_SERIAL_IN); } } diff --git a/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c index 91f921b9d..4d8c9ca86 100644 --- a/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c +++ b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c @@ -68,7 +68,7 @@ PROCESS(cc26xx_web_demo_process, "CC26XX Web Demo"); struct ctimer batmon_timer; #if BOARD_SENSORTAG -struct ctimer bmp_timer, sht_timer, tmp_timer, opt_timer, mpu_timer; +struct ctimer bmp_timer, hdc_timer, tmp_timer, opt_timer, mpu_timer; #endif /*---------------------------------------------------------------------------*/ /* Provide visible feedback via LEDS while searching for a network */ @@ -111,11 +111,11 @@ DEMO_SENSOR(bmp_pres, CC26XX_WEB_DEMO_SENSOR_BMP_PRES, DEMO_SENSOR(bmp_temp, CC26XX_WEB_DEMO_SENSOR_BMP_TEMP, "Air Temp", "air-temp", "bmp_temp", CC26XX_WEB_DEMO_UNIT_TEMP); -DEMO_SENSOR(sht_temp, CC26XX_WEB_DEMO_SENSOR_SHT_TEMP, - "SHT Temp", "sht-temp", "sht_temp", +DEMO_SENSOR(hdc_temp, CC26XX_WEB_DEMO_SENSOR_HDC_TEMP, + "HDC Temp", "hdc-temp", "hdc_temp", CC26XX_WEB_DEMO_UNIT_TEMP); -DEMO_SENSOR(sht_hum, CC26XX_WEB_DEMO_SENSOR_SHT_HUMIDITY, - "SHT Humidity", "sht-humidity", "sht_hum", +DEMO_SENSOR(hdc_hum, CC26XX_WEB_DEMO_SENSOR_HDC_HUMIDITY, + "HDC Humidity", "hdc-humidity", "hdc_hum", CC26XX_WEB_DEMO_UNIT_HUMIDITY); DEMO_SENSOR(tmp_amb, CC26XX_WEB_DEMO_SENSOR_TMP_AMBIENT, "Ambient Temp", "ambient-temp", "tmp_amb", @@ -152,7 +152,7 @@ DEMO_SENSOR(mpu_gyro_z, CC26XX_WEB_DEMO_SENSOR_MPU_GYRO_Z, #if BOARD_SENSORTAG static void init_bmp_reading(void *data); static void init_light_reading(void *data); -static void init_sht_reading(void *data); +static void init_hdc_reading(void *data); static void init_tmp_reading(void *data); static void init_mpu_reading(void *data); #endif @@ -392,8 +392,7 @@ get_batmon_reading(void *data) buf = batmon_temp_reading.converted; memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); - snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value >> 2, - (value & 0x00000003) * 25); + snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d", value); } } @@ -526,42 +525,42 @@ get_tmp_reading() } /*---------------------------------------------------------------------------*/ static void -get_sht_reading() +get_hdc_reading() { int value; char *buf; clock_time_t next = SENSOR_READING_PERIOD + (random_rand() % SENSOR_READING_RANDOM); - if(sht_temp_reading.publish) { - value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_TEMP); + if(hdc_temp_reading.publish) { + value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_TEMP); if(value != CC26XX_SENSOR_READING_ERROR) { - sht_temp_reading.raw = value; + hdc_temp_reading.raw = value; - compare_and_update(&sht_temp_reading); + compare_and_update(&hdc_temp_reading); - buf = sht_temp_reading.converted; + buf = hdc_temp_reading.converted; memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value / 100, value % 100); } } - if(sht_hum_reading.publish) { - value = sht_21_sensor.value(SHT_21_SENSOR_TYPE_HUMIDITY); + if(hdc_hum_reading.publish) { + value = hdc_1000_sensor.value(HDC_1000_SENSOR_TYPE_HUMIDITY); if(value != CC26XX_SENSOR_READING_ERROR) { - sht_hum_reading.raw = value; + hdc_hum_reading.raw = value; - compare_and_update(&sht_hum_reading); + compare_and_update(&hdc_hum_reading); - buf = sht_hum_reading.converted; + buf = hdc_hum_reading.converted; memset(buf, 0, CC26XX_WEB_DEMO_CONVERTED_LEN); snprintf(buf, CC26XX_WEB_DEMO_CONVERTED_LEN, "%d.%02d", value / 100, value % 100); } } - ctimer_set(&sht_timer, next, init_sht_reading, NULL); + ctimer_set(&hdc_timer, next, init_hdc_reading, NULL); } /*---------------------------------------------------------------------------*/ static void @@ -574,8 +573,6 @@ get_light_reading() value = opt_3001_sensor.value(0); - SENSORS_DEACTIVATE(opt_3001_sensor); - if(value != CC26XX_SENSOR_READING_ERROR) { opt_reading.raw = value; @@ -587,6 +584,7 @@ get_light_reading() value % 100); } + /* The OPT will turn itself off, so we don't need to call its DEACTIVATE */ ctimer_set(&opt_timer, next, init_light_reading, NULL); } /*---------------------------------------------------------------------------*/ @@ -702,12 +700,12 @@ init_bmp_reading(void *data) } /*---------------------------------------------------------------------------*/ static void -init_sht_reading(void *data) +init_hdc_reading(void *data) { - if(sht_hum_reading.publish || sht_temp_reading.publish) { - SENSORS_ACTIVATE(sht_21_sensor); + if(hdc_hum_reading.publish || hdc_temp_reading.publish) { + SENSORS_ACTIVATE(hdc_1000_sensor); } else { - ctimer_set(&sht_timer, CLOCK_SECOND, init_sht_reading, NULL); + ctimer_set(&hdc_timer, CLOCK_SECOND, init_hdc_reading, NULL); } } /*---------------------------------------------------------------------------*/ @@ -756,7 +754,7 @@ init_sensor_readings(void) #if BOARD_SENSORTAG init_bmp_reading(NULL); init_light_reading(NULL); - init_sht_reading(NULL); + init_hdc_reading(NULL); init_tmp_reading(NULL); init_mpu_reading(NULL); #endif /* BOARD_SENSORTAG */ @@ -781,8 +779,8 @@ init_sensors(void) list_add(sensor_list, &opt_reading); - list_add(sensor_list, &sht_hum_reading); - list_add(sensor_list, &sht_temp_reading); + list_add(sensor_list, &hdc_hum_reading); + list_add(sensor_list, &hdc_temp_reading); list_add(sensor_list, &mpu_acc_x_reading); list_add(sensor_list, &mpu_acc_y_reading); @@ -852,7 +850,7 @@ PROCESS_THREAD(cc26xx_web_demo_process, ev, data) while(1) { if(ev == sensors_event && data == CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER) { if((CC26XX_WEB_DEMO_SENSOR_READING_TRIGGER)->value( - BUTTON_SENSOR_VALUE_DURATION) > CLOCK_SECOND * 5) { + BUTTON_SENSOR_VALUE_DURATION) > CLOCK_SECOND * 5) { printf("Restoring defaults!\n"); cc26xx_web_demo_restore_defaults(); } else { @@ -873,8 +871,8 @@ PROCESS_THREAD(cc26xx_web_demo_process, ev, data) get_bmp_reading(); } else if(ev == sensors_event && data == &opt_3001_sensor) { get_light_reading(); - } else if(ev == sensors_event && data == &sht_21_sensor) { - get_sht_reading(); + } else if(ev == sensors_event && data == &hdc_1000_sensor) { + get_hdc_reading(); } else if(ev == sensors_event && data == &tmp_007_sensor) { get_tmp_reading(); } else if(ev == sensors_event && data == &mpu_9250_sensor) { diff --git a/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h index 89bf91d2b..a501925e8 100644 --- a/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h +++ b/examples/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h @@ -121,8 +121,8 @@ #define CC26XX_WEB_DEMO_SENSOR_BMP_TEMP 3 #define CC26XX_WEB_DEMO_SENSOR_TMP_AMBIENT 4 #define CC26XX_WEB_DEMO_SENSOR_TMP_OBJECT 5 -#define CC26XX_WEB_DEMO_SENSOR_SHT_TEMP 6 -#define CC26XX_WEB_DEMO_SENSOR_SHT_HUMIDITY 7 +#define CC26XX_WEB_DEMO_SENSOR_HDC_TEMP 6 +#define CC26XX_WEB_DEMO_SENSOR_HDC_HUMIDITY 7 #define CC26XX_WEB_DEMO_SENSOR_OPT_LIGHT 8 #define CC26XX_WEB_DEMO_SENSOR_MPU_ACC_X 9 #define CC26XX_WEB_DEMO_SENSOR_MPU_ACC_Y 10 diff --git a/examples/cc26xx/cc26xx-web-demo/coap-server.c b/examples/cc26xx/cc26xx-web-demo/coap-server.c index 65d748707..0b434d170 100644 --- a/examples/cc26xx/cc26xx-web-demo/coap-server.c +++ b/examples/cc26xx/cc26xx-web-demo/coap-server.c @@ -66,8 +66,8 @@ extern resource_t res_bmp280_temp; extern resource_t res_bmp280_press; extern resource_t res_tmp007_amb; extern resource_t res_tmp007_obj; -extern resource_t res_sht21_temp; -extern resource_t res_sht21_hum; +extern resource_t res_hdc1000_temp; +extern resource_t res_hdc1000_hum; extern resource_t res_opt3001_light; extern resource_t res_mpu_acc_x; extern resource_t res_mpu_acc_y; @@ -98,8 +98,8 @@ start_board_resources(void) rest_activate_resource(&res_bmp280_press, "sen/bar/pres"); rest_activate_resource(&res_tmp007_amb, "sen/tmp/amb"); rest_activate_resource(&res_tmp007_obj, "sen/tmp/obj"); - rest_activate_resource(&res_sht21_temp, "sen/sht/t"); - rest_activate_resource(&res_sht21_hum, "sen/sht/h"); + rest_activate_resource(&res_hdc1000_temp, "sen/hdc/t"); + rest_activate_resource(&res_hdc1000_hum, "sen/hdc/h"); rest_activate_resource(&res_opt3001_light, "sen/opt/light"); rest_activate_resource(&res_mpu_acc_x, "sen/mpu/acc/x"); rest_activate_resource(&res_mpu_acc_y, "sen/mpu/acc/y"); diff --git a/examples/cc26xx/cc26xx-web-demo/httpd-simple.c b/examples/cc26xx/cc26xx-web-demo/httpd-simple.c index 281567acf..29c22d22b 100644 --- a/examples/cc26xx/cc26xx-web-demo/httpd-simple.c +++ b/examples/cc26xx/cc26xx-web-demo/httpd-simple.c @@ -163,11 +163,6 @@ static const char *http_header_srv_str[] = { NULL }; -static const char *http_header_redir_location[] = { - "Location: /config.html\r\n", - NULL -}; - static const char *http_header_con_close[] = { CONN_CLOSE, NULL @@ -197,37 +192,49 @@ static const char config_div_left[] = "
"; static const char config_div_right[] = "
"; static const char config_div_close[] = "
"; /*---------------------------------------------------------------------------*/ +static char generate_index(struct httpd_state *s); +static char generate_config(struct httpd_state *s); +/*---------------------------------------------------------------------------*/ typedef struct page { struct page *next; char *filename; char *title; + char (*script)(struct httpd_state *s); } page_t; static page_t http_index_page = { NULL, "index.html", "Index", + generate_index, }; static page_t http_dev_cfg_page = { NULL, "config.html", "Device Config", + generate_config, }; #if CC26XX_WEB_DEMO_NET_UART +static char generate_net_uart_config(struct httpd_state *s); + static page_t http_net_cfg_page = { NULL, - "net.html", + "netu.html", "Net-UART Config", + generate_net_uart_config, }; #endif #if CC26XX_WEB_DEMO_MQTT_CLIENT +static char generate_mqtt_config(struct httpd_state *s); + static page_t http_mqtt_cfg_page = { NULL, "mqtt.html", "MQTT/IBM Cloud Config", + generate_mqtt_config, }; #endif /*---------------------------------------------------------------------------*/ @@ -395,12 +402,12 @@ PT_THREAD(generate_top_matter(struct httpd_state *s, const char *title, s->page = list_head(pages_list); PT_WAIT_THREAD(&s->top_matter_pt, - enqueue_chunk(s, 0, "[ %s ]", + enqueue_chunk(s, 0, "[ %s ]", s->page->filename, s->page->title)); for(s->page = s->page->next; s->page != NULL; s->page = s->page->next) { PT_WAIT_THREAD(&s->top_matter_pt, - enqueue_chunk(s, 0, " | [ %s ]", + enqueue_chunk(s, 0, " | [ %s ]", s->page->filename, s->page->title)); } @@ -531,7 +538,8 @@ PT_THREAD(generate_config(struct httpd_state *s)) PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, - "
generate_pt, enqueue_chunk(s, 0, "method=\"post\" enctype=\"")); PT_WAIT_THREAD(&s->generate_pt, @@ -570,7 +578,8 @@ PT_THREAD(generate_config(struct httpd_state *s)) PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "

Actions

")); PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, - "generate_pt, enqueue_chunk(s, 0, "method=\"post\" enctype=\"")); PT_WAIT_THREAD(&s->generate_pt, @@ -607,7 +616,8 @@ PT_THREAD(generate_mqtt_config(struct httpd_state *s)) PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, - "generate_pt, enqueue_chunk(s, 0, "method=\"post\" enctype=\"")); PT_WAIT_THREAD(&s->generate_pt, @@ -747,7 +757,8 @@ PT_THREAD(generate_mqtt_config(struct httpd_state *s)) enqueue_chunk(s, 0, "
")); PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, - "
generate_pt, enqueue_chunk(s, 0, "method=\"post\" enctype=\"")); PT_WAIT_THREAD(&s->generate_pt, @@ -786,7 +797,8 @@ PT_THREAD(generate_net_uart_config(struct httpd_state *s)) PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, - "generate_pt, enqueue_chunk(s, 0, "method=\"post\" enctype=\"")); PT_WAIT_THREAD(&s->generate_pt, @@ -974,18 +986,13 @@ parse_post_request_chunk(char *buf, int buf_len, int last_chunk) static httpd_simple_script_t get_script(const char *name) { - if(strlen(name) == 10 && strncmp(name, "index.html", 10) == 0) { - return generate_index; - } else if(strlen(name) == 11 && strncmp(name, "config.html", 11) == 0) { - return generate_config; -#if CC26XX_WEB_DEMO_MQTT_CLIENT - } else if(strlen(name) == 9 && strncmp(name, "mqtt.html", 9) == 0) { - return generate_mqtt_config; -#endif -#if CC26XX_WEB_DEMO_NET_UART - } else if(strlen(name) == 8 && strncmp(name, "net.html", 8) == 0) { - return generate_net_uart_config; -#endif + page_t *page; + + for(page = list_head(pages_list); page != NULL; + page = list_item_next(page)) { + if(strncmp(name, page->filename, strlen(page->filename)) == 0) { + return page->script; + } } return NULL; @@ -1003,7 +1010,8 @@ PT_THREAD(send_string(struct httpd_state *s, const char *str)) /*---------------------------------------------------------------------------*/ static PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr, - const char *content_type, const char **additional)) + const char *content_type, const char *redir, + const char **additional)) { PT_BEGIN(&s->generate_pt); @@ -1013,6 +1021,11 @@ PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr, PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, *(s->ptr))); } + if(redir) { + PT_WAIT_THREAD(&s->generate_pt, + enqueue_chunk(s, 0, "Location: %s\r\n", redir)); + } + if(additional) { for(s->ptr = additional; *(s->ptr) != NULL; s->ptr++) { PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, *(s->ptr))); @@ -1041,25 +1054,30 @@ PT_THREAD(handle_output(struct httpd_state *s)) if(s->return_code == RETURN_CODE_OK) { PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_302, http_content_type_plain, - http_header_redir_location)); + s->filename, + NULL)); } else if(s->return_code == RETURN_CODE_LR) { PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_411, http_content_type_plain, + NULL, http_header_con_close)); PT_WAIT_THREAD(&s->outputpt, send_string(s, "Content-Length Required\n")); } else if(s->return_code == RETURN_CODE_TL) { PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_413, http_content_type_plain, + NULL, http_header_con_close)); PT_WAIT_THREAD(&s->outputpt, send_string(s, "Content-Length too Large\n")); } else if(s->return_code == RETURN_CODE_SU) { PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_503, http_content_type_plain, + NULL, http_header_con_close)); PT_WAIT_THREAD(&s->outputpt, send_string(s, "Service Unavailable\n")); } else { PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_400, http_content_type_plain, + NULL, http_header_con_close)); PT_WAIT_THREAD(&s->outputpt, send_string(s, "Bad Request\n")); } @@ -1069,6 +1087,7 @@ PT_THREAD(handle_output(struct httpd_state *s)) strncpy(s->filename, "/notfound.html", sizeof(s->filename)); PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_404, http_content_type_html, + NULL, http_header_con_close)); PT_WAIT_THREAD(&s->outputpt, send_string(s, NOT_FOUND)); @@ -1077,6 +1096,7 @@ PT_THREAD(handle_output(struct httpd_state *s)) } else { PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_200, http_content_type_html, + NULL, http_header_con_close)); PT_WAIT_THREAD(&s->outputpt, s->script(s)); } @@ -1109,6 +1129,15 @@ PT_THREAD(handle_input(struct httpd_state *s)) } } else if(strncasecmp(s->inputbuf, http_post, 5) == 0) { s->request_type = REQUEST_TYPE_POST; + PSOCK_READTO(&s->sin, ISO_space); + + if(s->inputbuf[0] != ISO_slash) { + PSOCK_CLOSE_EXIT(&s->sin); + } + + s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0; + strncpy(s->filename, s->inputbuf, sizeof(s->filename)); + /* POST: Read out the rest of the line and ignore it */ PSOCK_READTO(&s->sin, ISO_nl); @@ -1279,8 +1308,8 @@ PROCESS_THREAD(httpd_simple_process, ev, data) init(); snprintf(http_mqtt_a, IBM_QUICKSTART_LINK_LEN, - "[ IBM Quickstart ]", + "[ IBM Quickstart ]", 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]); diff --git a/examples/cc26xx/cc26xx-web-demo/net-uart.c b/examples/cc26xx/cc26xx-web-demo/net-uart.c index 96463aee0..c3ddf0977 100644 --- a/examples/cc26xx/cc26xx-web-demo/net-uart.c +++ b/examples/cc26xx/cc26xx-web-demo/net-uart.c @@ -59,12 +59,13 @@ #include "contiki-conf.h" #include "sys/process.h" #include "dev/serial-line.h" +#include "dev/cc26xx-uart.h" #include "net/ip/uip.h" #include "net/ip/uip-udp-packet.h" #include "net/ip/uiplib.h" -#include "lpm.h" #include "net-uart.h" #include "httpd-simple.h" +#include "sys/cc.h" #include "ti-lib.h" @@ -86,10 +87,6 @@ #define ADDRESS_CONVERSION_OK 1 #define ADDRESS_CONVERSION_ERROR 0 /*---------------------------------------------------------------------------*/ -#ifndef MIN -#define MIN(n, m) (((n) < (m)) ? (n) : (m)) -#endif -/*---------------------------------------------------------------------------*/ static struct uip_udp_conn *udp_conn = NULL; static uint8_t buffer[MAX_MSG_SIZE]; @@ -148,37 +145,16 @@ net_input(void) return; } /*---------------------------------------------------------------------------*/ -/* - * In order to maintain UART input operation: - * - Keep the uart clocked in sleep and deep sleep - * - Keep the serial PD on in deep sleep - */ -static lpm_power_domain_lock_t lock; -/*---------------------------------------------------------------------------*/ static void release_uart(void) { - /* Release serial PD lock */ - lpm_pd_lock_release(&lock); - - /* Let the UART turn off during Sleep and Deep Sleep */ - ti_lib_prcm_peripheral_sleep_disable(PRCM_PERIPH_UART0); - ti_lib_prcm_peripheral_deep_sleep_disable(PRCM_PERIPH_UART0); - ti_lib_prcm_load_set(); - while(!ti_lib_prcm_load_get()); + cc26xx_uart_set_input(NULL); } /*---------------------------------------------------------------------------*/ static void keep_uart_on(void) { - /* Keep the serial PD on */ - lpm_pd_lock_obtain(&lock, PRCM_DOMAIN_SERIAL); - - /* Keep the UART clock on during Sleep and Deep Sleep */ - ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_UART0); - ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_UART0); - ti_lib_prcm_load_set(); - while(!ti_lib_prcm_load_get()); + cc26xx_uart_set_input(serial_line_input_byte); } /*---------------------------------------------------------------------------*/ static int diff --git a/examples/cc26xx/cc26xx-web-demo/project-conf.h b/examples/cc26xx/cc26xx-web-demo/project-conf.h index d49a7b3e9..b7baac119 100644 --- a/examples/cc26xx/cc26xx-web-demo/project-conf.h +++ b/examples/cc26xx/cc26xx-web-demo/project-conf.h @@ -44,10 +44,14 @@ #define CC26XX_WEB_DEMO_CONF_COAP_SERVER 1 #define CC26XX_WEB_DEMO_CONF_NET_UART 1 /*---------------------------------------------------------------------------*/ -/* Shrink the size of the uIP buffer, routing table and ND cache */ +/* + * Shrink the size of the uIP buffer, routing table and ND cache. + * Set the TCP MSS + */ #define UIP_CONF_BUFFER_SIZE 900 #define NBR_TABLE_CONF_MAX_NEIGHBORS 8 #define UIP_CONF_MAX_ROUTES 8 +#define UIP_CONF_TCP_MSS 128 /*---------------------------------------------------------------------------*/ #endif /* PROJECT_CONF_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/examples/cc26xx/cc26xx-web-demo/resources/res-sensors.c b/examples/cc26xx/cc26xx-web-demo/resources/res-sensors.c index fecfca994..277c29c05 100644 --- a/examples/cc26xx/cc26xx-web-demo/resources/res-sensors.c +++ b/examples/cc26xx/cc26xx-web-demo/resources/res-sensors.c @@ -229,28 +229,28 @@ RESOURCE(res_bmp280_press, "title=\"Barometer (Pressure)\";rt=\"hPa (hectopascal / millibar)\"", res_get_handler_bmp_press, NULL, NULL, NULL); /*---------------------------------------------------------------------------*/ -/* SHT21 sensor resources and handler: Temperature, Pressure */ +/* HDC1000 sensor resources and handler: Temperature, Pressure */ static void -res_get_handler_sht_temp(void *request, void *response, uint8_t *buffer, +res_get_handler_hdc_temp(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_SHT_TEMP, request, response, + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_HDC_TEMP, request, response, buffer, preferred_size, offset); } /*---------------------------------------------------------------------------*/ static void -res_get_handler_sht_humidity(void *request, void *response, uint8_t *buffer, +res_get_handler_hdc_humidity(void *request, void *response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { - res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_SHT_HUMIDITY, request, response, + res_get_handler_all(CC26XX_WEB_DEMO_SENSOR_HDC_HUMIDITY, request, response, buffer, preferred_size, offset); } /*---------------------------------------------------------------------------*/ -RESOURCE(res_sht21_temp, "title=\"Temperature\";rt=\"C\"", - res_get_handler_sht_temp, NULL, NULL, NULL); +RESOURCE(res_hdc1000_temp, "title=\"Temperature\";rt=\"C\"", + res_get_handler_hdc_temp, NULL, NULL, NULL); -RESOURCE(res_sht21_hum, "title=\"Humidity\";rt=\"%RH\"", - res_get_handler_sht_humidity, NULL, NULL, NULL); +RESOURCE(res_hdc1000_hum, "title=\"Humidity\";rt=\"%RH\"", + res_get_handler_hdc_humidity, NULL, NULL, NULL); /*---------------------------------------------------------------------------*/ /* Illuminance resources and handler */ static void diff --git a/examples/er-rest-example/resources/res-plugtest-large-update.c b/examples/er-rest-example/resources/res-plugtest-large-update.c index e48d08b5f..12c7d1e9f 100644 --- a/examples/er-rest-example/resources/res-plugtest-large-update.c +++ b/examples/er-rest-example/resources/res-plugtest-large-update.c @@ -37,6 +37,7 @@ */ #include +#include "sys/cc.h" #include "rest-engine.h" #include "er-coap.h" #include "er-plugtest.h" diff --git a/examples/example-shell/example-shell.c b/examples/example-shell/example-shell.c index 24b7c2a05..a8c7c74b6 100644 --- a/examples/example-shell/example-shell.c +++ b/examples/example-shell/example-shell.c @@ -66,7 +66,6 @@ PROCESS_THREAD(example_shell_process, ev, data) shell_file_init(); shell_httpd_init(); shell_irc_init(); - shell_netfile_init(); /*shell_ping_init();*/ /* uIP ping */ shell_power_init(); /*shell_profile_init();*/ diff --git a/examples/http-socket/Makefile b/examples/http-socket/Makefile new file mode 100644 index 000000000..b1d95efe0 --- /dev/null +++ b/examples/http-socket/Makefile @@ -0,0 +1,7 @@ +all: http-example +CONTIKI=../.. +MODULES += core/net/http-socket + +include $(CONTIKI)/Makefile.include + + diff --git a/examples/http-socket/http-example.c b/examples/http-socket/http-example.c new file mode 100644 index 000000000..21aff094d --- /dev/null +++ b/examples/http-socket/http-example.c @@ -0,0 +1,62 @@ +#include "contiki-net.h" +#include "http-socket.h" +#include "ip64-addr.h" + +#include + +static struct http_socket s; +static int bytes_received = 0; + +/*---------------------------------------------------------------------------*/ +PROCESS(http_example_process, "HTTP Example"); +AUTOSTART_PROCESSES(&http_example_process); +/*---------------------------------------------------------------------------*/ +static void +callback(struct http_socket *s, void *ptr, + http_socket_event_t e, + const uint8_t *data, uint16_t datalen) +{ + if(e == HTTP_SOCKET_ERR) { + printf("HTTP socket error\n"); + } else if(e == HTTP_SOCKET_TIMEDOUT) { + printf("HTTP socket error: timed out\n"); + } else if(e == HTTP_SOCKET_ABORTED) { + printf("HTTP socket error: aborted\n"); + } else if(e == HTTP_SOCKET_HOSTNAME_NOT_FOUND) { + printf("HTTP socket error: hostname not found\n"); + } else if(e == HTTP_SOCKET_CLOSED) { + printf("HTTP socket closed, %d bytes received\n", bytes_received); + } else if(e == HTTP_SOCKET_DATA) { + bytes_received += datalen; + printf("HTTP socket received %d bytes of data\n", datalen); + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(http_example_process, ev, data) +{ + static struct etimer et; + uip_ip4addr_t ip4addr; + uip_ip6addr_t ip6addr; + + PROCESS_BEGIN(); + + uip_ipaddr(&ip4addr, 8,8,8,8); + ip64_addr_4to6(&ip4addr, &ip6addr); + uip_nameserver_update(&ip6addr, UIP_NAMESERVER_INFINITE_LIFETIME); + + etimer_set(&et, CLOCK_SECOND * 60); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + http_socket_init(&s); + http_socket_get(&s, "http://www.contiki-os.org/", 0, 0, + callback, NULL); + + etimer_set(&et, CLOCK_SECOND); + while(1) { + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + etimer_reset(&et); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/ip64-router/Makefile b/examples/ip64-router/Makefile new file mode 100644 index 000000000..c44c677ad --- /dev/null +++ b/examples/ip64-router/Makefile @@ -0,0 +1,5 @@ +all: ip64-router +CONTIKI=../.. + +include $(CONTIKI)/Makefile.include + diff --git a/examples/ip64-router/ip64-router.c b/examples/ip64-router/ip64-router.c new file mode 100644 index 000000000..391b5038b --- /dev/null +++ b/examples/ip64-router/ip64-router.c @@ -0,0 +1,27 @@ +#include "contiki.h" +#include "contiki-net.h" +#include "ip64.h" +#include "net/netstack.h" + +/*---------------------------------------------------------------------------*/ +PROCESS(router_node_process, "Router node"); +AUTOSTART_PROCESSES(&router_node_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(router_node_process, ev, data) +{ + PROCESS_BEGIN(); + + /* Set us up as a RPL root node. */ + rpl_dag_root_init_dag(); + + /* Initialize the IP64 module so we'll start translating packets */ + ip64_init(); + + /* ... and do nothing more. */ + while(1) { + PROCESS_WAIT_EVENT(); + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/ip64-router/project-conf.h b/examples/ip64-router/project-conf.h new file mode 100644 index 000000000..e69de29bb diff --git a/examples/ipv6/rpl-collect/udp-sender.c b/examples/ipv6/rpl-collect/udp-sender.c index f216cbdcc..dd279cc7f 100644 --- a/examples/ipv6/rpl-collect/udp-sender.c +++ b/examples/ipv6/rpl-collect/udp-sender.c @@ -137,7 +137,7 @@ collect_common_send(void) /* Use parts of the IPv6 address as the parent address, in reversed byte order. */ parent.u8[LINKADDR_SIZE - 1] = nbr->ipaddr.u8[sizeof(uip_ipaddr_t) - 2]; parent.u8[LINKADDR_SIZE - 2] = nbr->ipaddr.u8[sizeof(uip_ipaddr_t) - 1]; - parent_etx = rpl_get_parent_rank((linkaddr_t *) uip_ds6_nbr_get_ll(nbr)) / 2; + parent_etx = rpl_get_parent_rank((uip_lladdr_t *) uip_ds6_nbr_get_ll(nbr)) / 2; } } rtmetric = dag->rank; diff --git a/examples/ipv6/slip-radio/no-framer.c b/examples/ipv6/slip-radio/no-framer.c index e3aed93b7..7f3447e97 100644 --- a/examples/ipv6/slip-radio/no-framer.c +++ b/examples/ipv6/slip-radio/no-framer.c @@ -109,8 +109,7 @@ parse(void) } packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr); packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending); - /* packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, frame.fcf.ack_required);*/ - packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq); + packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq); PRINTF("15.4-IN: %2X", frame.fcf.frame_type); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); diff --git a/examples/remote/Makefile b/examples/remote/Makefile new file mode 100644 index 000000000..289f7e330 --- /dev/null +++ b/examples/remote/Makefile @@ -0,0 +1,9 @@ +DEFINES+=PROJECT_CONF_H=\"project-conf.h\" +CONTIKI_PROJECT = remote-demo test-tsl2563 test-sht25 +CONTIKI_TARGET_SOURCEFILES += tsl2563.c sht25.c + +all: $(CONTIKI_PROJECT) + +CONTIKI = ../.. +CONTIKI_WITH_RIME = 1 +include $(CONTIKI)/Makefile.include diff --git a/examples/remote/Makefile.target b/examples/remote/Makefile.target new file mode 100644 index 000000000..fe36b5539 --- /dev/null +++ b/examples/remote/Makefile.target @@ -0,0 +1 @@ +TARGET = remote diff --git a/examples/remote/node-red/README.md b/examples/remote/node-red/README.md new file mode 100644 index 000000000..0e8fc7b74 --- /dev/null +++ b/examples/remote/node-red/README.md @@ -0,0 +1,38 @@ +Re-Mote + Node Red README +======================== + +A very basic example of how to use MQTT-Demo + Mosquitto + Node Red + +Install Mosquitto +----------------- +* Install and run [mosquitto](http://mosquitto.org/). Default configuration + options should work. + +Fire up a Re-Mote +----------------- +* Compile the MQTT demo example from `../../cc2538dk/mqtt-demo.c` following + the instructions of the README.md therein. +* Program your Re-Mote. +* If you are running mosquitto with `-v`, a few seconds later you should see + the Re-Mote connect, subscribe and start publishing. + +Deploy your Node Red +-------------------- +* Install and run [Node Red](https://github.com/node-red/node-red) as per the + instructions +* Open `mqtt-remote-demo.json` from this directory with your favourite text + editor, select all and copy. +* Once you have the opened the Node Red page, click the menu icon on the top + right and go to Import -> Clipboard. Paste the copied text. +* Double click the `MQTT input from Re-Mote` box on the top left. Set `Broker` + IP and port to those corresponding to your running mosquitto. +* Hit Deploy +* Optionally, export the flow to a file for future use + +Browse +------ +Fire up a browser and browse to `http:///remote` + +Do more cool stuff +------------------ +Come up with more cool flows and share! diff --git a/examples/remote/node-red/mqtt-remote-demo.json b/examples/remote/node-red/mqtt-remote-demo.json new file mode 100644 index 000000000..a121cc6c2 --- /dev/null +++ b/examples/remote/node-red/mqtt-remote-demo.json @@ -0,0 +1,2 @@ +[{"id":"d95a1e7f.43a","type":"mqtt-broker","broker":"localhost","port":"1883","clientid":""},{"id":"ddd5cc1c.723e18","type":"mqtt in","name":"MQTT input from Re-Mote","topic":"iot-2/evt/status/fmt/json","broker":"d95a1e7f.43a","x":131.11109924316406,"y":98.88890075683594,"z":"9b2868a4.2cef5","wires":[["12ea094e.3c2447"]]},{"id":"7728d120.25c64","type":"function","name":"Parse and Store Data","func":"var dat = msg.payload.d;\n\nif(dat) {\n var ret = [\n {\n name: \"Name\",\n value: dat.myName,\n unit: \"\",\n },\n {\n name: \"Seq #\",\n value: dat[\"Seq #\"],\n unit: \"\",\n },\n {\n name: \"Uptime\",\n value: dat[\"Uptime (sec)\"],\n unit: \"sec\",\n },\n {\n name: \"On-Chip Temp\",\n value: dat[\"On-Chip Temp (mC)\"],\n unit: \"C\",\n },\n {\n name: \"VDD/3\",\n value: dat[\"VDD3 (mV)\"],\n unit: \"V\",\n },\n {\n name: \"Parent RSSI\",\n value: dat[\"RSSI (dBm)\"],\n unit: \"dBm\",\n },\n ];\n \n context.ret = ret;\n} else {\n if(context.ret) {\n msg.has_data = true;\n msg.payload = context.ret;\n } else {\n msg.payload = \"No Data!\";\n }\n return [msg, msg];\n}\nreturn [msg, null];","outputs":"2","x":545.1110992431641,"y":346.38890075683594,"z":"9b2868a4.2cef5","wires":[["4249c5c.35b5c3c"],["dacab617.9133c8"]]},{"id":"12ea094e.3c2447","type":"json","name":"Convert to JS Object","x":305.61109924316406,"y":263.13890075683594,"z":"9b2868a4.2cef5","wires":[["7728d120.25c64"]]},{"id":"e5e8271c.99c2d","type":"http response","name":"Send HTTP Reponse","x":1252.2220611572266,"y":488.38890075683594,"z":"9b2868a4.2cef5","wires":[]},{"id":"4b2260f8.436808","type":"http in","name":"","url":"/remote","method":"get","x":327.11109924316406,"y":429.88890075683594,"z":"9b2868a4.2cef5","wires":[["8a3f88a9.ec77d8","7728d120.25c64"]]},{"id":"8a3f88a9.ec77d8","type":"debug","name":"","active":false,"console":"false","complete":"req","x":459.61109924316406,"y":522.3889007568359,"z":"9b2868a4.2cef5","wires":[]},{"id":"ac349e33.beb47","type":"template","name":"Render HTML from Data","field":"payload","template":"\n\n
    \n {{#payload}}\n
  • {{name}}: {{value}}{{#unit}} {{unit}}{{/unit}}
  • \n {{/payload}}\n
\n\n","x":1046.361099243164,"y":347.13890075683594,"z":"9b2868a4.2cef5","wires":[["e5e8271c.99c2d","530bf522.d773dc"]]},{"id":"4249c5c.35b5c3c","type":"debug","name":"","active":false,"console":"false","complete":"false","x":620.1110992431641,"y":247.88890075683594,"z":"9b2868a4.2cef5","wires":[]},{"id":"dacab617.9133c8","type":"switch","name":"","property":"has_data","rules":[{"t":"true"},{"t":"else"}],"checkall":"false","outputs":2,"x":765.1110992431641,"y":352.88890075683594,"z":"9b2868a4.2cef5","wires":[["124554c4.5b82b3","ac349e33.beb47"],["e5e8271c.99c2d"]]},{"id":"530bf522.d773dc","type":"debug","name":"","active":false,"console":"false","complete":"payload","x":1228.361099243164,"y":217.88890075683594,"z":"9b2868a4.2cef5","wires":[]},{"id":"124554c4.5b82b3","type":"debug","name":"","active":false,"console":"false","complete":"payload","x":898.1110992431641,"y":220.88890075683594,"z":"9b2868a4.2cef5","wires":[]}] + diff --git a/examples/remote/project-conf.h b/examples/remote/project-conf.h new file mode 100644 index 000000000..1f2f9adf4 --- /dev/null +++ b/examples/remote/project-conf.h @@ -0,0 +1,45 @@ +/* + * 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 NETSTACK_CONF_RDC nullrdc_driver + +#endif /* PROJECT_CONF_H_ */ + +/** @} */ diff --git a/examples/remote/remote-demo.c b/examples/remote/remote-demo.c new file mode 100644 index 000000000..929726871 --- /dev/null +++ b/examples/remote/remote-demo.c @@ -0,0 +1,196 @@ +/* + * 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 + * @{ + * + * \defgroup remote-examples Re-Mote Example Projects + * @{ + * + * \defgroup remote-demo Re-Mote Demo Project + * + * Example project demonstrating the Re-Mote functionality + * + * - Boot sequence: LEDs flashing (Red, then yellow, finally green) + * + * - etimer/clock : Every LOOP_INTERVAL clock ticks (LOOP_PERIOD secs) the LED + * defined as LEDS_PERIODIC will turn on + * - rtimer : Exactly LEDS_OFF_HYSTERISIS rtimer ticks later, + * LEDS_PERIODIC will turn back off + * - ADC sensors : On-chip VDD / 3, temperature, and Phidget sensor + * values are printed over UART periodically. + * - UART : Every LOOP_INTERVAL the Remote will print something over + * the UART. Receiving an entire line of text over UART (ending + * in \\r) will cause LEDS_SERIAL_IN to toggle + * - Radio comms : BTN_USER sends a rime broadcast. Reception of a rime + * packet will toggle LEDs defined as LEDS_RF_RX + * - Button : Keeping the button pressed will print a counter that + * increments every BUTTON_PRESS_EVENT_INTERVAL ticks + * - TMP102 : Built-in digital temperature sensor, every LOOP_INTERVAL + * clock ticks a sensor reading will be taken + * + * @{ + * + * \file + * Example demonstrating the Re-Mote platform + */ +#include "contiki.h" +#include "cpu.h" +#include "sys/etimer.h" +#include "sys/rtimer.h" +#include "dev/leds.h" +#include "dev/uart.h" +#include "dev/button-sensor.h" +#include "dev/remote-sensors.h" +#include "dev/watchdog.h" +#include "dev/serial-line.h" +#include "dev/sys-ctrl.h" +#include "net/rime/broadcast.h" +#include "dev/antenna-sw.h" +#include "dev/tmp102.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +#define LOOP_PERIOD 8 +#define LOOP_INTERVAL (CLOCK_SECOND * LOOP_PERIOD) +#define LEDS_OFF_HYSTERISIS ((RTIMER_SECOND * LOOP_PERIOD) >> 1) +#define LEDS_PERIODIC LEDS_BLUE +#define LEDS_BUTTON LEDS_RED +#define LEDS_SERIAL_IN LEDS_GREEN +#define LEDS_REBOOT LEDS_ALL +#define LEDS_RF_RX (LEDS_YELLOW | LEDS_RED) +#define BROADCAST_CHANNEL 129 + +#define BUTTON_PRESS_EVENT_INTERVAL (CLOCK_SECOND) +/*---------------------------------------------------------------------------*/ +static struct etimer et; +static struct rtimer rt; +static uint16_t counter, temperature; +/*---------------------------------------------------------------------------*/ +PROCESS(cc2538_demo_process, "cc2538 demo process"); +AUTOSTART_PROCESSES(&cc2538_demo_process); +/*---------------------------------------------------------------------------*/ +static void +broadcast_recv(struct broadcast_conn *c, const linkaddr_t *from) +{ + leds_toggle(LEDS_RF_RX); + printf("*** Received %u bytes from %u:%u: '0x%04x'\n", packetbuf_datalen(), + from->u8[0], from->u8[1], *(uint16_t *)packetbuf_dataptr()); +} +/*---------------------------------------------------------------------------*/ +static const struct broadcast_callbacks bc_rx = { broadcast_recv }; +static struct broadcast_conn bc; +/*---------------------------------------------------------------------------*/ +void +rt_callback(struct rtimer *t, void *ptr) +{ + leds_off(LEDS_PERIODIC); +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(cc2538_demo_process, ev, data) +{ + PROCESS_EXITHANDLER(broadcast_close(&bc)) + + PROCESS_BEGIN(); + + counter = 0; + broadcast_open(&bc, BROADCAST_CHANNEL, &bc_rx); + + /* Enable antenna */ + antenna_sw_select(ANTENNA_SW_SELECT_INTERNAL); + + button_sensor.configure(BUTTON_SENSOR_CONFIG_TYPE_INTERVAL, + BUTTON_PRESS_EVENT_INTERVAL); + + tmp102_init(); + + printf("Re-Mote test application, initial values:\n"); + + etimer_set(&et, LOOP_INTERVAL); + + while(1) { + + PROCESS_YIELD(); + + if(ev == PROCESS_EVENT_TIMER) { + leds_on(LEDS_PERIODIC); + + printf("-----------------------------------------\n" + "Counter = 0x%08x\n", counter); + + printf("VDD = %d mV\n", + vdd3_sensor.value(CC2538_SENSORS_VALUE_TYPE_CONVERTED)); + + printf("Temperature = %d mC\n", + cc2538_temp_sensor.value(CC2538_SENSORS_VALUE_TYPE_CONVERTED)); + + printf("Phidget ADC2 = %d raw\n", + phidget_sensor.value(PHIDGET_SENSORS_ADC2)); + + printf("Phidget ADC3 = %d raw\n", + phidget_sensor.value(PHIDGET_SENSORS_ADC3)); + + tmp102_read(&temperature); + printf("TMP102 sensor = %u mC\n", temperature); + + etimer_set(&et, LOOP_INTERVAL); + rtimer_set(&rt, RTIMER_NOW() + LEDS_OFF_HYSTERISIS, 1, + rt_callback, NULL); + counter++; + } else if(ev == sensors_event) { + if(data == &button_sensor) { + if(button_sensor.value(BUTTON_SENSOR_VALUE_TYPE_LEVEL) == + BUTTON_SENSOR_PRESSED_LEVEL) { + printf("Press\n"); + packetbuf_copyfrom(&counter, sizeof(counter)); + broadcast_send(&bc); + } else { + printf("Release\n"); + } + } + } else if(ev == serial_line_event_message) { + leds_toggle(LEDS_SERIAL_IN); + } else if(ev == button_press_duration_exceeded) { + printf("Button pressed for %d ticks [%u events]\n", + (*((uint8_t *)data) * BUTTON_PRESS_EVENT_INTERVAL), + button_sensor.value(BUTTON_SENSOR_VALUE_TYPE_PRESS_DURATION)); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + */ diff --git a/examples/rest-example/project-conf.h b/examples/remote/test-sht25.c similarity index 62% rename from examples/rest-example/project-conf.h rename to examples/remote/test-sht25.c index 7019c021a..3ff4316bd 100644 --- a/examples/rest-example/project-conf.h +++ b/examples/remote/test-sht25.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Swedish Institute of Computer Science. + * Copyright (c) 2015, Zolertia * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,35 +26,38 @@ * 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 quick program for testing the SHT25 temperature and humidity sensor + * \author + * Antonio Lignan + */ +#include +#include "contiki.h" +#include "dev/sht25.h" -#ifndef PROJECT_RPL_WEB_CONF_H_ -#define PROJECT_RPL_WEB_CONF_H_ +PROCESS(test_sht25_process, "SHT25 test"); +AUTOSTART_PROCESSES(&test_sht25_process); -/* Disabling RDC and CSMA for demo purposes. Core updates often - require more memory. */ -/* For projects, optimize memory and enable RDC and CSMA again. */ -#undef NETSTACK_CONF_RDC -#define NETSTACK_CONF_RDC nullrdc_driver +static struct etimer et; -#undef NETSTACK_CONF_MAC -#define NETSTACK_CONF_MAC nullmac_driver +PROCESS_THREAD(test_sht25_process, ev, data) +{ + int16_t temperature, humidity; -#ifndef QUEUEBUF_CONF_NUM -#define QUEUEBUF_CONF_NUM 6 -#endif + PROCESS_BEGIN(); + SENSORS_ACTIVATE(sht25); -#ifndef UIP_CONF_BUFFER_SIZE -#define UIP_CONF_BUFFER_SIZE 140 -#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_RPL_WEB_CONF_H_ */ + while(1) { + etimer_set(&et, CLOCK_SECOND); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + temperature = sht25.value(SHT25_VAL_TEMP); + printf("Temperature %d.%d ºC\n", temperature / 100, temperature % 100); + humidity = sht25.value(SHT25_VAL_HUM); + printf("Humidity %d.%d RH\n", humidity / 100, humidity % 100); + } + PROCESS_END(); +} diff --git a/examples/remote/test-tsl2563.c b/examples/remote/test-tsl2563.c new file mode 100644 index 000000000..88f3cbe2d --- /dev/null +++ b/examples/remote/test-tsl2563.c @@ -0,0 +1,85 @@ +/* + * 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. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup remote-examples + * @{ + * + * \defgroup remote-tsl2563-test Re-Mote TSL2563 light sensor test + * + * Demonstrates the use of the TSL2563 digital ambient light sensor + * @{ + * + * \file + * Driver for the Re-Mote external TSL2563 light sensor (Ziglet) + * + * \author + * Antonio Lignan + * Toni Lozano + */ + +#include +#include "contiki.h" +#include "dev/i2c.h" +#include "dev/tsl2563.h" + +#if 1 +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#define SENSOR_READ_INTERVAL (CLOCK_SECOND / 2) + +PROCESS(test_process, "Test TSL2563 light ziglet process"); +AUTOSTART_PROCESSES(&test_process); +/*---------------------------------------------------------------------------*/ +static struct etimer et; +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(test_process, ev, data) +{ + PROCESS_BEGIN(); + int light; + SENSORS_ACTIVATE(tsl2563); + + while(1) { + etimer_set(&et, SENSOR_READ_INTERVAL); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + light = tsl2563.value(TSL2563_VAL_READ); + PRINTF("Light = %u\n", light); + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ + diff --git a/examples/rest-example/Makefile b/examples/rest-example/Makefile deleted file mode 100644 index 745091636..000000000 --- a/examples/rest-example/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -all: rest-server-example coap-client-example - -ifndef TARGET -TARGET=sky -endif - -CONTIKI=../.. - -WITH_COAP = 1 - -CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" - -ifeq ($(WITH_COAP), 1) -CFLAGS += -DWITH_COAP -APPS += rest-coap -else -CFLAGS += -DWITH_HTTP -APPS += rest-http -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 aaaa::1/64 - -connect-router-cooja: $(CONTIKI)/tools/tunslip6 - sudo $(CONTIKI)/tools/tunslip6 -a 127.0.0.1 aaaa::1/64 diff --git a/examples/rest-example/README.md b/examples/rest-example/README.md deleted file mode 100644 index 1fd391653..000000000 --- a/examples/rest-example/README.md +++ /dev/null @@ -1,137 +0,0 @@ -REST example -============ - -Open a terminal and go to "/examples/rest-example/" directory. - -MAIN EXAMPLE: rest-server-example.c : A RESTful server example showing how to -use the REST layer to develop server-side applications (possible to run it over -either COAP or HTTP) To use COAP as the underlying application protocol, one -should define WITH_COAP = 1 in rest-example/Makefile. Otherwise, HTTP is used. -Look at the source code to see which resources are available. (check the -RESOURCE macros in the code). Each resource has a handler function which is -called by the REST layer to serve the request. (i.e. "helloworld" resource has -a handler function named "helloworld_handler" which is called when a web -service request is received for "helloworld" resource.) - - -To run REST examples in COOJA on Linux --------------------------------------------- - -Accessing the server from outside: - -1. Start COOJA and load the simulation "rest-server-example.csc" by the following command. - - make TARGET=cooja rest-server-example.csc - -2. After loading the COOJA file, open another another terminal pointing to the - same directory and connect to the COOJA simulation using tunslip6: - - make connect-router-cooja - -3. You need to use a COAP or HTTP client to interact with the COOJA nodes - running REST code. In this setting, two servers are available: IP addresses - are aaaa::0212:7402:0002:0202 and aaaa::0212:7403:0003:0303. COAP uses - 61616, whereas HTTP uses 8080 port in default configuration. First, ping - the COOJA nodes to test the connectivity. - - ping6 aaaa::0212:7402:0002:0202 - ping6 aaaa::0212:7403:0003:0303 - -HTTP Examples -------------- - -You can use curl as an http client to interact with the COOJA motes running -REST code. - - curl -H "User-Agent: curl" aaaa::0212:7402:0002:0202:8080/helloworld #get helloworld plain text - curl -H "User-Agent: curl" aaaa::0212:7402:0002:0202:8080/led?color=green -d mode=off -i #turn off the green led - curl -H "User-Agent: curl" aaaa::0212:7402:0002:0202:8080/.well-known/core -i - curl -X POST -H "User-Agent: curl" aaaa::0212:7402:0002:0202:8080/helloworld #method not allowed - -COAP Examples -------------- - -You should run a COAP client on your computer. You can use the URLs and methods -provided above in HTTP examples to test the COAP Server. For example, Matthias -Kovatsch has developed a CoAP Firefox plug-in which is accessible via -[http://people.inf.ethz.ch/mkovatsc/#pro](http://people.inf.ethz.ch/mkovatsc/#pro) - -Accessing the server inside the sensor network: (Note: Provided only for COAP -implementation) Start COOJA and load the simulation -"coap-client-server-example.csc" by the following command. - - make TARGET=cooja coap-client-server-example.csc - -coap-client-server-example.csc : Runs rest-server-example.c as the server (over -COAP) (IP:aaaa::0212:7401:0001:0101) in one node and coap-client-example.c as -the client (IP: aaaa::0212:7402:0002:0202) in another node. Client -periodically accesses resources of server and prints the payload. - -Note: If the generated binary is bigger than the MOTE code size, then you will -get a "region text is full" error. Right now, REST+HTTP example uses (Contiki -& ContikiMAC & uIPv6 & RPL & HTTP Server & REST Layer) which does not fit in -Tmote Sky memory. To save same code space and make the example fit, you can -define static routes rather than using RPL or use nullrdc rather than -ContikiMAC. If border router does not fit, then first try to update the -Makefile of border router in /examples/ipv6/rpl-border-router by -setting WITH_WEBSERVER=0. - -To run REST server on real nodes (i.e. tmote sky) --------------------------------------------- - -1. Program the nodes with the rest-server-example - - make TARGET=sky rest-server-example.upload - -2. Disconnect the nodes and program one node with the RPL border router - - cd ../ipv6/rpl-border-router && make TARGET=sky border-router.upload - -3. Connect to the border router using tunslip6: - - make connect-router - -4. Reconnect the motes, open new terminal for each mote and run the following - command to note their IP addresses (after running the command reset the - corresponding mote to get IP address printed) - - make login TARGET=sky MOTE=2 #Shows the prints for first mote - make login TARGET=sky MOTE=3 #For second mote and so on. - -5. Test the connectivity by pinging them. - - ping6 - -6. Remaining parts are the same with the COOJA example. (i.e. if it is a COAP - Server, it's available at :61616) - - -To run REST server with minimal-net on Linux --------------------------------------------- -1. Compile with minimal-net setting. - - make rest-server-example TARGET=minimal-net - -2. Run the generated executable with sudo and note the IP address of the server - which will be printed right after. - - sudo ./rest-server-example.minimal-net - -3. How to access and test the server is same with the other settings. (i.e. if - it is a COAP Server, it's available at :61616 and if - it's a HTTP Server it is available at :8080) - -TODO ----- - -- Better option handling needed - ex: critical options are not differentiated - for now. Need to add support for some such as Tokens. Also, C/E difference - should be added. -- Reilable message sending is missing. i.e. client example should resend - request in case ACK does not arrive. Same for server pushing (in case of - subscriptions) -- Add Block transfer example -- Add Subscription example -- Add an Android/Java COAP Client to Contikiprojects to be able to interact - with Contiki. -- COAP-specific Method Codes diff --git a/examples/rest-example/coap-client-example.c b/examples/rest-example/coap-client-example.c deleted file mode 100644 index e5772f103..000000000 --- a/examples/rest-example/coap-client-example.c +++ /dev/null @@ -1,123 +0,0 @@ -#include -#include -#include -#include "contiki.h" -#include "contiki-net.h" -#include "rest.h" -#include "buffer.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 - -#define SERVER_NODE(ipaddr) uip_ip6addr(ipaddr, 0xfe80, 0, 0, 0, 0x0212, 0x7401, 0x0001, 0x0101) -#define LOCAL_PORT 61617 -#define REMOTE_PORT 61616 - -char temp[100]; -int xact_id; -static uip_ipaddr_t server_ipaddr; -static struct uip_udp_conn *client_conn; -static struct etimer et; -#define MAX_PAYLOAD_LEN 100 - -#define NUMBER_OF_URLS 3 -char* service_urls[NUMBER_OF_URLS] = {"light", ".well-known/core", "helloworld"}; - -static void -response_handler(coap_packet_t* response) -{ - uint16_t payload_len = 0; - uint8_t* payload = NULL; - payload_len = coap_get_payload(response, &payload); - - PRINTF("Response transaction id: %u", response->tid); - if (payload) { - memcpy(temp, payload, payload_len); - temp[payload_len] = 0; - PRINTF(" payload: %s\n", temp); - } -} - -static void -send_data(void) -{ - char buf[MAX_PAYLOAD_LEN]; - - if (init_buffer(COAP_DATA_BUFF_SIZE)) { - int data_size = 0; - int service_id = random_rand() % NUMBER_OF_URLS; - coap_packet_t* request = (coap_packet_t*)allocate_buffer(sizeof(coap_packet_t)); - init_packet(request); - - coap_set_method(request, COAP_GET); - request->tid = xact_id++; - request->type = MESSAGE_TYPE_CON; - coap_set_header_uri(request, service_urls[service_id]); - - data_size = serialize_packet(request, buf); - - PRINTF("Client sending request to:["); - PRINT6ADDR(&client_conn->ripaddr); - PRINTF("]:%u/%s\n", (uint16_t)REMOTE_PORT, service_urls[service_id]); - uip_udp_packet_send(client_conn, buf, data_size); - - delete_buffer(); - } -} - -static void -handle_incoming_data() -{ - PRINTF("Incoming packet size: %u \n", (uint16_t)uip_datalen()); - if (init_buffer(COAP_DATA_BUFF_SIZE)) { - if (uip_newdata()) { - coap_packet_t* response = (coap_packet_t*)allocate_buffer(sizeof(coap_packet_t)); - if (response) { - parse_message(response, uip_appdata, uip_datalen()); - response_handler(response); - } - } - delete_buffer(); - } -} - -PROCESS(coap_client_example, "COAP Client Example"); -AUTOSTART_PROCESSES(&coap_client_example); - -PROCESS_THREAD(coap_client_example, ev, data) -{ - PROCESS_BEGIN(); - - SERVER_NODE(&server_ipaddr); - - /* new connection with server */ - client_conn = udp_new(&server_ipaddr, UIP_HTONS(REMOTE_PORT), NULL); - udp_bind(client_conn, UIP_HTONS(LOCAL_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)); - - etimer_set(&et, 5 * CLOCK_SECOND); - while(1) { - PROCESS_YIELD(); - if (etimer_expired(&et)) { - send_data(); - etimer_reset(&et); - } else if (ev == tcpip_event) { - handle_incoming_data(); - } - } - - PROCESS_END(); -} diff --git a/examples/rest-example/coap-client-server-example.csc b/examples/rest-example/coap-client-server-example.csc deleted file mode 100644 index bee90493b..000000000 --- a/examples/rest-example/coap-client-server-example.csc +++ /dev/null @@ -1,147 +0,0 @@ - - - [CONTIKI_DIR]/tools/cooja/apps/mrm - [CONTIKI_DIR]/tools/cooja/apps/mspsim - [CONTIKI_DIR]/tools/cooja/apps/avrora - [CONTIKI_DIR]/tools/cooja/apps/serial_socket - - coap-client-server-example - -2147483648 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 100.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - sky1 - CoapServer - [CONTIKI_DIR]/examples/rest-example/rest-server-example.c - make rest-server-example.sky TARGET=sky - [CONTIKI_DIR]/examples/rest-example/rest-server-example.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 - CoapClient - [CONTIKI_DIR]/examples/rest-example/coap-client-example.c - make coap-client-example.sky TARGET=sky - [CONTIKI_DIR]/examples/rest-example/coap-client-example.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 - 54.5338749671737 - 36.41934631024719 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - sky1 - - - - - org.contikios.cooja.interfaces.Position - 49.41583327244326 - 52.00647916206431 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - sky2 - - - - org.contikios.cooja.plugins.SimControl - 318 - 2 - 172 - 0 - 0 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.AddressVisualizerSkin - 3.686023978928717 0.0 0.0 3.686023978928717 -20.14794638096936 -127.69712925102564 - - 271 - 0 - 211 - 666 - 41 - - - org.contikios.cooja.plugins.LogListener - - - - 1263 - 1 - 199 - 0 - 339 - - - org.contikios.cooja.plugins.TimeLine - - 0 - 1 - - - - 125 - 500.0 - - 1263 - 3 - 150 - 0 - 538 - - - diff --git a/examples/rest-example/rest-server-example.c b/examples/rest-example/rest-server-example.c deleted file mode 100644 index 24b33ff15..000000000 --- a/examples/rest-example/rest-server-example.c +++ /dev/null @@ -1,180 +0,0 @@ -#include -#include -#include -#include "contiki.h" -#include "contiki-net.h" -#include "rest.h" - -#if defined (PLATFORM_HAS_LIGHT) -#include "dev/light-sensor.h" -#endif -#if defined (PLATFORM_HAS_BATT) -#include "dev/battery-sensor.h" -#endif -#if defined (PLATFORM_HAS_SHT11) -#include "dev/sht11/sht11-sensor.h" -#endif -#if defined (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 - -char temp[100]; - -/* Resources are defined by RESOURCE macro, signature: resource name, the http methods it handles and its url*/ -RESOURCE(helloworld, METHOD_GET, "helloworld"); - -/* For each resource defined, there corresponds an handler method which should be defined too. - * Name of the handler method should be [resource name]_handler - * */ -void -helloworld_handler(REQUEST* request, RESPONSE* response) -{ - sprintf(temp,"Hello World!\n"); - - rest_set_header_content_type(response, TEXT_PLAIN); - rest_set_response_payload(response, (uint8_t*)temp, strlen(temp)); -} - -RESOURCE(discover, METHOD_GET, ".well-known/core"); -void -discover_handler(REQUEST* request, RESPONSE* response) -{ - char temp[100]; - int index = 0; - index += sprintf(temp + index, "%s,", ";n=\"HelloWorld\""); -#if defined (PLATFORM_HAS_LEDS) - index += sprintf(temp + index, "%s,", ";n=\"LedControl\""); -#endif -#if defined (PLATFORM_HAS_LIGHT) - index += sprintf(temp + index, "%s", ";n=\"Light\""); -#endif - - rest_set_response_payload(response, (uint8_t*)temp, strlen(temp)); - rest_set_header_content_type(response, APPLICATION_LINK_FORMAT); -} - -#if defined (PLATFORM_HAS_LIGHT) -uint16_t light_photosynthetic; -uint16_t light_solar; - -void -read_light_sensor(uint16_t* light_1, uint16_t* light_2) -{ - *light_1 = light_sensor.value(LIGHT_SENSOR_PHOTOSYNTHETIC); - *light_2 = light_sensor.value(LIGHT_SENSOR_TOTAL_SOLAR); -} - -/*A simple getter example. Returns the reading from light sensor with a simple etag*/ -RESOURCE(light, METHOD_GET, "light"); -void -light_handler(REQUEST* request, RESPONSE* response) -{ - read_light_sensor(&light_photosynthetic, &light_solar); - sprintf(temp,"%u;%u", light_photosynthetic, light_solar); - - char etag[4] = "ABCD"; - rest_set_header_content_type(response, TEXT_PLAIN); - rest_set_header_etag(response, etag, sizeof(etag)); - rest_set_response_payload(response, temp, strlen(temp)); -} -#endif /*PLATFORM_HAS_LIGHT*/ - -#if defined (PLATFORM_HAS_LEDS) -/*A simple actuator example, depending on the color query parameter and post variable mode, corresponding led is activated or deactivated*/ -RESOURCE(led, METHOD_POST | METHOD_PUT , "led"); - -void -led_handler(REQUEST* request, RESPONSE* response) -{ - char color[10]; - char mode[10]; - uint8_t led = 0; - int success = 1; - - if (rest_get_query_variable(request, "color", color, 10)) { - PRINTF("color %s\n", color); - - if (!strcmp(color,"red")) { - led = LEDS_RED; - } else if(!strcmp(color,"green")) { - led = LEDS_GREEN; - } else if ( !strcmp(color,"blue") ) { - led = LEDS_BLUE; - } else { - success = 0; - } - } else { - success = 0; - } - - if (success && rest_get_post_variable(request, "mode", mode, 10)) { - PRINTF("mode %s\n", mode); - - if (!strcmp(mode, "on")) { - leds_on(led); - } else if (!strcmp(mode, "off")) { - leds_off(led); - } else { - success = 0; - } - } else { - success = 0; - } - - if (!success) { - rest_set_response_status(response, BAD_REQUEST_400); - } -} - - -/*A simple actuator example. Toggles the red led*/ -RESOURCE(toggle, METHOD_GET | METHOD_PUT | METHOD_POST, "toggle"); -void -toggle_handler(REQUEST* request, RESPONSE* response) -{ - leds_toggle(LEDS_RED); -} -#endif /*defined (CONTIKI_HAS_LEDS)*/ - - -PROCESS(rest_server_example, "Rest Server Example"); -AUTOSTART_PROCESSES(&rest_server_example); - -PROCESS_THREAD(rest_server_example, ev, data) -{ - PROCESS_BEGIN(); - -#ifdef WITH_COAP - PRINTF("COAP Server\n"); -#else - PRINTF("HTTP Server\n"); -#endif - - rest_init(); - -#if defined (PLATFORM_HAS_LIGHT) - SENSORS_ACTIVATE(light_sensor); - rest_activate_resource(&resource_light); -#endif -#if defined (PLATFORM_HAS_LEDS) - rest_activate_resource(&resource_led); - rest_activate_resource(&resource_toggle); -#endif /*defined (PLATFORM_HAS_LEDS)*/ - - rest_activate_resource(&resource_helloworld); - rest_activate_resource(&resource_discover); - - PROCESS_END(); -} diff --git a/examples/rest-example/rest-server-example.csc b/examples/rest-example/rest-server-example.csc deleted file mode 100644 index 3b598c66a..000000000 --- a/examples/rest-example/rest-server-example.csc +++ /dev/null @@ -1,185 +0,0 @@ - - - [CONTIKI_DIR]/tools/cooja/apps/mrm - [CONTIKI_DIR]/tools/cooja/apps/mspsim - [CONTIKI_DIR]/tools/cooja/apps/avrora - [CONTIKI_DIR]/tools/cooja/apps/serial_socket - - REST with RPL router - -2147483648 - 123456 - 1000000 - - org.contikios.cooja.radiomediums.UDGM - 50.0 - 50.0 - 1.0 - 1.0 - - - 40000 - - - org.contikios.cooja.mspmote.SkyMoteType - rplroot - Sky RPL Root - [CONTIKI_DIR]/examples/ipv6/rpl-border-router/border-router.c - make border-router.sky TARGET=sky - [CONTIKI_DIR]/examples/ipv6/rpl-border-router/border-router.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 - skyweb - Rest - [CONTIKI_DIR]/examples/rest-example/rest-server-example.c - make rest-server-example.sky TARGET=sky - [CONTIKI_DIR]/examples/rest-example/rest-server-example.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 - 33.260163187353555 - 30.643217359962595 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 1 - - rplroot - - - - - org.contikios.cooja.interfaces.Position - 62.239287566073514 - 34.43810269527116 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 2 - - skyweb - - - - - org.contikios.cooja.interfaces.Position - 47.68359039801751 - 47.26544238238854 - 0.0 - - - org.contikios.cooja.mspmote.interfaces.MspMoteID - 3 - - skyweb - - - - org.contikios.cooja.plugins.SimControl - 259 - 1 - 179 - 0 - 0 - - - org.contikios.cooja.plugins.Visualizer - - org.contikios.cooja.plugins.skins.IDVisualizerSkin - org.contikios.cooja.plugins.skins.UDGMVisualizerSkin - org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin - org.contikios.cooja.plugins.skins.AttributeVisualizerSkin - 10.505309204322225 0.0 0.0 10.505309204322225 -249.89475921566975 -141.01191150973983 - - 819 - 5 - 563 - 35 - 306 - - - org.contikios.cooja.plugins.LogListener - - - - 762 - 0 - 326 - 36 - 296 - - - org.contikios.cooja.plugins.RadioLogger - - 150 - - - 815 - 4 - 385 - 255 - 8 - - - SerialSocketServer - 0 - 422 - 3 - 74 - 1234 - 93 - - - org.contikios.cooja.plugins.TimeLine - - 0 - 1 - - - - - 125 - 25.49079397896416 - - 1624 - 2 - 252 - 166 - 699 - - - diff --git a/examples/rime/Makefile b/examples/rime/Makefile index e35d8f1e9..f46fc2fbf 100644 --- a/examples/rime/Makefile +++ b/examples/rime/Makefile @@ -1,7 +1,7 @@ CONTIKI = ../.. all: example-abc example-mesh example-collect example-trickle example-polite \ - example-rudolph0 example-rudolph1 example-rudolph2 example-rucb \ + example-rudolph1 example-rudolph2 example-rucb \ example-runicast example-unicast example-neighbors CONTIKI_WITH_RIME = 1 diff --git a/examples/rime/example-rudolph0.c b/examples/rime/example-rudolph0.c deleted file mode 100644 index 196340f1c..000000000 --- a/examples/rime/example-rudolph0.c +++ /dev/null @@ -1,150 +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 - * Testing the rudolph0 code in Rime - * \author - * Adam Dunkels - */ - -#include "contiki.h" -#include "cfs/cfs.h" -#include "net/rime/rudolph0.h" - -#include "dev/button-sensor.h" - -#include "dev/leds.h" - -#include - -#define FILESIZE 200 - -/*---------------------------------------------------------------------------*/ -PROCESS(example_rudolph0_process, "Rudolph0 example"); -AUTOSTART_PROCESSES(&example_rudolph0_process); -/*---------------------------------------------------------------------------*/ -static void -write_chunk(struct rudolph0_conn *c, int offset, int flag, - uint8_t *data, int datalen) -{ - int fd; - - if(flag == RUDOLPH0_FLAG_NEWFILE) { - /* printf("+++ rudolph0 new file incoming at %lu\n", clock_time());*/ - leds_on(LEDS_RED); - fd = cfs_open("codeprop.out", CFS_WRITE); - } else { - fd = cfs_open("codeprop.out", CFS_WRITE + CFS_APPEND); - } - - if(datalen > 0) { - int ret; - cfs_seek(fd, offset, CFS_SEEK_SET); - ret = cfs_write(fd, data, datalen); - /* printf("write_chunk wrote %d bytes at %d, %d\n", ret, offset, (unsigned char)data[0]);*/ - } - - cfs_close(fd); - - if(flag == RUDOLPH0_FLAG_LASTCHUNK) { - int i; - /* printf("+++ rudolph0 entire file received at %lu\n", clock_time());*/ - leds_off(LEDS_RED); - leds_on(LEDS_YELLOW); - fd = cfs_open("hej", CFS_READ); - for(i = 0; i < FILESIZE; ++i) { - unsigned char buf; - cfs_read(fd, &buf, 1); - if(buf != (unsigned char)i) { - printf("error: diff at %d, %d != %d\n", i, i, buf); - break; - } - } - cfs_close(fd); - } -} -static int -read_chunk(struct rudolph0_conn *c, int offset, uint8_t *to, int maxsize) -{ - int fd; - int ret; - - fd = cfs_open("hej", CFS_READ); - - cfs_seek(fd, offset, CFS_SEEK_SET); - ret = cfs_read(fd, to, maxsize); - /* printf("read_chunk %d bytes at %d, %d\n", ret, offset, (unsigned char)to[0]);*/ - cfs_close(fd); - return ret; -} -const static struct rudolph0_callbacks rudolph0_call = {write_chunk, - read_chunk}; -static struct rudolph0_conn rudolph0; -/*---------------------------------------------------------------------------*/ -PROCESS_THREAD(example_rudolph0_process, ev, data) -{ - static int fd; - - PROCESS_EXITHANDLER(rudolph0_close(&rudolph0);) - - PROCESS_BEGIN(); - - PROCESS_PAUSE(); - - - rudolph0_open(&rudolph0, 138, &rudolph0_call); - SENSORS_ACTIVATE(button_sensor); - - while(1) { - PROCESS_WAIT_EVENT_UNTIL(ev == sensors_event && - data == &button_sensor); - { - int i; - - fd = cfs_open("hej", CFS_WRITE); - for(i = 0; i < FILESIZE; i++) { - unsigned char buf = i; - cfs_write(fd, &buf, 1); - } - cfs_close(fd); - } - rudolph0_send(&rudolph0, CLOCK_SECOND / 4); - - PROCESS_WAIT_EVENT_UNTIL(ev == sensors_event && - data == &button_sensor); - rudolph0_stop(&rudolph0); - - } - PROCESS_END(); -} -/*---------------------------------------------------------------------------*/ diff --git a/examples/seedeye/powerswitch/Makefile b/examples/seedeye/powerswitch/Makefile index 6e12ccc81..683da4226 100644 --- a/examples/seedeye/powerswitch/Makefile +++ b/examples/seedeye/powerswitch/Makefile @@ -7,42 +7,8 @@ all: remotepowerswitch CONTIKI=../../../ CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" -WITH_COAP=13 - -# REST framework, requires WITH_COAP -ifeq ($(WITH_COAP), 13) -${info INFO: compiling with CoAP-13} -CFLAGS += -DWITH_COAP=13 -CFLAGS += -DREST=coap_rest_implementation -CFLAGS += -DUIP_CONF_TCP=0 -APPS += er-coap-13 -else ifeq ($(WITH_COAP), 12) -${info INFO: compiling with CoAP-12} -CFLAGS += -DWITH_COAP=12 -CFLAGS += -DREST=coap_rest_implementation -CFLAGS += -DUIP_CONF_TCP=0 -APPS += er-coap-12 -else ifeq ($(WITH_COAP), 7) -${info INFO: compiling with CoAP-08} -CFLAGS += -DWITH_COAP=7 -CFLAGS += -DREST=coap_rest_implementation -CFLAGS += -DUIP_CONF_TCP=0 -APPS += er-coap-07 -else ifeq ($(WITH_COAP), 3) -${info INFO: compiling with CoAP-03} -CFLAGS += -DWITH_COAP=3 -CFLAGS += -DREST=coap_rest_implementation -CFLAGS += -DUIP_CONF_TCP=0 -APPS += er-coap-03 -else -${info INFO: compiling with HTTP} -CFLAGS += -DWITH_HTTP -CFLAGS += -DREST=http_rest_implementation -CFLAGS += -DUIP_CONF_TCP=1 -APPS += er-http-engine -endif - -APPS += erbium +APPS += er-coap +APPS += rest-engine CONTIKI_WITH_IPV6 = 1 include $(CONTIKI)/Makefile.include diff --git a/examples/seedeye/powerswitch/remotepowerswitch.c b/examples/seedeye/powerswitch/remotepowerswitch.c index 3bcfb10f3..04d3ea3c5 100644 --- a/examples/seedeye/powerswitch/remotepowerswitch.c +++ b/examples/seedeye/powerswitch/remotepowerswitch.c @@ -1,13 +1,13 @@ /* * Remote Power Switch Example for the Seed-Eye Board * Copyright (c) 2013, Giovanni Pellerano - * + * * Ownership: Scuola Superiore Sant'Anna (http://www.sssup.it) and * Consorzio Nazionale Interuniversitario per le Telecomunicazioni * (http://www.cnit.it). * * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -33,7 +33,7 @@ * SUCH DAMAGE. * */ - + /** * \addtogroup Remote Power Switch Example for the Seed-Eye Board * @@ -55,20 +55,21 @@ #include "contiki.h" #include "contiki-net.h" -#include "erbium.h" +#include "rest-engine.h" #include "dev/leds.h" #include -RESOURCE(toggle, METHOD_GET | METHOD_PUT | METHOD_POST, "actuators/powerswitch", "title=\"Red LED\";rt=\"Control\""); void toggle_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) { leds_toggle(LEDS_RED); - + PORTEbits.RE0 = !PORTEbits.RE0; } +RESOURCE(resource_toggle, "title=\"Red LED\";rt=\"Control\"", toggle_handler, toggle_handler, toggle_handler, NULL); + PROCESS(remote_power_switch, "Remote Power Switch"); @@ -79,11 +80,11 @@ PROCESS_THREAD(remote_power_switch, ev, data) PROCESS_BEGIN(); rest_init_engine(); - + TRISEbits.TRISE0 = 0; PORTEbits.RE0 = 0; - rest_activate_resource(&resource_toggle); + rest_activate_resource(&resource_toggle, "actuators/powerswitch"); while(1) { PROCESS_WAIT_EVENT(); diff --git a/examples/sky-shell/sky-upload.c b/examples/sky-shell/sky-upload.c index 703b450bc..7d4b221ac 100644 --- a/examples/sky-shell/sky-upload.c +++ b/examples/sky-shell/sky-upload.c @@ -58,7 +58,6 @@ PROCESS_THREAD(test_shell_process, ev, data) shell_coffee_init(); shell_exec_init(); shell_file_init(); - shell_netfile_init(); shell_ps_init(); shell_rime_init(); shell_rime_netcmd_init(); diff --git a/examples/sky/sky-collect.c b/examples/sky/sky-collect.c index d49dc8184..04cedf696 100644 --- a/examples/sky/sky-collect.c +++ b/examples/sky/sky-collect.c @@ -38,6 +38,7 @@ */ #include "contiki.h" +#include "sys/cc.h" #include "net/netstack.h" #include "net/rime/rime.h" #include "net/rime/collect.h" @@ -120,8 +121,6 @@ PROCESS_THREAD(depth_blink_process, ev, data) PROCESS_END(); } /*---------------------------------------------------------------------------*/ -#define MAX(a, b) ((a) > (b)? (a): (b)) -#define MIN(a, b) ((a) < (b)? (a): (b)) struct spectrum { int channel[16]; }; diff --git a/examples/sky/tcprudolph0.c b/examples/sky/tcprudolph0.c deleted file mode 100644 index 1dfea085f..000000000 --- a/examples/sky/tcprudolph0.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * 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. - * - */ - -#include -#include - -#include "contiki.h" -#include "sys/etimer.h" -#include "loader/elfloader.h" - -#include "net/ip/uip.h" - -#include "dev/leds.h" - -#include "cfs/cfs.h" - -#include "codeprop.h" - -#include "net/rime/rudolph0.h" - -#include - -#define DEBUG 0 -#if DEBUG -#include -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif - -PROCESS(tcp_loader_process, "TCP loader"); -AUTOSTART_PROCESSES(&tcp_loader_process); - -static -struct codeprop_state { - uint16_t addr; - uint16_t len; - struct pt tcpthread_pt; - int fd; -} s; - -static char msg[30 + 10]; - -static struct rudolph0_conn rudolph0; - -/*---------------------------------------------------------------------*/ -static int -start_program(void) -{ - /* Link, load, and start new program. */ - int ret; - s.fd = cfs_open("codeprop.out", CFS_READ); - ret = elfloader_load(s.fd); - - /* XXX: Interrupts seems to be turned off a little too long during the - ELF loading process, so we need to "manually" trigger a timer - interrupt here. */ - TACCR1 = TAR + 1000; - - if(ret == ELFLOADER_OK) { - sprintf(msg, "ok\n"); - PRINTF("Ok, starting new program.\n"); - /* Start processes. */ - autostart_start(elfloader_autostart_processes); - } else { - sprintf(msg, "err %d %s", ret, elfloader_unknown); - PRINTF("Error: '%s'.\n", msg); - } - cfs_close(s.fd); - return ret; -} -/*---------------------------------------------------------------------*/ -static -PT_THREAD(recv_tcpthread(struct pt *pt)) -{ - PT_BEGIN(pt); - - /* Read the header. */ - PT_WAIT_UNTIL(pt, uip_newdata() && uip_datalen() > 0); - - if(uip_datalen() < sizeof(struct codeprop_tcphdr)) { - PRINTF(("codeprop: header not found in first tcp segment\n")); - uip_abort(); - goto thread_done; - } - - /* Kill old program. */ - rudolph0_stop(&rudolph0); - /* elfloader_unload();*/ - - s.len = uip_htons(((struct codeprop_tcphdr *)uip_appdata)->len); - s.addr = 0; - uip_appdata += sizeof(struct codeprop_tcphdr); - uip_len -= sizeof(struct codeprop_tcphdr); - - s.fd = cfs_open("codeprop.out", CFS_WRITE); - cfs_close(s.fd); - /* xmem_erase(XMEM_ERASE_UNIT_SIZE, EEPROMFS_ADDR_CODEPROP);*/ - - /* Read the rest of the data. */ - do { - leds_toggle(LEDS_RED); - if(uip_len > 0) { - s.fd = cfs_open("codeprop.out", CFS_WRITE + CFS_APPEND); - cfs_seek(s.fd, s.addr, CFS_SEEK_SET); - /* xmem_pwrite(uip_appdata, uip_len, EEPROMFS_ADDR_CODEPROP + s.addr);*/ - cfs_write(s.fd, uip_appdata, uip_len); - cfs_close(s.fd); - - PRINTF("Wrote %d bytes to file\n", uip_len); - s.addr += uip_len; - } - if(s.addr < s.len) { - PT_YIELD_UNTIL(pt, uip_newdata()); - } - } while(s.addr < s.len); - leds_off(LEDS_RED); - -#if DEBUG - { - int i, fd, j; - printf("Contents of file:\n"); - fd = cfs_open("codeprop.out", CFS_READ); - j = 0; - printf("\n0x%04x: ", 0); - for(i = 0; i < s.len; ++i) { - unsigned char byte; - cfs_read(fd, &byte, 1); - printf("0x%02x, ", byte); - ++j; - if(j == 8) { - printf("\n0x%04x: ", i + 1); - j = 0; - } - clock_delay(400); - } - cfs_close(fd); - } -#endif - - int ret; - - ret = start_program(); - -#if CONTIKI_TARGET_NETSIM - rudolph0_send(&rudolph0, CLOCK_SECOND / 4); -#else /* CONTIKI_TARGET_NETSIM */ - if(ret == ELFLOADER_OK) { - /* Propagate program. */ - rudolph0_send(&rudolph0, CLOCK_SECOND / 4); - } -#endif /* CONTIKI_TARGET_NETSIM */ - - /* Return "ok" message. */ - do { - ret = strlen(msg); - uip_send(msg, ret); - PT_WAIT_UNTIL(pt, uip_acked() || uip_rexmit() || uip_closed()); - } while(uip_rexmit()); - - /* Close the connection. */ - uip_close(); - - - thread_done:; - PT_END(pt); -} -/*---------------------------------------------------------------------*/ -static void -write_chunk(struct rudolph0_conn *c, int offset, int flag, - uint8_t *data, int datalen) -{ - int fd; - - leds_toggle(LEDS_YELLOW); - - if(flag == RUDOLPH0_FLAG_NEWFILE) { - printf("+++ rudolph0 new file incoming at %u\n", clock_time()); - fd = cfs_open("codeprop.out", CFS_WRITE); - - if(elfloader_autostart_processes != NULL) { - PRINTF("Stopping old programs.\n"); - autostart_exit(elfloader_autostart_processes); - elfloader_autostart_processes = NULL; - } - - } else { - fd = cfs_open("codeprop.out", CFS_WRITE + CFS_APPEND); - } - - if(datalen > 0) { - int ret; - cfs_seek(fd, offset, CFS_SEEK_SET); - ret = cfs_write(fd, data, datalen); - /* printf("write_chunk wrote %d bytes at %d, %d\n", ret, offset, (unsigned char)data[0]);*/ - } - - cfs_close(fd); - - if(flag == RUDOLPH0_FLAG_LASTCHUNK) { - printf("+++ rudolph0 entire file received at %u\n", clock_time()); - start_program(); - leds_off(LEDS_YELLOW); - } -} -static int -read_chunk(struct rudolph0_conn *c, int offset, uint8_t *to, int maxsize) -{ - int fd; - int ret; - - leds_toggle(LEDS_GREEN); - - fd = cfs_open("codeprop.out", CFS_READ); - - cfs_seek(fd, offset, CFS_SEEK_SET); - ret = cfs_read(fd, to, maxsize); - /* printf("read_chunk %d bytes at %d, %d\n", ret, offset, (unsigned char)to[0]);*/ - if(ret < maxsize) { - leds_off(LEDS_GREEN); - } - cfs_close(fd); - return ret; -} -const static struct rudolph0_callbacks rudolph0_call = {write_chunk, - read_chunk}; -/*---------------------------------------------------------------------*/ -PROCESS_THREAD(tcp_loader_process, ev, data) -{ - PROCESS_BEGIN(); - - rudolph0_open(&rudolph0, 20, &rudolph0_call); - - tcp_listen(UIP_HTONS(CODEPROP_DATA_PORT)); - - while(1) { - PROCESS_YIELD(); - if(ev == tcpip_event && uip_conn->lport == UIP_HTONS(CODEPROP_DATA_PORT)) { - if(uip_connected()) { /* Really uip_connecting()!!! */ - if(data == NULL) { - PT_INIT(&s.tcpthread_pt); - process_poll(&tcp_loader_process); - tcp_markconn(uip_conn, &s); - - if(elfloader_autostart_processes != NULL) { - PRINTF("Stopping old programs.\n"); - autostart_exit(elfloader_autostart_processes); - elfloader_autostart_processes = NULL; - } - } else { - PRINTF(("codeprop: uip_connected() and data != NULL\n")); - uip_abort(); - } - } - recv_tcpthread(&s.tcpthread_pt); /* Run thread */ - - if(uip_closed() || uip_aborted() || uip_timedout()) { - PRINTF(("codeprop: connection down\n")); - tcp_markconn(uip_conn, NULL); - } - } - } - - PROCESS_END(); -} -/*---------------------------------------------------------------------*/ -#include "net/rime/collect.h" -#include "net/rime/mesh.h" -#include "net/rime/rudolph0.h" -#include "net/rime/rudolph1.h" -void -dummy(void) -{ - /* Make sure that all Rime modules are present in the core */ - collect_close(NULL); - mesh_close(NULL); - ipolite_close(NULL); - polite_close(NULL); - ruc_close(NULL); - sibc_close(NULL); - rudolph0_close(NULL); - rudolph1_close(NULL); - - /* Make sure psock is included */ - psock_datalen(NULL); -} -/*---------------------------------------------------------------------*/ diff --git a/examples/tcp-socket/tcp-server.c b/examples/tcp-socket/tcp-server.c index f2e776784..e25d65579 100644 --- a/examples/tcp-socket/tcp-server.c +++ b/examples/tcp-socket/tcp-server.c @@ -30,6 +30,7 @@ */ #include "contiki-net.h" +#include "sys/cc.h" #include #include @@ -104,7 +105,6 @@ PROCESS_THREAD(tcp_server_process, ev, data) while(bytes_to_send > 0) { PROCESS_PAUSE(); int len, tosend; -#define MIN(a,b) ((a)<(b)?(a):(b)) tosend = MIN(bytes_to_send, sizeof(outputbuf)); len = tcp_socket_send(&socket, (uint8_t *)"", tosend); bytes_to_send -= len; diff --git a/platform/avr-atmega128rfa1/contiki-conf.h b/platform/avr-atmega128rfa1/contiki-conf.h index 47f5c6584..545f6a253 100644 --- a/platform/avr-atmega128rfa1/contiki-conf.h +++ b/platform/avr-atmega128rfa1/contiki-conf.h @@ -191,8 +191,6 @@ typedef unsigned short uip_stats_t; #define CHANNEL_802_15_4 26 /* 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) */ diff --git a/platform/avr-raven/contiki-conf.h b/platform/avr-raven/contiki-conf.h index 40469aa21..2fe0d6099 100644 --- a/platform/avr-raven/contiki-conf.h +++ b/platform/avr-raven/contiki-conf.h @@ -206,8 +206,6 @@ typedef unsigned short uip_stats_t; #define RADIO_CONF_CALIBRATE_INTERVAL 256 /* 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 /* Number of auto retry attempts+1, 1-16. Set zero to disable extended TX_ARET_ON mode with CCA) */ #define RF230_CONF_FRAME_RETRIES 3 /* Number of CSMA attempts 0-7. 802.15.4 2003 standard max is 5. */ diff --git a/platform/avr-ravenlcd/lcd.c b/platform/avr-ravenlcd/lcd.c index 0fe92b80a..3c4f9e230 100644 --- a/platform/avr-ravenlcd/lcd.c +++ b/platform/avr-ravenlcd/lcd.c @@ -411,7 +411,7 @@ lcd_num_putdec(int numb, lcd_padding_t padding) } /* Convert to BCD */ - bcd = itobcd(abs(numb)); + bcd = itobcd(ABS(numb)); /* Print */ return lcd_num_print(bcd, (bool)(numb<0), padding); diff --git a/platform/avr-ravenusb/cdc_task.c b/platform/avr-ravenusb/cdc_task.c index eb2ef3d8b..64af3741e 100644 --- a/platform/avr-ravenusb/cdc_task.c +++ b/platform/avr-ravenusb/cdc_task.c @@ -48,6 +48,7 @@ #include "contiki.h" +#include "sys/cc.h" #include "usb_drv.h" #include "usb_descriptors.h" #include "usb_specific_request.h" @@ -753,7 +754,7 @@ uint16_t p=(uint16_t)&__bss_end; radio_get_rssi_value(&RSSI); RSSI*=3; #endif - maxRSSI[i-11]=Max(maxRSSI[i-11],RSSI); + maxRSSI[i-11]=MAX(maxRSSI[i-11],RSSI); accRSSI[i-11]+=RSSI; } if(j&(1<<7)) { @@ -774,7 +775,7 @@ uint16_t p=(uint16_t)&__bss_end; #endif PRINTF_P(PSTR("\n")); for(i=11;i<=26;i++) { - uint8_t activity=Min(maxRSSI[i-11],accRSSI[i-11]/(1<<7)); + uint8_t activity=MIN(maxRSSI[i-11],accRSSI[i-11]/(1<<7)); PRINTF_P(PSTR(" %d: %02ddB "),i, -91+(maxRSSI[i-11]-1)); for(;activity--;maxRSSI[i-11]--) { PRINTF_P(PSTR("#")); diff --git a/platform/avr-ravenusb/contiki-conf.h b/platform/avr-ravenusb/contiki-conf.h index 03001d02a..1ebe6d718 100644 --- a/platform/avr-ravenusb/contiki-conf.h +++ b/platform/avr-ravenusb/contiki-conf.h @@ -284,9 +284,6 @@ typedef unsigned short uip_stats_t; #define RADIO_CONF_CALIBRATE_INTERVAL 256 /* 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 by sicslowpan.c (else autoretry) */ -/* Broadcasts will be duplicated by the retry count, since no one will ACK them! */ -#define SICSLOWPAN_CONF_ACK_ALL 0 /* 1 + Number of auto retry attempts 0-15 (0 implies don't use extended TX_ARET_ON mode with CCA) */ #define RF230_CONF_FRAME_RETRIES 2 /* CCA theshold energy -91 to -61 dBm (default -77). Set this smaller than the expected minimum rssi to avoid packet collisions */ diff --git a/platform/cc2538dk/Makefile.cc2538dk b/platform/cc2538dk/Makefile.cc2538dk index a760ee5a1..5c3fd77ec 100644 --- a/platform/cc2538dk/Makefile.cc2538dk +++ b/platform/cc2538dk/Makefile.cc2538dk @@ -9,10 +9,7 @@ CONTIKI_TARGET_DIRS = . dev CONTIKI_TARGET_SOURCEFILES += leds.c leds-arch.c CONTIKI_TARGET_SOURCEFILES += contiki-main.c CONTIKI_TARGET_SOURCEFILES += sensors.c smartrf-sensors.c -CONTIKI_TARGET_SOURCEFILES += button-sensor.c adc-sensor.c - -TARGET_START_SOURCEFILES += startup-gcc.c -TARGET_STARTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(TARGET_START_SOURCEFILES)}} +CONTIKI_TARGET_SOURCEFILES += button-sensor.c als-sensor.c CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) diff --git a/platform/cc2538dk/README.md b/platform/cc2538dk/README.md index 4cb83fdd2..dde73842e 100644 --- a/platform/cc2538dk/README.md +++ b/platform/cc2538dk/README.md @@ -29,6 +29,7 @@ In terms of hardware support, the following drivers have been implemented: * Low Power Modes * General-Purpose Timers. NB: GPT0 is in use by the platform code, the remaining GPTs are available for application development. * ADC + * Cryptoprocessor (AES-CCM-256, SHA-256) * SmartRF06 EB and BB peripherals * LEDs * Buttons @@ -74,10 +75,9 @@ The toolchain used to build contiki is arm-gcc, also used by other arm-based Con Thread model: single gcc version 4.3.2 (Sourcery G++ Lite 2008q3-66) -The platform is currently being used/tested with the following toolchains: +The platform is currently being used/tested with "GNU Tools for ARM Embedded Processors". This is the recommended version and the one being used by Contiki's regression tests on Travis. -* GNU Tools for ARM Embedded Processors. This is the recommended version. Works nicely on OS X. -* Alternatively, you can use this older version for Linux. At the time of writing, this is the version used by Contiki's regression tests. +The older version (Sourcery G++ Lite 2008q3-66) shown above should still work, but the port is no longer being tested with it. Drivers ------- @@ -147,10 +147,14 @@ The CC2538 EM's USB Vendor and Product IDs are the following: The implementation in Contiki is pure CDC-ACM: The Linux and OS X kernels know exactly what to do and drivers are not required. -On windows, you will need to provide a driver: +On windows, you will need to provide a driver. You have two options: - * Download this LUFA CDC-ACM driver: - + * Use the signed or unsigned driver provided by TI in [CC2538 Foundation Firmware](http://www.ti.com/tool/cc2538-sw). You will find them both under the `drivers` directory. + * Download a generic Virtual Serial Port driver and modify it so it works for the CC2538. + +For the latter option: + + * Download this [LUFA CDC-ACM driver](https://raw.githubusercontent.com/abcminiuser/lufa/master/Demos/Device/LowLevel/VirtualSerial/LUFA%20VirtualSerial.inf). * Adjust the VID and PID near the end with the values at the start of this section. * Next time you get prompted for the driver, include the directory containing the .inf file in the search path and the driver will be installed. diff --git a/platform/cc2538dk/contiki-main.c b/platform/cc2538dk/contiki-main.c index 4487a07f2..71de03a10 100644 --- a/platform/cc2538dk/contiki-main.c +++ b/platform/cc2538dk/contiki-main.c @@ -43,6 +43,7 @@ */ /*---------------------------------------------------------------------------*/ #include "contiki.h" +#include "dev/adc.h" #include "dev/leds.h" #include "dev/sys-ctrl.h" #include "dev/scb.h" @@ -208,6 +209,8 @@ main(void) process_start(&tcpip_process, NULL); #endif /* NETSTACK_CONF_WITH_IPV6 */ + adc_init(); + process_start(&sensors_process, NULL); energest_init(); diff --git a/platform/cc2538dk/dev/adc-sensor.c b/platform/cc2538dk/dev/als-sensor.c similarity index 82% rename from platform/cc2538dk/dev/adc-sensor.c rename to platform/cc2538dk/dev/als-sensor.c index 4c2f1f853..2ecc857ea 100644 --- a/platform/cc2538dk/dev/adc-sensor.c +++ b/platform/cc2538dk/dev/als-sensor.c @@ -30,18 +30,18 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /** - * \addtogroup cc2538dk-adc-sensor + * \addtogroup cc2538dk-als-sensor * @{ * * \file - * Driver for the SmartRF06EB ADC + * Driver for the SmartRF06EB ALS */ #include "contiki.h" #include "sys/clock.h" #include "dev/ioc.h" #include "dev/gpio.h" #include "dev/adc.h" -#include "dev/adc-sensor.h" +#include "dev/als-sensor.h" #include @@ -52,30 +52,15 @@ static int value(int type) { - uint8_t channel; + uint8_t channel = SOC_ADC_ADCCON_CH_AIN0 + ADC_ALS_OUT_PIN; int16_t res; - switch(type) { - case ADC_SENSOR_VDD_3: - channel = SOC_ADC_ADCCON_CH_VDD_3; - break; - case ADC_SENSOR_TEMP: - channel = SOC_ADC_ADCCON_CH_TEMP; - break; - case ADC_SENSOR_ALS: - channel = SOC_ADC_ADCCON_CH_AIN0 + ADC_ALS_OUT_PIN; - GPIO_SET_PIN(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK); - clock_delay_usec(2000); - break; - default: - return 0; - } + GPIO_SET_PIN(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK); + clock_delay_usec(2000); res = adc_get(channel, SOC_ADC_ADCCON_REF_INT, SOC_ADC_ADCCON_DIV_512); - if(type == ADC_SENSOR_ALS) { - GPIO_CLR_PIN(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK); - } + GPIO_CLR_PIN(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK); return res; } @@ -94,7 +79,6 @@ configure(int type, int value) GPIO_SET_INPUT(GPIO_A_BASE, ADC_ALS_OUT_PIN_MASK); ioc_set_over(GPIO_A_NUM, ADC_ALS_OUT_PIN, IOC_OVERRIDE_ANA); - adc_init(); break; } return 0; @@ -106,6 +90,6 @@ status(int type) return 1; } /*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(adc_sensor, ADC_SENSOR, value, configure, status); +SENSORS_SENSOR(als_sensor, ALS_SENSOR, value, configure, status); /** @} */ diff --git a/platform/cc2538dk/dev/adc-sensor.h b/platform/cc2538dk/dev/als-sensor.h similarity index 79% rename from platform/cc2538dk/dev/adc-sensor.h rename to platform/cc2538dk/dev/als-sensor.h index b6d0efbdf..abed92e13 100644 --- a/platform/cc2538dk/dev/adc-sensor.h +++ b/platform/cc2538dk/dev/als-sensor.h @@ -33,33 +33,29 @@ * \addtogroup cc2538-smartrf-sensors * @{ * - * \defgroup cc2538dk-adc-sensor cc2538dk ADC Driver + * \defgroup cc2538dk-als-sensor cc2538dk ALS Driver * - * Driver for the SmartRF06EB ADC sensors + * Driver for the SmartRF06EB ALS sensor * @{ * * \file - * Header file for the cc2538dk ADC Driver + * Header file for the cc2538dk ALS Driver */ -#ifndef ADC_SENSOR_H_ -#define ADC_SENSOR_H_ +#ifndef ALS_SENSOR_H_ +#define ALS_SENSOR_H_ #include "lib/sensors.h" /*---------------------------------------------------------------------------*/ -/** \name ADC sensors +/** \name ALS sensor * @{ */ -#define ADC_SENSOR "ADC" - -#define ADC_SENSOR_VDD_3 0 /**< On-chip VDD / 3 */ -#define ADC_SENSOR_TEMP 1 /**< On-chip temperature */ -#define ADC_SENSOR_ALS 2 /**< Ambient light sensor */ +#define ALS_SENSOR "ALS" /** @} */ -extern const struct sensors_sensor adc_sensor; +extern const struct sensors_sensor als_sensor; -#endif /* ADC_SENSOR_H_ */ +#endif /* ALS_SENSOR_H_ */ /** * @} diff --git a/platform/cc2538dk/dev/board.h b/platform/cc2538dk/dev/board.h index d5514839d..2d9c5ac48 100644 --- a/platform/cc2538dk/dev/board.h +++ b/platform/cc2538dk/dev/board.h @@ -28,7 +28,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** +/** * \addtogroup cc2538dk * @{ * @@ -78,28 +78,28 @@ #undef LEDS_RED #undef LEDS_CONF_ALL -#define LEDS_YELLOW 2 /**< LED2 (Yellow) -> PC1 */ -#define LEDS_GREEN 4 /**< LED3 (Green) -> PC2 */ -#define LEDS_ORANGE 8 /**< LED4 (Orange) -> PC3 */ +#define LEDS_YELLOW 2 /**< LED2 (Yellow) -> PC1 */ +#define LEDS_GREEN 4 /**< LED3 (Green) -> PC2 */ +#define LEDS_ORANGE 8 /**< LED4 (Orange) -> PC3 */ #if USB_SERIAL_CONF_ENABLE -#define LEDS_CONF_ALL 14 -#define LEDS_RED LEDS_ORANGE +#define LEDS_CONF_ALL 14 +#define LEDS_RED LEDS_ORANGE #else -#define LEDS_CONF_ALL 15 -#define LEDS_RED 1 /**< LED1 (Red) -> PC0 */ +#define LEDS_CONF_ALL 15 +#define LEDS_RED 1 /**< LED1 (Red) -> PC0 */ #endif /* Notify various examples that we have LEDs */ -#define PLATFORM_HAS_LEDS 1 +#define PLATFORM_HAS_LEDS 1 /** @} */ /*---------------------------------------------------------------------------*/ /** \name USB configuration * * The USB pullup is driven by PC0 and is shared with LED1 */ -#define USB_PULLUP_PORT GPIO_C_NUM -#define USB_PULLUP_PIN 0 +#define USB_PULLUP_PORT GPIO_C_NUM +#define USB_PULLUP_PIN 0 /** @} */ /*---------------------------------------------------------------------------*/ /** \name UART configuration @@ -115,17 +115,17 @@ * UART1_* below. * @{ */ -#define UART0_RX_PORT GPIO_A_NUM -#define UART0_RX_PIN 0 +#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 UART0_TX_PORT GPIO_A_NUM +#define UART0_TX_PIN 1 -#define UART1_CTS_PORT GPIO_B_NUM -#define UART1_CTS_PIN 0 +#define UART1_CTS_PORT GPIO_B_NUM +#define UART1_CTS_PIN 0 -#define UART1_RTS_PORT GPIO_D_NUM -#define UART1_RTS_PIN 3 +#define UART1_RTS_PORT GPIO_D_NUM +#define UART1_RTS_PIN 3 /** @} */ /*---------------------------------------------------------------------------*/ /** \name SmartRF Button configuration @@ -139,32 +139,32 @@ * @{ */ /** BUTTON_SELECT -> PA3 */ -#define BUTTON_SELECT_PORT GPIO_A_NUM -#define BUTTON_SELECT_PIN 3 -#define BUTTON_SELECT_VECTOR NVIC_INT_GPIO_PORT_A +#define BUTTON_SELECT_PORT GPIO_A_NUM +#define BUTTON_SELECT_PIN 3 +#define BUTTON_SELECT_VECTOR NVIC_INT_GPIO_PORT_A /** BUTTON_LEFT -> PC4 */ -#define BUTTON_LEFT_PORT GPIO_C_NUM -#define BUTTON_LEFT_PIN 4 -#define BUTTON_LEFT_VECTOR NVIC_INT_GPIO_PORT_C +#define BUTTON_LEFT_PORT GPIO_C_NUM +#define BUTTON_LEFT_PIN 4 +#define BUTTON_LEFT_VECTOR NVIC_INT_GPIO_PORT_C /** BUTTON_RIGHT -> PC5 */ -#define BUTTON_RIGHT_PORT GPIO_C_NUM -#define BUTTON_RIGHT_PIN 5 -#define BUTTON_RIGHT_VECTOR NVIC_INT_GPIO_PORT_C +#define BUTTON_RIGHT_PORT GPIO_C_NUM +#define BUTTON_RIGHT_PIN 5 +#define BUTTON_RIGHT_VECTOR NVIC_INT_GPIO_PORT_C /** BUTTON_UP -> PC6 */ -#define BUTTON_UP_PORT GPIO_C_NUM -#define BUTTON_UP_PIN 6 -#define BUTTON_UP_VECTOR NVIC_INT_GPIO_PORT_C +#define BUTTON_UP_PORT GPIO_C_NUM +#define BUTTON_UP_PIN 6 +#define BUTTON_UP_VECTOR NVIC_INT_GPIO_PORT_C /** BUTTON_DOWN -> PC7 */ -#define BUTTON_DOWN_PORT GPIO_C_NUM -#define BUTTON_DOWN_PIN 7 -#define BUTTON_DOWN_VECTOR NVIC_INT_GPIO_PORT_C +#define BUTTON_DOWN_PORT GPIO_C_NUM +#define BUTTON_DOWN_PIN 7 +#define BUTTON_DOWN_VECTOR NVIC_INT_GPIO_PORT_C /* Notify various examples that we have Buttons */ -#define PLATFORM_HAS_BUTTON 1 +#define PLATFORM_HAS_BUTTON 1 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -176,23 +176,49 @@ * ADC inputs can only be on port A. * @{ */ -#define ADC_ALS_PWR_PORT GPIO_A_NUM /**< ALS power GPIO control port */ -#define ADC_ALS_PWR_PIN 7 /**< ALS power GPIO control pin */ -#define ADC_ALS_OUT_PIN 6 /**< ALS output ADC input pin on port A */ +#define ADC_ALS_PWR_PORT GPIO_A_NUM /**< ALS power GPIO control port */ +#define ADC_ALS_PWR_PIN 7 /**< ALS power GPIO control pin */ +#define ADC_ALS_OUT_PIN 6 /**< ALS output ADC input pin on port A */ /** @} */ /*---------------------------------------------------------------------------*/ /** * \name SPI configuration * - * These values configure which CC2538 pins to use for the SPI lines. + * These values configure which CC2538 pins to use for the SPI lines. Both + * SPI instances can be used independently by providing the corresponding + * port / pin macros. * @{ */ -#define SPI_CLK_PORT GPIO_A_NUM /**< Clock port */ -#define SPI_CLK_PIN 2 /**< Clock pin */ -#define SPI_MOSI_PORT GPIO_A_NUM /**< MOSI port */ -#define SPI_MOSI_PIN 4 /**< MOSI pin */ -#define SPI_MISO_PORT GPIO_A_NUM /**< MISO port */ -#define SPI_MISO_PIN 5 /**< MISO pin */ +#define SPI0_IN_USE 0 +#define SPI1_IN_USE 0 +#if SPI0_IN_USE +/** Clock port SPI0 */ +#define SPI0_CLK_PORT GPIO_A_NUM +/** Clock pin SPI0 */ +#define SPI0_CLK_PIN 2 +/** TX port SPI0 (master mode: MOSI) */ +#define SPI0_TX_PORT GPIO_A_NUM +/** TX pin SPI0 */ +#define SPI0_TX_PIN 4 +/** RX port SPI0 (master mode: MISO */ +#define SPI0_RX_PORT GPIO_A_NUM +/** RX pin SPI0 */ +#define SPI0_RX_PIN 5 +#endif /* #if SPI0_IN_USE */ +#if SPI1_IN_USE +/** Clock port SPI1 */ +#define SPI1_CLK_PORT GPIO_A_NUM +/** Clock pin SPI1 */ +#define SPI1_CLK_PIN 2 +/** TX port SPI1 (master mode: MOSI) */ +#define SPI1_TX_PORT GPIO_A_NUM +/** TX pin SPI1 */ +#define SPI1_TX_PIN 4 +/** RX port SPI1 (master mode: MISO) */ +#define SPI1_RX_PORT GPIO_A_NUM +/** RX pin SPI1 */ +#define SPI1_RX_PIN 5 +#endif /* #if SPI1_IN_USE */ /** @} */ /*---------------------------------------------------------------------------*/ /** diff --git a/platform/cc2538dk/dev/smartrf-sensors.c b/platform/cc2538dk/dev/smartrf-sensors.c index 41d977783..76841af3b 100644 --- a/platform/cc2538dk/dev/smartrf-sensors.c +++ b/platform/cc2538dk/dev/smartrf-sensors.c @@ -42,13 +42,15 @@ */ #include "contiki.h" #include "dev/button-sensor.h" -#include "dev/adc-sensor.h" +#include "dev/als-sensor.h" +#include "dev/cc2538-sensors.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, &adc_sensor); + &button_up_sensor, &button_down_sensor, &als_sensor, + &cc2538_temp_sensor, &vdd3_sensor); /** * @} diff --git a/platform/cooja-ip64/Makefile.cooja-ip64 b/platform/cooja-ip64/Makefile.cooja-ip64 new file mode 100644 index 000000000..d86077c57 --- /dev/null +++ b/platform/cooja-ip64/Makefile.cooja-ip64 @@ -0,0 +1,15 @@ +COOJAPLATFORMDIR=$(CONTIKI)/platform/cooja + +MODULES += core/net/ip64 +include $(COOJAPLATFORMDIR)/Makefile.cooja + +vpath %.c $(COOJAPLATFORMDIR) $(COOJAPLATFORMDIR)/dev \ + $(COOJAPLATFORMDIR)/net $(COOJAPLATFORMDIR)/lib \ + $(COOJAPLATFORMDIR)/sys $(COOJAPLATFORMDIR)/cfs +CFLAGS += -I $(COOJAPLATFORMDIR) + +CFLAGS += -DWITH_IP64=1 -DWITH_LARGE_BUFFER_SIZE=1 +CFLAGS += -DINCLUDE_SUBPLATFORM_CONF=1 + +%.cooja: %.cooja-ip64 + cp $< $@ diff --git a/platform/cooja-ip64/Makefile.customrules-cooja-ip64 b/platform/cooja-ip64/Makefile.customrules-cooja-ip64 new file mode 100644 index 000000000..3de3bc7c5 --- /dev/null +++ b/platform/cooja-ip64/Makefile.customrules-cooja-ip64 @@ -0,0 +1,50 @@ +### Define custom targets + +REDEF_PRINTF=1 # Redefine functions to enable printf()s inside Cooja + +# NB: Assumes ARCHIVE was not overridden and is in $(OBJECTDIR) +$(ARCHIVE): $(CONTIKI_OBJECTFILES) | $(OBJECTDIR) + ${subst obj_cooja/,$(OBJECTDIR)/,$(AR_COMMAND_1)} $^ $(AR_COMMAND_2) + +# NB: Assumes JNILIB was not overridden and is in $(OBJECTDIR) +$(JNILIB): $(CONTIKI_APP_OBJ) $(MAIN_OBJ) $(PROJECT_OBJECTFILES) $(ARCHIVE) | $(OBJECTDIR) +ifdef SYMBOLS + @echo Generating symbols + # Recreate symbols file and relink with final memory layout (twice) + ${CONTIKI}/tools/make-symbols-nm $(JNILIB) + $(CC) $(CFLAGS) -c symbols.c -o $(OBJECTDIR)/symbols.o + $(LINK_COMMAND_1) $^ $(LINK_COMMAND_2) + ${CONTIKI}/tools/make-symbols-nm $(JNILIB) + $(CC) $(CFLAGS) -c symbols.c -o $(OBJECTDIR)/symbols.o +endif ## SYMBOLS +ifdef REDEF_PRINTF + @echo Redefining printf + -$(foreach OBJ,$^, $(OBJCOPY) --redefine-sym printf=log_printf $(OBJ); ) + -$(foreach OBJ,$^, $(OBJCOPY) --redefine-sym puts=log_puts $(OBJ); ) + -$(foreach OBJ,$^, $(OBJCOPY) --redefine-sym putchar=log_putchar $(OBJ); ) +endif ## REDEF_PRINTF + ${subst .cooja,.$(TARGET),${subst obj_cooja/,$(OBJECTDIR)/,$(LINK_COMMAND_1)}} $^ $(LINK_COMMAND_2) + +.PHONY: $(CONTIKI_APP).$(TARGET) +$(CONTIKI_APP).$(TARGET): $(JNILIB) + cp $(JNILIB) $@ + rm $(CONTIKI_APP_OBJ) + + mkdir -p obj_cooja + @-cp obj_cooja-ip64/$(LIBNAME).map obj_cooja/$(LIBNAME).map && echo Placed a copy of the map file at obj_cooja/$(LIBNAME).map + + cp obj_cooja-ip64/$(LIBNAME).cooja-ip64 obj_cooja/$(LIBNAME).cooja + @echo Placed a copy of the shared library at obj_cooja/$(LIBNAME).cooja + + cp $@ $(CONTIKI_APP).cooja + @echo Placed a copy of the shared library at $(CONTIKI_APP).cooja + +# Trickiness: GNU make matches this against the file base name. +# Assume that the directory part is the standard location. +mtype%.o: contiki-cooja-ip64-main.o | $(OBJECTDIR) + mv contiki-cooja-ip64-main.o $@ + +symbols.c: + # Create initial symbol files if not existing + cp ${CONTIKI}/tools/empty-symbols.c symbols.c + cp ${CONTIKI}/tools/empty-symbols.h symbols.h diff --git a/platform/cooja-ip64/contiki-cooja-ip64-main.c b/platform/cooja-ip64/contiki-cooja-ip64-main.c new file mode 100644 index 000000000..1077162a7 --- /dev/null +++ b/platform/cooja-ip64/contiki-cooja-ip64-main.c @@ -0,0 +1,425 @@ +/* + * 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 + * COOJA Contiki mote main file. + * \author + * Fredrik Osterlind + */ + +#include +#include +#include + +#include "contiki.h" + +#include "sys/clock.h" +#include "sys/etimer.h" +#include "sys/cooja_mt.h" +#include "sys/autostart.h" + +#include "lib/random.h" +#include "lib/simEnvChange.h" + +#include "net/rime/rime.h" +#include "net/netstack.h" +#include "net/ip/uip-nameserver.h" + +#include "dev/serial-line.h" +#include "dev/cooja-radio.h" +#include "dev/button-sensor.h" +#include "dev/pir-sensor.h" +#include "dev/vib-sensor.h" + +#include "sys/node-id.h" + +#include "ip64.h" +#include "dev/slip.h" + +/* JNI-defined functions, depends on the environment variable CLASSNAME */ +#ifndef CLASSNAME +#error CLASSNAME is undefined, required by contiki-cooja-main.c +#endif /* CLASSNAME */ +#define COOJA__QUOTEME(a,b,c) COOJA_QUOTEME(a,b,c) +#define COOJA_QUOTEME(a,b,c) a##b##c +#define COOJA_JNI_PATH Java_org_contikios_cooja_corecomm_ +#define Java_org_contikios_cooja_corecomm_CLASSNAME_init COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_init) +#define Java_org_contikios_cooja_corecomm_CLASSNAME_getMemory COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_getMemory) +#define Java_org_contikios_cooja_corecomm_CLASSNAME_setMemory COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_setMemory) +#define Java_org_contikios_cooja_corecomm_CLASSNAME_tick COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_tick) +#define Java_org_contikios_cooja_corecomm_CLASSNAME_setReferenceAddress COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_setReferenceAddress) + +#include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" +#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]) + +/* Simulation mote interfaces */ +SIM_INTERFACE_NAME(moteid_interface); +SIM_INTERFACE_NAME(vib_interface); +SIM_INTERFACE_NAME(rs232_interface); +SIM_INTERFACE_NAME(simlog_interface); +SIM_INTERFACE_NAME(beep_interface); +SIM_INTERFACE_NAME(radio_interface); +SIM_INTERFACE_NAME(button_interface); +SIM_INTERFACE_NAME(pir_interface); +SIM_INTERFACE_NAME(clock_interface); +SIM_INTERFACE_NAME(leds_interface); +SIM_INTERFACE_NAME(cfs_interface); +SIM_INTERFACES(&vib_interface, &moteid_interface, &rs232_interface, &simlog_interface, &beep_interface, &radio_interface, &button_interface, &pir_interface, &clock_interface, &leds_interface, &cfs_interface); +/* Example: manually add mote interfaces */ +//SIM_INTERFACE_NAME(dummy_interface); +//SIM_INTERFACES(..., &dummy_interface); + +/* Sensors */ +SENSORS(&button_sensor, &pir_sensor, &vib_sensor); + +/* + * referenceVar is used for comparing absolute and process relative memory. + * (this must not be static due to memory locations) + */ +long referenceVar; + +/* + * Contiki and rtimer threads. + */ +static struct cooja_mt_thread rtimer_thread; +static struct cooja_mt_thread process_run_thread; + +#define MIN(a, b) ( (a)<(b) ? (a) : (b) ) + +/*---------------------------------------------------------------------------*/ +static void +print_processes(struct process * const processes[]) +{ + /* const struct process * const * p = processes;*/ + printf("Starting"); + while(*processes != NULL) { + printf(" '%s'", (*processes)->name); + processes++; + } + putchar('\n'); +} +/*---------------------------------------------------------------------------*/ +static void +rtimer_thread_loop(void *data) +{ + while(1) + { + rtimer_arch_check(); + + /* Return to COOJA */ + cooja_mt_yield(); + } +} +/*---------------------------------------------------------------------------*/ +static void +set_mac_addr(void) +{ + linkaddr_t addr; + int i; + + memset(&addr, 0, sizeof(linkaddr_t)); + for(i = 0; i < sizeof(uip_lladdr.addr); i += 2) { + addr.u8[i + 1] = node_id & 0xff; + addr.u8[i + 0] = node_id >> 8; + } + linkaddr_set_node_addr(&addr); + printf("MAC address "); + for(i = 0; i < sizeof(addr.u8) - 1; i++) { + printf("%d.", addr.u8[i]); + } + printf("%d\n", addr.u8[i]); +} +/*---------------------------------------------------------------------------*/ +void +contiki_init(void) +{ + int i; + uint8_t addr[sizeof(uip_lladdr.addr)]; + uip_ipaddr_t ipaddr; + uip_ds6_addr_t *lladdr; + uip_ip4addr_t ipv4addr, netmask; + + /* Start process handler */ + process_init(); + + /* Start Contiki processes */ + process_start(&etimer_process, NULL); + process_start(&sensors_process, NULL); + ctimer_init(); + + /* Print startup information */ + printf(CONTIKI_VERSION_STRING " started. "); + if(node_id > 0) { + printf("Node id is set to %u.\n", node_id); + } else { + printf("Node id is not set.\n"); + } + + set_mac_addr(); + + queuebuf_init(); + + /* Initialize communication stack */ + netstack_init(); + printf("%s/%s/%s, channel check rate %lu Hz\n", + NETSTACK_NETWORK.name, NETSTACK_MAC.name, NETSTACK_RDC.name, + CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1: + NETSTACK_RDC.channel_check_interval())); + + /* IPv6 CONFIGURATION */ + + + for(i = 0; i < sizeof(uip_lladdr.addr); i += 2) { + addr[i + 1] = node_id & 0xff; + addr[i + 0] = node_id >> 8; + } + linkaddr_copy(addr, &linkaddr_node_addr); + memcpy(&uip_lladdr.addr, addr, sizeof(uip_lladdr.addr)); + + process_start(&tcpip_process, NULL); + + printf("Tentative link-local IPv6 address "); + + lladdr = uip_ds6_get_link_local(-1); + for(i = 0; i < 7; ++i) { + printf("%02x%02x:", lladdr->ipaddr.u8[i * 2], + lladdr->ipaddr.u8[i * 2 + 1]); + } + printf("%02x%02x\n", lladdr->ipaddr.u8[14], + lladdr->ipaddr.u8[15]); + + 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_TENTATIVE); + printf("Tentative global IPv6 address "); + for(i = 0; i < 7; ++i) { + printf("%02x%02x:", + ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]); + } + printf("%02x%02x\n", + ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]); + + /* Start serial process */ + serial_line_init(); + + /* Start autostart processes (defined in Contiki application) */ + print_processes(autostart_processes); + autostart_start(autostart_processes); + + /* Start the SLIP */ + printf("Initiating SLIP with IP address is 172.16.0.2.\n"); + + uip_ipaddr(&ipv4addr, 172, 16, 0, 2); + uip_ipaddr(&netmask, 255, 255, 255, 0); + ip64_set_ipv4_address(&ipv4addr, &netmask); + + rs232_set_input(slip_input_byte); + log_set_putchar_with_slip(1); + + uip_ip4addr_t ip4addr; + uip_ip6addr_t ip6addr; + + uip_ipaddr(&ip4addr, 8,8,8,8); + ip64_addr_4to6(&ip4addr, &ip6addr); + + uip_nameserver_update((uip_ipaddr_t *)&ip6addr, UIP_NAMESERVER_INFINITE_LIFETIME); +} +/*---------------------------------------------------------------------------*/ +static void +process_run_thread_loop(void *data) +{ + /* Yield once during bootup */ + simProcessRunValue = 1; + cooja_mt_yield(); + + contiki_init(); + + while(1) { + simProcessRunValue = process_run(); + while(simProcessRunValue-- > 0) { + process_run(); + } + simProcessRunValue = process_nevents(); + + /* Check if we must stay awake */ + if(simDontFallAsleep) { + simDontFallAsleep = 0; + simProcessRunValue = 1; + } + + /* Return to COOJA */ + cooja_mt_yield(); + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialize a mote by starting processes etc. + * + * This function initializes a mote by starting certain + * processes and setting up the environment. + * + * This is a JNI function and should only be called via the + * responsible Java part (MoteType.java). + */ +JNIEXPORT void JNICALL +Java_org_contikios_cooja_corecomm_CLASSNAME_init(JNIEnv *env, jobject obj) +{ + /* Create rtimers and Contiki threads */ + cooja_mt_start(&rtimer_thread, &rtimer_thread_loop, NULL); + cooja_mt_start(&process_run_thread, &process_run_thread_loop, NULL); + } +/*---------------------------------------------------------------------------*/ +/** + * \brief Get a segment from the process memory. + * \param start Start address of segment + * \param length Size of memory segment + * \return Java byte array containing a copy of memory segment. + * + * Fetches a memory segment from the process memory starting at + * (start), with size (length). This function does not perform + * ANY error checking, and the process may crash if addresses are + * not available/readable. + * + * This is a JNI function and should only be called via the + * responsible Java part (MoteType.java). + */ +JNIEXPORT void JNICALL +Java_org_contikios_cooja_corecomm_CLASSNAME_getMemory(JNIEnv *env, jobject obj, jint rel_addr, jint length, jbyteArray mem_arr) +{ + (*env)->SetByteArrayRegion( + env, + mem_arr, + 0, + (size_t) length, + (jbyte *) (((long)rel_addr) + referenceVar) + ); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Replace a segment of the process memory with given byte array. + * \param start Start address of segment + * \param length Size of memory segment + * \param mem_arr Byte array contaning new memory + * + * Replaces a process memory segment with given byte array. + * This function does not perform ANY error checking, and the + * process may crash if addresses are not available/writable. + * + * This is a JNI function and should only be called via the + * responsible Java part (MoteType.java). + */ +JNIEXPORT void JNICALL +Java_org_contikios_cooja_corecomm_CLASSNAME_setMemory(JNIEnv *env, jobject obj, jint rel_addr, jint length, jbyteArray mem_arr) +{ + jbyte *mem = (*env)->GetByteArrayElements(env, mem_arr, 0); + memcpy((char *)(((long)rel_addr) + referenceVar), + mem, + length); + (*env)->ReleaseByteArrayElements(env, mem_arr, mem, 0); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Let mote execute one "block" of code (tick mote). + * + * Let mote defined by the active contiki processes and current + * process memory execute some program code. This code must not block + * or else this function will never return. A typical contiki + * process will return when it executes PROCESS_WAIT..() statements. + * + * Before the control is left to contiki processes, any messages + * from the Java part are handled. These may for example be + * incoming network data. After the contiki processes return control, + * messages to the Java part are also handled (those which may need + * special attention). + * + * This is a JNI function and should only be called via the + * responsible Java part (MoteType.java). + */ +JNIEXPORT void JNICALL +Java_org_contikios_cooja_corecomm_CLASSNAME_tick(JNIEnv *env, jobject obj) +{ + clock_time_t nextEtimer; + rtimer_clock_t nextRtimer; + + simProcessRunValue = 0; + + /* Let all simulation interfaces act first */ + doActionsBeforeTick(); + + /* Poll etimer process */ + if(etimer_pending()) { + etimer_request_poll(); + } + + /* Let rtimers run. + * Sets simProcessRunValue */ + cooja_mt_exec(&rtimer_thread); + + if(simProcessRunValue == 0) { + /* Rtimers done: Let Contiki handle a few events. + * Sets simProcessRunValue */ + cooja_mt_exec(&process_run_thread); + } + + /* Let all simulation interfaces act before returning to java */ + doActionsAfterTick(); + + /* Do we have any pending timers */ + simEtimerPending = etimer_pending() || rtimer_arch_pending(); + if(!simEtimerPending) { + return; + } + + /* Save nearest expiration time */ + nextEtimer = etimer_next_expiration_time() - (clock_time_t) simCurrentTime; + nextRtimer = rtimer_arch_next() - (rtimer_clock_t) simCurrentTime; + if(etimer_pending() && rtimer_arch_pending()) { + simNextExpirationTime = MIN(nextEtimer, nextRtimer); + } else if(etimer_pending()) { + simNextExpirationTime = nextEtimer; + } else if(rtimer_arch_pending()) { + simNextExpirationTime = nextRtimer; + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Set the relative memory address of the reference variable. + * \return Relative memory address. + * + * This is a JNI function and should only be called via the + * responsible Java part (MoteType.java). + */ +JNIEXPORT void JNICALL +Java_org_contikios_cooja_corecomm_CLASSNAME_setReferenceAddress(JNIEnv *env, jobject obj, jint addr) +{ + referenceVar = (((long)&referenceVar) - ((long)addr)); +} diff --git a/platform/cooja-ip64/ip64-conf.h b/platform/cooja-ip64/ip64-conf.h new file mode 100644 index 000000000..376614abe --- /dev/null +++ b/platform/cooja-ip64/ip64-conf.h @@ -0,0 +1,45 @@ +/* + * 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 IP64_CONF_H +#define IP64_CONF_H + +#undef UIP_FALLBACK_INTERFACE +#define UIP_FALLBACK_INTERFACE ip64_uip_fallback_interface + +#include "ip64-slip-interface.h" +#include "ip64-null-driver.h" + +#define IP64_CONF_UIP_FALLBACK_INTERFACE_SLIP 1 +#define IP64_CONF_UIP_FALLBACK_INTERFACE ip64_slip_interface +#define IP64_CONF_INPUT ip64_slip_interface_input +#define IP64_CONF_ETH_DRIVER ip64_null_driver + +#endif /* IP64_CONF_H */ diff --git a/platform/cooja-ip64/subplatform-conf.h b/platform/cooja-ip64/subplatform-conf.h new file mode 100644 index 000000000..14afc2ad2 --- /dev/null +++ b/platform/cooja-ip64/subplatform-conf.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 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 __PLATFORM_CONF_H__ +#define __PLATFORM_CONF_H__ + +#if WITH_IP64 +#define WITH_SLIP 1 +#ifndef UIP_FALLBACK_INTERFACE +#define UIP_FALLBACK_INTERFACE ip64_uip_fallback_interface +#endif +#endif /* WITH_IP64 */ + +#ifndef UIP_CONF_ND6_RA_RDNSS +#define UIP_CONF_ND6_RA_RDNSS 1 +#endif + +#ifndef UIP_CONF_ND6_SEND_RA +#define UIP_CONF_ND6_SEND_RA 1 +#endif + +#ifndef UIP_CONF_ROUTER +#define UIP_CONF_ROUTER 1 +#endif + +#endif /* __PLATFORM_CONF_H__ */ diff --git a/platform/cooja/Makefile.cooja b/platform/cooja/Makefile.cooja index 574def7c7..c28dac608 100644 --- a/platform/cooja/Makefile.cooja +++ b/platform/cooja/Makefile.cooja @@ -37,7 +37,7 @@ endif ## QUICKSTART #MAIN_SRC = $(OBJECTDIR)/$(LIBNAME).c MAIN_OBJ = $(OBJECTDIR)/$(LIBNAME).o ARCHIVE = $(OBJECTDIR)/$(LIBNAME).a -JNILIB = $(OBJECTDIR)/$(LIBNAME).cooja +JNILIB = $(OBJECTDIR)/$(LIBNAME).$(TARGET) CONTIKI_APP_OBJ = $(CONTIKI_APP).co ### COOJA platform sources @@ -75,7 +75,7 @@ CFLAGSNO = $(EXTRA_CC_ARGS) -Wall -g -I/usr/local/include -DCLASSNAME=$(CLASSNAM CFLAGS += $(CFLAGSNO) MODULES += core/net core/net/mac \ - core/net/llsec + core/net/llsec core/net/ip64-addr ## Copied from Makefile.include, since Cooja overrides CFLAGS et al HAS_STACK = 0 diff --git a/platform/cooja/contiki-conf.h b/platform/cooja/contiki-conf.h index e92d63c6a..d4f3979e9 100644 --- a/platform/cooja/contiki-conf.h +++ b/platform/cooja/contiki-conf.h @@ -33,6 +33,10 @@ #ifndef CONTIKI_CONF_H_ #define CONTIKI_CONF_H_ +#ifdef INCLUDE_SUBPLATFORM_CONF +#include "subplatform-conf.h" +#endif /* INCLUDE_SUBPLATFORM_CONF */ + #define PROFILE_CONF_ON 0 #define ENERGEST_CONF_ON 0 #define LOG_CONF_ENABLED 1 @@ -135,9 +139,17 @@ #define TCPIP_CONF_ANNOTATE_TRANSMISSIONS 1 +#ifndef UIP_CONF_ND6_SEND_RA #define UIP_CONF_ND6_SEND_RA 0 +#endif + +#ifndef UIP_CONF_ND6_REACHABLE_TIME #define UIP_CONF_ND6_REACHABLE_TIME 600000 +#endif + +#ifndef UIP_CONF_ND6_RETRANS_TIMER #define UIP_CONF_ND6_RETRANS_TIMER 10000 +#endif #define LINKADDR_CONF_SIZE 8 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 @@ -149,9 +161,6 @@ #define UIP_CONF_IPV6_REASSEMBLY 0 #define UIP_CONF_NETIF_MAX_ADDRESSES 3 #define UIP_CONF_IP_FORWARD 0 -#ifndef UIP_CONF_BUFFER_SIZE -#define UIP_CONF_BUFFER_SIZE 240 -#endif #define SICSLOWPAN_CONF_COMPRESSION SICSLOWPAN_COMPRESSION_HC06 #ifndef SICSLOWPAN_CONF_FRAG @@ -168,7 +177,9 @@ #define PACKETBUF_CONF_ATTRS_INLINE 1 +#ifndef QUEUEBUF_CONF_NUM #define QUEUEBUF_CONF_NUM 16 +#endif #define CC_CONF_REGISTER_ARGS 1 #define CC_CONF_FUNCTION_POINTER_ARGS 1 @@ -202,12 +213,6 @@ typedef unsigned long rtimer_clock_t; #define UIP_CONF_DHCP_LIGHT #define UIP_CONF_LLH_LEN 0 -#ifndef UIP_CONF_RECEIVE_WINDOW -#define UIP_CONF_RECEIVE_WINDOW 48 -#endif -#ifndef UIP_CONF_TCP_MSS -#define UIP_CONF_TCP_MSS 48 -#endif #define UIP_CONF_MAX_CONNECTIONS 4 #define UIP_CONF_MAX_LISTENPORTS 8 #define UIP_CONF_UDP_CONNS 12 @@ -230,10 +235,27 @@ typedef unsigned long rtimer_clock_t; #define CFS_CONF_OFFSET_TYPE long +#ifndef UIP_CONF_BUFFER_SIZE +#define UIP_CONF_BUFFER_SIZE 1600 +#endif + +#ifndef UIP_CONF_TCP_MSS +#define UIP_CONF_TCP_MSS (UIP_CONF_BUFFER_SIZE - 70) +#endif + +#ifndef UIP_CONF_RECEIVE_WINDOW +#define UIP_CONF_RECEIVE_WINDOW (UIP_CONF_BUFFER_SIZE - 70) +#endif + +#define RF_CHANNEL 26 +#define IEEE802154_CONF_PANID 0xABCD +#define NETSTACK_RADIO_MAX_PAYLOAD_LEN 125 + /* include the project config */ /* PROJECT_CONF_H might be defined in the project Makefile */ #ifdef PROJECT_CONF_H #include PROJECT_CONF_H #endif /* PROJECT_CONF_H */ + #endif /* CONTIKI_CONF_H_ */ diff --git a/platform/cooja/contiki-cooja-main.c b/platform/cooja/contiki-cooja-main.c index 084c605cc..eddfe1adf 100644 --- a/platform/cooja/contiki-cooja-main.c +++ b/platform/cooja/contiki-cooja-main.c @@ -40,6 +40,7 @@ #include #include "contiki.h" +#include "sys/cc.h" #include "sys/clock.h" #include "sys/etimer.h" @@ -136,8 +137,6 @@ long referenceVar; static struct cooja_mt_thread rtimer_thread; static struct cooja_mt_thread process_run_thread; -#define MIN(a, b) ( (a)<(b) ? (a) : (b) ) - /*---------------------------------------------------------------------------*/ #if NETSTACK_CONF_WITH_IPV4 static void diff --git a/platform/exp5438/hal_lcd.h b/platform/exp5438/hal_lcd.h index 5d76c6c6a..6842c4952 100644 --- a/platform/exp5438/hal_lcd.h +++ b/platform/exp5438/hal_lcd.h @@ -37,18 +37,6 @@ #ifndef HAL_LCD_H #define HAL_LCD_H -#ifndef MIN -# define MIN(n, m) (((n) < (m)) ? (n) : (m)) -#endif - -#ifndef MAX -# define MAX(n, m) (((n) < (m)) ? (m) : (n)) -#endif - -#ifndef ABS -# define ABS(n) (((n) < 0) ? -(n) : (n)) -#endif - #define LCD_BACKLT_OUT P8OUT #define LCD_BACKLT_DIR P8DIR #define LCD_BACKLT_SEL P8SEL diff --git a/platform/mbxxx/contiki-conf.h b/platform/mbxxx/contiki-conf.h index f6b51612e..1d2b17322 100644 --- a/platform/mbxxx/contiki-conf.h +++ b/platform/mbxxx/contiki-conf.h @@ -128,12 +128,6 @@ #define UIP_CONF_UDP 1 -#if (WITH_COAP==7) || (WITH_COAP==6) || (WITH_COAP==3) -#define UIP_CONF_TCP 0 -#else -#define UIP_CONF_TCP 1 -#endif /* WITH_COAP */ - #define UIP_CONF_ROUTER 1 #define UIP_CONF_ND6_SEND_RA 0 diff --git a/platform/native/Makefile.native b/platform/native/Makefile.native index 460610a6a..198dbabee 100644 --- a/platform/native/Makefile.native +++ b/platform/native/Makefile.native @@ -42,4 +42,4 @@ CURSES_LIBS ?= -lncurses TARGET_LIBFILES += $(CURSES_LIBS) -MODULES+=core/net core/net/mac core/ctk core/net/llsec +MODULES+=core/net core/net/mac core/ctk core/net/llsec core/net/ip64-addr/ diff --git a/platform/remote/Makefile.remote b/platform/remote/Makefile.remote new file mode 100644 index 000000000..a9acc1dbc --- /dev/null +++ b/platform/remote/Makefile.remote @@ -0,0 +1,46 @@ +# Remote platform makefile + +ifndef CONTIKI + $(error CONTIKI not defined! You must specify where CONTIKI resides!) +endif + +PYTHON = python +BSL_FLAGS += -e -w -v -b 115200 + +ifdef PORT + BSL_FLAGS += -p $(PORT) +endif + +CONTIKI_TARGET_DIRS = . dev + +CONTIKI_TARGET_SOURCEFILES += leds.c leds-arch.c +CONTIKI_TARGET_SOURCEFILES += contiki-main.c +CONTIKI_TARGET_SOURCEFILES += sensors.c remote-sensors.c +CONTIKI_TARGET_SOURCEFILES += button-sensor.c antenna-sw.c +CONTIKI_TARGET_SOURCEFILES += phidget-sensor.c tmp102.c + +CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES) + +CLEAN += *.remote + +### 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 + +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 diff --git a/platform/remote/README.md b/platform/remote/README.md new file mode 100644 index 000000000..7172ebd02 --- /dev/null +++ b/platform/remote/README.md @@ -0,0 +1,283 @@ +Zolertia Re-Mote platform +============================================ + + + +The Re-Mote platform is a IoT Hardware development platform based on TI's CC2538 +system on chip (SoC), featuring an ARM Cortex-M3 with 512KB flash, 32Kb RAM, +double RF interface, and the following goodies: + +* ISM 2.4-GHz IEEE 802.15.4 & Zigbee compliant. +* ISM 868-, 915-, 920-, 950-MHz ISM/SRD Band. +* AES-128/256, SHA2 Hardware Encryption Engine. +* ECC-128/256, RSA Hardware Acceleration Engine for Secure Key Exchange. +* Power consumption down to 3uA using our shutdown mode. +* Co-Processor to allow peripheral management, programming over BSL without requiring to press any button to enter bootloader mode. +* Built-in battery charger (500mA), Energy Harvesting and Solar Panels to be connected to standards LiPo batteries. +* Power input with wide range 2-26VDC. +* Built-in TMP102 temperature sensor +* Small form-factor (as the Z1 mote, half the size of an Arduino) 57x35 mm. + + +Port Features +============= +The platform has the following key features: + + * Deep Sleep support with RAM retention for ultra-low energy consumption. + * Native USB support (CDC-ACM). SLIP over UART for border routers is no longer a bottleneck. + * DMA transfers for increased performance (RAM to/from RF, RAM to/from USB). + * Shutdown mode controlled externally by the Co-processor, completely power the + platform OFF, further reducing current consumption. + +In terms of hardware support, the following drivers have been implemented: + + * CC2538 System-on-Chip: + * Standard Cortex M3 peripherals (NVIC, SCB, SysTick) + * Sleep Timer (underpins rtimers) + * SysTick (underpins the platform clock and Contiki's timers infrastructure) + * RF + * 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. NB: GPT0 is in use by the platform code, the remaining GPTs are available for application development. + * ADC + * Cryptoprocessor (AES-CCM-256, SHA-256) + * LEDs + * Buttons + * Internal/external 2.4GHz antenna switch controllable by SW. + * Built-in core temperature and battery sensor. + * TMP102 temperature sensor driver. + * CC1120 sub-1GHz radio interface: + * Ported in Contiki, SPI based. + * Micro-SD external storage: + * Pending to port, SPI based. + +Requirements +============ +To start using Contiki, the following is required: + + * 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 +------------------- +Forked from `platform/cc2538dk/README.md`. +The toolchain used to build contiki is arm-gcc, also used by other arm-based Contiki ports. If you are using Instant Contiki, you will have a version pre-installed in your system. To find out if this is the case, try this: + + $ arm-none-eabi-gcc -v + Using built-in specs. + Target: arm-none-eabi + Configured with: /scratch/julian/lite-respin/eabi/src/gcc-4.3/configure + ... + (skip) + ... + Thread model: single + gcc version 4.3.2 (Sourcery G++ Lite 2008q3-66) + +The platform is currently being used/tested with the following toolchains: + +* GNU Tools for ARM Embedded Processors. This is the recommended version. Works nicely on OS X. +* Alternatively, you can use this older version for Linux. At the time of writing, this is the version used by Contiki's regression tests. + +Drivers +------- +The Re-Mote features a FTDI serial-to-USB module, the driver is commonly found in most OS, but if required it can be downloaded +from + + +### For the CC2538EM (USB CDC-ACM) +The Re-Mote has built-in support for USB 2.0 USB, Vendor and Product IDs are the following: + + * VID 0x0451 + * PID 0x16C8 + +The implementation in Contiki is pure CDC-ACM: The Linux and OS X kernels know exactly what to do and drivers are not required. + +On windows, you will need to provide a driver: + + * Download this LUFA CDC-ACM driver: + + * Adjust the VID and PID near the end with the values at the start of this section. + * Next time you get prompted for the driver, include the directory containing the .inf file in the search path and the driver will be installed. + +### Device Enumerations +For the UART, serial line settings are 115200 8N1, no flow control. + +Once all drivers have been installed correctly: + +On windows, devices will appear as a virtual COM port. + +On Linux and OS X, devices will appear under `/dev/`. + +On OS X: + +* XDS backchannel: `tty.usbserial-` +* EM in CDC-ACM: `tty.usbmodemf` (X a letter, ABC a number e.g. `tty.usbmodemfd121`) + +On Linux: + +* Re-Mote over FTDI: `ttyUSB1` +* Re-Mote over USB driver (in CDC-ACM): `ttyACMn` (n=0, 1, ....) + +Software to Program the Nodes +----------------------------- +The Re-Mote can be programmed via the jtag interface or via the serial boot loader on the chip. + +* On Windows: + * Nodes can be programmed with TI's ArmProgConsole or the [SmartRF Flash Programmer 2][smart-rf-flashprog]. The README should be self-explanatory. With ArmProgConsole, upload the file with a `.bin` extension. (jtag + serial) + * Nodes can also be programmed via the serial boot loader in the cc2538. In `tools/cc2538-bsl/` you can find `cc2538-bsl.py` this is a python script that 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. (serial) + +* On Linux: + * Nodes can be programmed with TI's [UniFlash] tool. With UniFlash, use the file with `.elf` extension. (jtag + serial) + * Nodes can also be programmed via the serial boot loader in the cc2538. No extra software needs to be installed. (serial) + +* On OSX: + * The `cc2538-bsl.py` script in `tools/cc2538-bsl/` is the only option. No extra software needs to be installed. (serial) + +The file with a `.remote` extension is a copy of the `.elf` file. + +Use the Port +============ +The following examples are intended to work off-the-shelf: + +* Examples under `examples/remote` +* 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 `remote-demo`, it is a simple example that walkthroughs the platform features, such as +the built-in sensors, LEDs, user button operation modes (press, release, hold-press), radio (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=remote savetarget` + +Then you can just run `make` to compile an application, otherwise you will need to do `make TARGET=remote`. + +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, or just let the Co-Processor detect the flash sequence and do it on your behalf, as simple as not pressing anything at all! + +Then use `make remote-demo.upload PORT=/dev/ttyUSB1`. + +The `PORT` argument is used to specify in which port the device is connected, as we are currently using a dual-channel FTDI chip, at the moment the programming channel is always assigned to the second FTDI channel, so the FTDI will enumerate as `/dev/ttyUSB0`, `/dev/ttyUSB1`, and we would need to use the later one and specify when flashing using the `cc2538-bsl` script, as it will use the first port found by default. This will be improved in the next release. + +To manually enable the boot loader, press the `reset` button on the board while holding the `user` button. (The boot loader backdoor needs to be enabled on the chip for this to work, see README in the `tools/cc2538-bsl` directory for more info) + +To generate an assembly listing of the compiled firmware, run `make remote-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 remote-demo.lst`. + +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`. + +NOTE: If you are using PG2 version of the Evaluation Module, the SoC will refuse to enter Power Modes 1+ if the debugger is connected and will always enter PM0 regardless of configuration. In order to get real low power mode functionality, make sure the debugger is disconnected. The Battery Board is ideal to test this. + +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 16MB instead of 32MB. + +### 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. + +### Shutdown Mode +The Re-Mote allows to further reduce power consumption by shutting down entirely all the components but the Co-Processor, powering completely of the CC2538 and CC1120 even preventing quiescent current from being drawn, allowing the platform to awake after a given period governed by the Co-Processor and the built-in battery management IC. This effectively reduces the power consumption down to 3-4uA. + +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/remote/Makefile.remote`. + +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/remote core cpu/cc2538 examples/remote examples/cc2538dk" + +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` + +More Reading +============ +1. [Zolertia Re-Mote website][remote-site] +2. [CC2538 System-on-Chip Solution for 2.4-GHz IEEE 802.15.4 and ZigBee®/ZigBee IP® Applications, (SWRU319B)][cc2538] +3. [CC1120 sub-1GHz RF transceiver][cc1120] + +[remote-site]: http://www.zolertia.io/products "Zolertia Re-Mote" +[cc1120]: http://www.ti.com/cc1120 "CC1120" +[smart-rf-studio]: http://www.ti.com/tool/smartrftm-studio "SmartRF Studio" +[smart-rf-flashprog]: http://www.ti.com/tool/flash-programmer "SmartRF Flash Programmer" +[cc2538]: http://www.ti.com/product/cc2538 "CC2538" +[uniflash]: http://processors.wiki.ti.com/index.php/Category:CCS_UniFlash "UniFlash" +[pandoc]: http://johnmacfarlane.net/pandoc/ "Pandoc - a universal document converter" diff --git a/platform/remote/contiki-conf.h b/platform/remote/contiki-conf.h new file mode 100644 index 000000000..959e5fe4b --- /dev/null +++ b/platform/remote/contiki-conf.h @@ -0,0 +1,525 @@ +/** + * \addtogroup remote + * @{ + * + * \file + * Configuration for the Re-Mote 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_LT to override this + */ +typedef uint32_t rtimer_clock_t; +#define RTIMER_CLOCK_LT(a,b) ((int32_t)((a)-(b)) < 0) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \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 */ + +/* This can be overriden to use the cc1120_driver instead */ +#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 2 +#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 25 +#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 +#define RPL_CONF_MAX_DAG_ENTRIES 1 +#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] = 0xaa; \ + addr_contexts[0].prefix[1] = 0xaa; \ +} +#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 */ +/** @} */ +/*---------------------------------------------------------------------------*/ + +#endif /* CONTIKI_CONF_H_ */ + +/** @} */ diff --git a/platform/remote/contiki-main.c b/platform/remote/contiki-main.c new file mode 100644 index 000000000..562af4e66 --- /dev/null +++ b/platform/remote/contiki-main.c @@ -0,0 +1,244 @@ +/* + * 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 platform + * @{ + * + * \defgroup remote Zolertia Re-Mote platform + * + * The Re-Mote is the new platform by Zolertia based on the cc2538, featuring a + * cc2538 SoC with an ARM Cortex-M3 core plus the CC1120 Sub-1Ghz transceiver + * @{ + * + * \file + * Main module for the Re-Mote 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/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 "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 "cpu.h" +#include "reg.h" +#include "ieee-addr.h" +#include "lpm.h" +#include "dev/antenna-sw.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 +/*---------------------------------------------------------------------------*/ +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 Re-Mote platform + */ +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(); + SENSORS_ACTIVATE(button_sensor); + + /* + * Character I/O Initialisation. + * When the UART receives a character it will call serial_line_input_byte to + * notify the core. The same applies for the USB driver. + * + * If slip-arch is also linked in afterwards (e.g. if we are a border router) + * it will overwrite one of the two peripheral input callbacks. Characters + * received over the relevant peripheral will be handled by + * slip_input_byte instead + */ +#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 + + serial_line_init(); + + INTERRUPTS_ENABLE(); + fade(LEDS_BLUE); + + PUTS(CONTIKI_VERSION_STRING); + PUTS(BOARD_STRING); + + PRINTF(" Net: "); + PRINTF("%s\n", NETSTACK_NETWORK.name); + PRINTF(" MAC: "); + PRINTF("%s\n", NETSTACK_MAC.name); + PRINTF(" RDC: "); + PRINTF("%s\n", NETSTACK_RDC.name); + + /* Initialise the H/W RNG engine. */ + random_init(0); + + udma_init(); + + process_start(&etimer_process, NULL); + ctimer_init(); + + set_rf_params(); + netstack_init(); + +#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 */ + + antenna_sw_config(); + + 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 { + /* Reset watchdog and handle polls and events */ + watchdog_periodic(); + + r = process_run(); + } while(r > 0); + + /* We have serviced all pending events. Enter a Low-Power mode. */ + lpm_enter(); + } +} +/*---------------------------------------------------------------------------*/ + +/** + * @} + * @} + */ diff --git a/platform/remote/dev/antenna-sw.c b/platform/remote/dev/antenna-sw.c new file mode 100644 index 000000000..6d320fedc --- /dev/null +++ b/platform/remote/dev/antenna-sw.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2015, 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. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup remote-antenna + * @{ + * + * Driver for the Re-Mote 2.4Ghz antenna switch, to enable either the internal + * ceramic antenna or an external one connected to the uFL connector + * @{ + * + * \file + * Driver for the Re-Mote 2.4Ghz antenna switch + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio.h" +#include "antenna-sw.h" + +#include +/*---------------------------------------------------------------------------*/ +#define ANTENNA_2_4GHZ_SW_PORT_BASE GPIO_PORT_TO_BASE(ANTENNA_2_4GHZ_SW_PORT) +#define ANTENNA_2_4GHZ_SW_PIN_MASK GPIO_PIN_MASK(ANTENNA_2_4GHZ_SW_PIN) +/*---------------------------------------------------------------------------*/ +static uint8_t initialized = 0; +/*---------------------------------------------------------------------------*/ +void +antenna_sw_config(void) +{ + /* Software controlled */ + GPIO_SOFTWARE_CONTROL(ANTENNA_2_4GHZ_SW_PORT_BASE, + ANTENNA_2_4GHZ_SW_PIN_MASK); + + /* Set pin to output */ + GPIO_SET_OUTPUT(ANTENNA_2_4GHZ_SW_PORT_BASE, ANTENNA_2_4GHZ_SW_PIN_MASK); + + /* Set the antenna selector to a default position */ + GPIO_CLR_PIN(ANTENNA_2_4GHZ_SW_PORT_BASE, ANTENNA_2_4GHZ_SW_PIN_MASK); + + initialized = 1; +} +/*---------------------------------------------------------------------------*/ +int +antenna_sw_select(uint8_t val) +{ + if(!initialized) { + return ANTENNA_SW_SELECT_ERROR; + } + + if(val != ANTENNA_SW_SELECT_INTERNAL && val != ANTENNA_SW_SELECT_EXTERNAL) { + return ANTENNA_SW_SELECT_ERROR; + } + + /* Set the antenna selector */ + GPIO_WRITE_PIN(ANTENNA_2_4GHZ_SW_PORT_BASE, ANTENNA_2_4GHZ_SW_PIN_MASK, val); + + return val; +} +/*---------------------------------------------------------------------------*/ + +/** + * @} + * @} + */ diff --git a/platform/remote/dev/antenna-sw.h b/platform/remote/dev/antenna-sw.h new file mode 100644 index 000000000..a93f580d3 --- /dev/null +++ b/platform/remote/dev/antenna-sw.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015, 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. + */ +/* -------------------------------------------------------------------------- */ +/** + * \addtogroup remote + * @{ + * + * \defgroup remote-antenna Re-Mote Antenna switch + * + * Driver for the Re-Mote 2.4Ghz antenna switch, to enable either the internal + * ceramic antenna or an external one connected to the uFL connector + * @{ + * + * \file + * Header file for the Re-Mote 2.4Ghz antenna switch Driver + */ +/* -------------------------------------------------------------------------- */ +#ifndef ANTENNA_SW_H_ +#define ANTENNA_SW_H_ +/* -------------------------------------------------------------------------- */ +#include +/* -------------------------------------------------------------------------- */ +#define ANTENNA_SW_SELECT_EXTERNAL 0xFF +#define ANTENNA_SW_SELECT_INTERNAL 0x00 + +#define ANTENNA_SW_SELECT_ERROR -1 +/* -------------------------------------------------------------------------- */ +/** + * \brief Init function for the antenna switch + * + * The Re-Mote platform allows to programatically select between the 2.4Ghz + * internal or external antenna. + * The function is set to enable using the internal ceramic antenna as default, + * it should be called from the contiki-main initialization process. + * + * \return ignored + */ +void antenna_sw_config(void); + +/** + * \brief Function to select between the internal or external 2.4Ghz antenna + * + * \param val Select antenna. + * External: ANTENNA_SW_SELECT_EXTERNAL or + * Internal (ceramic): ANTENNA_SW_SELECT_INTERNAL + * \return the selected antenna position, or ANTENNA_SW_SELECT_ERROR if not + * previously configured + */ +int antenna_sw_select(uint8_t val); +/* -------------------------------------------------------------------------- */ +#endif /* ifndef ANTENNA_SW_H_ */ +/* -------------------------------------------------------------------------- */ +/** + * @} + * @} + */ diff --git a/platform/remote/dev/board.h b/platform/remote/dev/board.h new file mode 100644 index 000000000..71c9b28c3 --- /dev/null +++ b/platform/remote/dev/board.h @@ -0,0 +1,278 @@ +/* + * 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 + * @{ + * + * \defgroup remote-peripherals Re-Mote Peripherals + * + * Defines related to the Re-Mote + * + * This file provides connectivity information on LEDs, Buttons, UART and + * other Re-Mote peripherals + * + * This file can be used as the basis to configure other platforms using the + * cc2538 SoC. + * @{ + * + * \file + * Header file with definitions related to the I/O connections on the Zolertia's + * Re-Mote platform, cc2538-based + * + * \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 Re-Mote LED configuration + * + * LEDs on the Re-mote are connected as follows: + * - LED1 (Red) -> PD2 + * - LED2 (Blue) -> PC3 + * - LED3 (Green) -> PD5 + * + * LED1 routed also to JP5 connector + * LED2 shares the same pin with Watchdog WDI pulse and routed to JP8 connector + * LED3 routed also to JP5 connector + * @{ + */ +/*---------------------------------------------------------------------------*/ +/* 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_BLUE +#undef LEDS_RED +#undef LEDS_CONF_ALL + +/* In leds.h the LEDS_BLUE is defined by LED_YELLOW definition */ +#define LEDS_GREEN 1 /**< LED1 (Green) -> PD5 */ +#define LEDS_BLUE 2 /**< LED2 (Blue) -> PC3 */ +#define LEDS_RED 4 /**< LED3 (Red) -> PD2 */ + +#define LEDS_CONF_ALL 7 + +#define LEDS_LIGHT_BLUE (LEDS_GREEN | LEDS_BLUE) /**< Green + Blue (3) */ +#define LEDS_YELLOW (LEDS_GREEN | LEDS_RED) /**< Green + Red (5) */ +#define LEDS_PURPLE (LEDS_BLUE | LEDS_RED) /**< Blue + Red (6) */ +#define LEDS_WHITE LEDS_ALL /**< Green + Blue + Red (7) */ + +/* Notify various examples that we have LEDs */ +#define PLATFORM_HAS_LEDS 1 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name USB configuration + * + * The USB pullup is enabled by an external resistor, not mapped to a GPIO + */ +#ifdef USB_PULLUP_PORT +#undef USB_PULLUP_PORT +#endif +#ifdef USB_PULLUP_PIN +#undef USB_PULLUP_PIN +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name UART configuration + * + * On the Re-Mote, the UART is connected to the following ports/pins + * - UART0: + * - RX: PA0 + * - TX: PA1 + * - UART1: + * - RX: PC6 + * - TX: PC5 + * - CTS: + * - RTS: + * We configure the port to use UART0 and UART1, CTS/RTS only for UART1, + * both without a HW pull-up resistor + * @{ + */ +#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_C_NUM +#define UART1_RX_PIN 6 +#define UART1_TX_PORT GPIO_C_NUM +#define UART1_TX_PIN 5 +#define UART1_CTS_PORT GPIO_C_NUM +#define UART1_CTS_PIN 1 +#define UART1_RTS_PORT GPIO_C_NUM +#define UART1_RTS_PIN 2 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name Re-Mote Button configuration + * + * Buttons on the Re-Mote are connected as follows: + * - BUTTON_USER -> PA3, S1 user button, shared with bootloader + * - BUTTON_RESET -> RESET_N line, S2 reset both CC2538 and CoP + * - BUTTON_VBAT -> Power switch, not mounted by default + * @{ + */ +/** 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 + * + * These values configure which CC2538 pins and ADC channels to use for the ADC + * inputs. By default the Re-Mote allows two out-of-the-box ADC ports with a + * phidget-like 3-pin connector (GND/3V3/ADC) + * + * ADC inputs can only be on port A. + * @{ + */ +#define ADC_PHIDGET_PORT GPIO_A_NUM /**< Phidget GPIO control port */ +#define ADC_PHIDGET_ADC2_PIN 6 /**< ADC2 to PA6, 3V3 */ +#define ADC_PHIDGET_ADC3_PIN 7 /**< ADC3 to PA7, 3V3 */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name SPI (SSI0) configuration + * + * These values configure which CC2538 pins to use for the SPI (SSI0) lines, + * shared with the CC1120 RF transceiver + * TX -> MOSI, RX -> MISO + * @{ + */ +#define SPI0_CLK_PORT GPIO_D_NUM +#define SPI0_CLK_PIN 1 +#define SPI0_TX_PORT GPIO_D_NUM +#define SPI0_TX_PIN 0 +#define SPI0_RX_PORT GPIO_C_NUM +#define SPI0_RX_PIN 4 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name SPI (SSI1) configuration + * + * These values configure which CC2538 pins to use for the SPI (SSI1) lines, + * shared with the microSD, not routed anywhere. + * TX -> MOSI, RX -> MISO + * @{ + */ +#define SPI1_CLK_PORT GPIO_B_NUM +#define SPI1_CLK_PIN 5 +#define SPI1_TX_PORT GPIO_C_NUM +#define SPI1_TX_PIN 7 +#define SPI1_RX_PORT GPIO_A_NUM +#define SPI1_RX_PIN 4 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name I2C configuration + * + * These values configure which CC2538 pins to use for the I2C lines, shared + * with the TMP102 built-in temperature sensor + * @{ + */ +#define I2C_SCL_PORT GPIO_B_NUM +#define I2C_SCL_PIN 1 +#define I2C_SDA_PORT GPIO_B_NUM +#define I2C_SDA_PIN 0 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Antenna switch configuration + * + * These values configure the required pin to drive the antenna switch, to + * use either the built-in ceramic antenna or an external one over the uFL + * connector + * - Internal antenna: LOW + * - External antenna: HIGH + * @{ + */ +#define ANTENNA_2_4GHZ_SW_PORT GPIO_D_NUM +#define ANTENNA_2_4GHZ_SW_PIN 4 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name CC1120/CC1200 configuration + * + * These values configure the required pins to drive the CC1120/CC1200 + * @{ + */ +#define CC1120_SPI_SCLK_PORT SPI0_CLK_PORT +#define CC1120_SPI_SCLK_PIN SPI0_CLK_PIN +#define CC1120_SPI_MOSI_PORT SPIO0_TX_PORT +#define CC1120_SPI_MOSI_PIN SPIO0_TX_PIN +#define CC1120_SPI_MISO_PORT SPIO0_RX_PORT +#define CC1120_SPI_MISO_PIN SPIO0_RX_PIN +#define CC1120_SPI_CSN_PORT GPIO_D_NUM +#define CC1120_SPI_CSN_PIN 3 +#define CC1120_GDO0_PORT GPIO_B_NUM +#define CC1120_GDO0_PIN 4 +#define CC1120_GDO2_PORT GPIO_B_NUM +#define CC1120_GDO2_PIN 3 +#define CC1120_RESET_PORT GPIO_B_NUM +#define CC1120_RESET_PIN 2 +#define CC1120_GPIO0_VECTOR NVIC_INT_GPIO_PORT_B +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name microSD configuration + * + * These values configure the required pins to drive the built-in microSD + * external module, to be used with SSI1 + * @{ + */ +#define USD_CLK_PORT SPI1_CLK_PORT +#define USD_CLK_PIN SPI1_CLK_PIN +#define USD_MOSI_PORT SPI1_TX_PORT +#define USD_MOSI_PIN SPI1_TX_PIN +#define USD_MISO_PORT SPI1_RX_PORT +#define USD_MISO_PIN SPI1_RX_PIN +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name Device string used on startup + * @{ + */ +#define BOARD_STRING "Zolertia Re-Mote platform" +/** @} */ + +#endif /* BOARD_H_ */ + +/** + * @} + * @} + */ diff --git a/platform/remote/dev/button-sensor.c b/platform/remote/dev/button-sensor.c new file mode 100644 index 000000000..4433f3e06 --- /dev/null +++ b/platform/remote/dev/button-sensor.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, 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 remote-button-sensor + * @{ + * + * \file + * Driver for the Re-Mote 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/remote/dev/button-sensor.h b/platform/remote/dev/button-sensor.h new file mode 100644 index 000000000..817769591 --- /dev/null +++ b/platform/remote/dev/button-sensor.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, 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 remote-sensors + * @{ + * + * \defgroup remote-button-sensor Re-Mote User Button Driver + * + * Driver for the Re-Mote user button + * + * The Re-Mote button will generate a sensors_changed event on press as well + * as on release. + * + * Unlike many other platforms, the Re-Mote user button has the ability to + * generate events when the user keeps the button pressed. The user can + * configure the button driver with a timer interval in clock ticks. When the + * button is kept pressed, the driver will then generate a broadcast event + * each time the interval passes. For example the driver can be configured to + * generate an event every second while the button is kept pressed. This + * functionality can be enabled through the configure() function, by passing + * BUTTON_SENSOR_CONFIG_TYPE_INTERVAL as the type argument. + * @{ + * + * \file + * Header file for the Re-Mote User 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/remote/dev/led-strip.c b/platform/remote/dev/led-strip.c new file mode 100644 index 000000000..a13ad23a8 --- /dev/null +++ b/platform/remote/dev/led-strip.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2015, 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. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup remote-led-strip + * @{ + * + * Driver to control a bright LED strip powered at 3VDC, drawing power directly + * from the battery power supply. An example on how to adapt 12VDC LED strips + * to 3VDC is provided at http://www.hackster.io/zolertia + * @{ + * + * \file + * Driver for the Re-Mote bright LED strip Driver + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio.h" +#include "led-strip.h" + +#include +/*---------------------------------------------------------------------------*/ +#ifndef LED_STRIP_PORT +#define LED_STRIP_PORT GPIO_A_NUM +#endif +#ifndef LED_STRIP_PIN +#define LED_STRIP_PIN 6 +#endif +#define LED_STRIP_PORT_BASE GPIO_PORT_TO_BASE(LED_STRIP_PORT) +#define LED_STRIP_PIN_MASK GPIO_PIN_MASK(LED_STRIP_PIN) +/*---------------------------------------------------------------------------*/ +static uint8_t initialized = 0; +/*---------------------------------------------------------------------------*/ +void +led_strip_config(void) +{ + /* Software controlled */ + GPIO_SOFTWARE_CONTROL(LED_STRIP_PORT_BASE, LED_STRIP_PIN_MASK); + /* Set pin to output */ + GPIO_SET_OUTPUT(LED_STRIP_PORT_BASE, LED_STRIP_PIN_MASK); + /* Set the antenna selector to a default position */ + GPIO_SET_PIN(LED_STRIP_PORT_BASE, LED_STRIP_PIN_MASK); + + initialized = 1; +} +/*---------------------------------------------------------------------------*/ +int +led_strip_switch(uint8_t val) +{ + if(!initialized) { + return LED_STRIP_ERROR; + } + + if(val != LED_STRIP_ON && val != LED_STRIP_OFF) { + return LED_STRIP_ERROR; + } + + /* Set the LED to ON or OFF */ + GPIO_WRITE_PIN(LED_STRIP_PORT_BASE, LED_STRIP_PIN_MASK, val); + + return val; +} +/*---------------------------------------------------------------------------*/ +int +led_strip_get(void) +{ + if(!initialized) { + return LED_STRIP_ERROR; + } + + /* Inverse logic, return ON if the pin is low */ + if(GPIO_READ_PIN(LED_STRIP_PORT_BASE, LED_STRIP_PIN_MASK)) { + return LED_STRIP_OFF; + } + return LED_STRIP_ON; +} +/*---------------------------------------------------------------------------*/ + +/** + * @} + * @} + */ + diff --git a/platform/remote/dev/led-strip.h b/platform/remote/dev/led-strip.h new file mode 100644 index 000000000..27880668a --- /dev/null +++ b/platform/remote/dev/led-strip.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2015, 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. + */ +/* -------------------------------------------------------------------------- */ +/** + * \addtogroup remote-sensors + * @{ + * + * \defgroup remote-led-strip Re-Mote LED strip driver + * + * Driver to control a bright LED strip powered at 3VDC, drawing power directly + * from the battery power supply. An example on how to adapt 12VDC LED strips + * to 3VDC is provided at http://www.hackster.io/zolertia + * @{ + * + * \file + * Header file for the Re-Mote bright LED strip Driver + */ +/* -------------------------------------------------------------------------- */ +#ifndef LED_STRIP_H_ +#define LED_STRIP_H_ +/* -------------------------------------------------------------------------- */ +#include +/* -------------------------------------------------------------------------- */ +#define LED_STRIP_OFF 0xFF +#define LED_STRIP_ON 0x00 + +#define LED_STRIP_ERROR -1 +/* -------------------------------------------------------------------------- */ +/** + * \brief Init function for the bright LED strip driver + * + * The LED strip driver allows to lighten up any application using up to 4 + * LEDs 3VDC-powered per strip + * The function is set to power OFF the LEDs as default, + * it should be called from the contiki-main initialization process. + * + * \return ignored + */ +void led_strip_config(void); + +/** + * \brief Function to turn ON/OFF the LED strip + * + * \param val Set ON/OFF (LED_STRIP_ON or LED_STRIP_OFF) + * \return the selected antenna position, or LED_STRIP_ERROR if not + * previously configured + */ +int led_strip_switch(uint8_t val); + +/** + * \brief Function to get the LED strip current state + * + * \return Current LED strip state or LED_STRIP_ERROR if not + * previously configured + */ +int led_strip_get(void); +/* -------------------------------------------------------------------------- */ +#endif /* ifndef LED_STRIP_H_ */ +/* -------------------------------------------------------------------------- */ +/** + * @} + * @} + */ + diff --git a/platform/remote/dev/leds-arch.c b/platform/remote/dev/leds-arch.c new file mode 100644 index 000000000..a120e4144 --- /dev/null +++ b/platform/remote/dev/leds-arch.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, 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 remote + * @{ + * + * \defgroup remote-leds Re-Mote LED driver + * + * LED driver implementation for the Re-Mote platform + * @{ + * + * \file + * LED driver implementation for the Re-Mote platform + */ +#include "contiki.h" +#include "reg.h" +#include "dev/leds.h" +#include "dev/gpio.h" +/*---------------------------------------------------------------------------*/ +#define LED_GREEN_PORT GPIO_D_BASE +#define LED_GREEN_PIN (1 << 5) + +#define LED_BLUE_PORT GPIO_C_BASE +#define LED_BLUE_PIN (1 << 3) + +#define LED_RED_PORT GPIO_D_BASE +#define LED_RED_PIN (1 << 2) + +#define PORT_D_LEDS (LED_RED_PIN | LED_GREEN_PIN) +#define PORT_C_LEDS LED_BLUE_PIN +/*---------------------------------------------------------------------------*/ +void +leds_arch_init(void) +{ + /* Initialize LED1 (Red) and LED3 (Green) */ + GPIO_SET_OUTPUT(GPIO_D_BASE, PORT_D_LEDS); + GPIO_SET_PIN(GPIO_D_BASE, PORT_D_LEDS); + + /* Initialize LED2 - Blue */ + GPIO_SET_OUTPUT(GPIO_C_BASE, PORT_C_LEDS); + GPIO_SET_PIN(GPIO_C_BASE, PORT_C_LEDS); +} +/*---------------------------------------------------------------------------*/ +unsigned char +leds_arch_get(void) +{ + uint8_t mask_leds; + + mask_leds = GPIO_READ_PIN(LED_GREEN_PORT, LED_GREEN_PIN) == 0? LEDS_GREEN : 0; + mask_leds |= GPIO_READ_PIN(LED_BLUE_PORT, LED_BLUE_PIN) == 0? LEDS_BLUE : 0; + mask_leds |= GPIO_READ_PIN(LED_RED_PORT, LED_RED_PIN) == 0? LEDS_RED : 0; + + return mask_leds; +} +/*---------------------------------------------------------------------------*/ +void +leds_arch_set(unsigned char leds) +{ + if(leds & LEDS_GREEN) { + GPIO_CLR_PIN(LED_GREEN_PORT, LED_GREEN_PIN); + } else { + GPIO_SET_PIN(LED_GREEN_PORT, LED_GREEN_PIN); + } + + if(leds & LEDS_BLUE) { + GPIO_CLR_PIN(LED_BLUE_PORT, LED_BLUE_PIN); + } else { + GPIO_SET_PIN(LED_BLUE_PORT, LED_BLUE_PIN); + } + + if(leds & LEDS_RED) { + GPIO_CLR_PIN(LED_RED_PORT, LED_RED_PIN); + } else { + GPIO_SET_PIN(LED_RED_PORT, LED_RED_PIN); + } +} +/*---------------------------------------------------------------------------*/ + +/** + * @} + * @} + */ diff --git a/platform/remote/dev/mp3-wtv020sd.c b/platform/remote/dev/mp3-wtv020sd.c new file mode 100644 index 000000000..7897c3d33 --- /dev/null +++ b/platform/remote/dev/mp3-wtv020sd.c @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2015, 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. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup remote-mp3-wtv020sd + * @{ + * + * Driver to control the MP3 WTV020SD board in MP3 mode (GPIO based) and the + * 2-line serial mode (CLK/DI). Loop Mode and Key Modes not implemented. + * More product information available at: + * http://avrproject.ru/chasy-budilnik/WTV020SD.pdf + * An example on how to wire with a sound power amplifier and speakers at + * http://www.hackster.io/zolertia + * @{ + * + * \file + * Header file for the MP3 WTV020SD driver + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/gpio.h" +#include "mp3-wtv020sd.h" + +#include +/*---------------------------------------------------------------------------*/ + +/* + * The WTV020SD can be used in MP3 mode (GPIO-controlled) or 2-line mode (CLK + * and DATA line). The following pin-out can be implemented without reusing + * the pins as below (in 2-line mode the CLK/DATA functions replace the VOL+/- + * keys, others remain the same), but this would require more GPIOs to + * interface all functions, so we chose the configuration that uses the less + * number of GPIOs, and emulate all functions available in each mode + */ +#ifndef MP3_WTV020SD_P07_PORT +#define MP3_WTV020SD_P07_PORT GPIO_B_NUM +#endif +#ifndef MP3_WTV020SD_P07_PIN +#define MP3_WTV020SD_P07_PIN 0 +#endif +#ifndef MP3_WTV020SD_P02_PORT +#define MP3_WTV020SD_P02_PORT GPIO_B_NUM +#endif +#ifndef MP3_WTV020SD_P02_PIN +#define MP3_WTV020SD_P02_PIN 1 +#endif +#ifndef MP3_WTV020SD_P06_PORT +#define MP3_WTV020SD_P06_PORT GPIO_C_NUM +#endif +#ifndef MP3_WTV020SD_P06_PIN +#define MP3_WTV020SD_P06_PIN 1 +#endif +#ifndef MP3_WTV020SD_P04_PORT +#define MP3_WTV020SD_P04_PORT GPIO_B_NUM +#endif +#ifndef MP3_WTV020SD_P04_PIN +#define MP3_WTV020SD_P04_PIN 0 +#endif +#ifndef MP3_WTV020SD_P05_PORT +#define MP3_WTV020SD_P05_PORT GPIO_B_NUM +#endif +#ifndef MP3_WTV020SD_P05_PIN +#define MP3_WTV020SD_P05_PIN 1 +#endif +#ifndef MP3_WTV020SD_RESET_PORT +#define MP3_WTV020SD_RESET_PORT GPIO_B_NUM +#endif +#ifndef MP3_WTV020SD_RESET_PIN +#define MP3_WTV020SD_RESET_PIN 1 +#endif + +/* The BUSY pin is shared between operation modes */ +#define MP3_BUSY_PORT_BASE GPIO_PORT_TO_BASE(MP3_WTV020SD_P06_PORT) +#define MP3_BUSY_PIN_MASK GPIO_PIN_MASK(MP3_WTV020SD_P06_PIN) + +#define MP3_PLAY_PORT_BASE GPIO_PORT_TO_BASE(MP3_WTV020SD_P07_PORT) +#define MP3_PLAY_PIN_MASK GPIO_PIN_MASK(MP3_WTV020SD_P07_PIN) +#define MP3_NEXT_PORT_BASE GPIO_PORT_TO_BASE(MP3_WTV020SD_P02_PORT) +#define MP3_NEXT_PIN_MASK GPIO_PIN_MASK(MP3_WTV020SD_P02_PIN) + +#define MP3_RESET_PORT_BASE GPIO_PORT_TO_BASE(MP3_WTV020SD_RESET_PORT) +#define MP3_RESET_PIN_MASK GPIO_PIN_MASK(MP3_WTV020SD_RESET_PIN) +#define MP3_CLK_PORT_BASE GPIO_PORT_TO_BASE(MP3_WTV020SD_P04_PORT) +#define MP3_CLK_PIN_MASK GPIO_PIN_MASK(MP3_WTV020SD_P04_PIN) +#define MP3_DATA_PORT_BASE GPIO_PORT_TO_BASE(MP3_WTV020SD_P05_PORT) +#define MP3_DATA_PIN_MASK GPIO_PIN_MASK(MP3_WTV020SD_P05_PIN) + +/*---------------------------------------------------------------------------*/ +static uint8_t initialized = 0; +static int mp3_line_command(uint16_t cmd); +/*---------------------------------------------------------------------------*/ +int +mp3_wtv020sd_config(uint8_t mode) +{ + if(mode != MP3_WTV020SD_GPIO_MODE && mode != MP3_WTV020SD_LINE_MODE) { + return MP3_WTV020SD_ERROR; + } + + if(mode == MP3_WTV020SD_GPIO_MODE) { + GPIO_SOFTWARE_CONTROL(MP3_PLAY_PORT_BASE, MP3_PLAY_PIN_MASK); + GPIO_SET_OUTPUT(MP3_PLAY_PORT_BASE, MP3_PLAY_PIN_MASK); + GPIO_SET_PIN(MP3_PLAY_PORT_BASE, MP3_PLAY_PIN_MASK); + GPIO_SOFTWARE_CONTROL(MP3_NEXT_PORT_BASE, MP3_NEXT_PIN_MASK); + GPIO_SET_OUTPUT(MP3_NEXT_PORT_BASE, MP3_NEXT_PIN_MASK); + GPIO_SET_PIN(MP3_NEXT_PORT_BASE, MP3_NEXT_PIN_MASK); + } else { + GPIO_SOFTWARE_CONTROL(MP3_RESET_PORT_BASE, MP3_RESET_PIN_MASK); + GPIO_SET_OUTPUT(MP3_RESET_PORT_BASE, MP3_RESET_PIN_MASK); + GPIO_SET_PIN(MP3_RESET_PORT_BASE, MP3_RESET_PIN_MASK); + GPIO_SOFTWARE_CONTROL(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK); + GPIO_SET_OUTPUT(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK); + GPIO_SET_PIN(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK); + GPIO_SOFTWARE_CONTROL(MP3_DATA_PORT_BASE, MP3_DATA_PIN_MASK); + GPIO_SET_OUTPUT(MP3_DATA_PORT_BASE, MP3_DATA_PIN_MASK); + GPIO_SET_PIN(MP3_DATA_PORT_BASE, MP3_DATA_PIN_MASK); + } + + GPIO_SOFTWARE_CONTROL(MP3_BUSY_PORT_BASE, MP3_BUSY_PIN_MASK); + GPIO_SET_INPUT(MP3_BUSY_PORT_BASE, MP3_BUSY_PIN_MASK); + + initialized = mode; + return MP3_WTV020SD_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +int +mp3_wtv020sd_gpio_play(void) +{ + if(initialized != MP3_WTV020SD_GPIO_MODE) { + return MP3_WTV020SD_ERROR; + } + GPIO_CLR_PIN(MP3_PLAY_PORT_BASE, MP3_PLAY_PIN_MASK); + return MP3_WTV020SD_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +int +mp3_wtv020sd_gpio_stop(void) +{ + if(initialized != MP3_WTV020SD_GPIO_MODE) { + return MP3_WTV020SD_ERROR; + } + GPIO_SET_PIN(MP3_PLAY_PORT_BASE, MP3_PLAY_PIN_MASK); + return MP3_WTV020SD_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +int +mp3_wtv020sd_gpio_next(void) +{ + if(initialized != MP3_WTV020SD_GPIO_MODE) { + return MP3_WTV020SD_ERROR; + } + GPIO_CLR_PIN(MP3_PLAY_PORT_BASE, MP3_PLAY_PIN_MASK); + clock_delay_usec(MP3_USEC_DELAY); + GPIO_SET_PIN(MP3_PLAY_PORT_BASE, MP3_PLAY_PIN_MASK); + return MP3_WTV020SD_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +int +mp3_wtv020sd_busy(void) +{ + if((initialized != MP3_WTV020SD_GPIO_MODE) && + (initialized != MP3_WTV020SD_LINE_MODE)) { + return MP3_WTV020SD_ERROR; + } + if(GPIO_READ_PIN(MP3_BUSY_PORT_BASE, MP3_BUSY_PIN_MASK)) { + return MP3_WTV020SD_BUSY; + } + return MP3_WTV020SD_IDLE; +} +/*---------------------------------------------------------------------------*/ +int +mp3_wtv020sd_reset(void) +{ + if(initialized != MP3_WTV020SD_LINE_MODE) { + return MP3_WTV020SD_ERROR; + } + GPIO_CLR_PIN(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK); + GPIO_SET_PIN(MP3_RESET_PORT_BASE, MP3_RESET_PIN_MASK); + GPIO_CLR_PIN(MP3_RESET_PORT_BASE, MP3_RESET_PIN_MASK); + clock_delay_usec(MP3_USEC_DELAY); + GPIO_SET_PIN(MP3_RESET_PORT_BASE, MP3_RESET_PIN_MASK); + GPIO_SET_PIN(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK); + clock_delay_usec(MP3_USEC_RESET_DELAY); + return MP3_WTV020SD_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +int +mp3_wtv020sd_sync_play(uint16_t track) +{ + if(initialized != MP3_WTV020SD_LINE_MODE) { + return MP3_WTV020SD_ERROR; + } + mp3_line_command(track); + while(mp3_wtv020sd_busy()); + return MP3_WTV020SD_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +int +mp3_wtv020sd_async_play(uint16_t track) +{ + if(initialized != MP3_WTV020SD_LINE_MODE) { + return MP3_WTV020SD_ERROR; + } + mp3_line_command(track); + return MP3_WTV020SD_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +int +mp3_wtv020sd_stop(void) +{ + if(initialized != MP3_WTV020SD_LINE_MODE) { + return MP3_WTV020SD_ERROR; + } + mp3_line_command(MP3_WTV020SD_STOP_VAL); + return MP3_WTV020SD_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +int +mp3_wtv020sd_pause(void) +{ + if(initialized != MP3_WTV020SD_LINE_MODE) { + return MP3_WTV020SD_ERROR; + } + mp3_line_command(MP3_WTV020SD_PLAY_PAUSE_VAL); + return MP3_WTV020SD_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +int +mp3_line_command(uint16_t cmd) +{ + uint16_t mask; + if(initialized != MP3_WTV020SD_LINE_MODE) { + return MP3_WTV020SD_ERROR; + } + GPIO_CLR_PIN(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK); + clock_delay_usec(MP3_USEC_CMD_DELAY / 10); + for(mask = 0x8000; mask > 0; mask >> 1) { + GPIO_CLR_PIN(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK); + clock_delay_usec(MP3_USEC_CMD_DELAY / 2); + if(cmd & mask) { + GPIO_SET_PIN(MP3_DATA_PORT_BASE, MP3_DATA_PIN_MASK); + } else { + GPIO_CLR_PIN(MP3_DATA_PORT_BASE, MP3_DATA_PIN_MASK); + } + clock_delay_usec(MP3_USEC_CMD_DELAY / 2); + GPIO_SET_PIN(MP3_CLK_PORT_BASE, MP3_CLK_PIN_MASK); + clock_delay_usec(MP3_USEC_CMD_DELAY); + if(mask > 0x0001) { + clock_delay_usec(MP3_USEC_CMD_DELAY / 10); + } + } + clock_delay_usec(MP3_USEC_CMD_DELAY / 8); + return MP3_WTV020SD_SUCCESS; +} +/*---------------------------------------------------------------------------*/ + +/** + * @} + * @} + */ diff --git a/platform/remote/dev/mp3-wtv020sd.h b/platform/remote/dev/mp3-wtv020sd.h new file mode 100644 index 000000000..15ec2c526 --- /dev/null +++ b/platform/remote/dev/mp3-wtv020sd.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2015, 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. + */ +/* -------------------------------------------------------------------------- */ +/** + * \addtogroup remote-sensors + * @{ + * + * \defgroup remote-mp3-wtv020sd Re-Mote MP3 WTV020SD driver + * + * Driver to control the MP3 WTV020SD board in MP3 mode (GPIO based) and the + * 2-line serial mode (CLK/DI). Loop Mode and Key Modes not implemented. + * More product information available at: + * http://avrproject.ru/chasy-budilnik/WTV020SD.pdf + * An example on how to wire with a sound power amplifier and speakers at + * http://www.hackster.io/zolertia + * Based on the Arduino Wtv020sd16p library + * @{ + * + * \file + * Header file for the MP3 WTV020SD driver + */ +/* -------------------------------------------------------------------------- */ +#ifndef MP3_WTV020SD_H_ +#define MP3_WTV020SD_H_ +/* -------------------------------------------------------------------------- */ +#include +/* -------------------------------------------------------------------------- */ +#define MP3_WTV020SD_ERROR -1 +#define MP3_WTV020SD_SUCCESS 0x00 +#define MP3_WTV020SD_GPIO_MODE 0x01 +#define MP3_WTV020SD_LINE_MODE 0x02 +#define MP3_WTV020SD_IDLE 0x00 +#define MP3_WTV020SD_BUSY 0x0F +/* -------------------------------------------------------------------------- */ +#define MP3_WTV020SD_PLAY_PAUSE_VAL 0xFFFE +#define MP3_WTV020SD_STOP_VAL 0xFFFF +#define MP3_WTV020SD_VOLUME_MIN 0xFFF0 +#define MP3_WTV020SD_VOLUME_MAX 0xFFF7 +/* -------------------------------------------------------------------------- */ +#define MP3_USEC_DELAY 1000 +#define MP3_USEC_CMD_DELAY 100 +#define MP3_USEC_RESET_DELAY ((MP3_USEC_DELAY) * 30) +/* -------------------------------------------------------------------------- */ +#define MP3_TRACK_BASE 0 /* 0000.ad4 */ +/* -------------------------------------------------------------------------- */ +/** + * \brief Init function for the MP3 driver + * + * Configures the pins required to operate in either driver mode + * + * \param mode drive the board using GPIOs or the two-line mode, using + * either MP3_WTV020SD_GPIO_MODE or MP3_WTV020SD_LINE_MODE + * \return MP3_WTV020SD_ERROR if invalid mode selected, otherwise it + * will return MP3_WTV020SD_SUCCESS + */ +int mp3_wtv020sd_config(uint8_t mode); +/** + * \brief Function to play a current track + * + * \return MP3_WTV020SD_ERROR if invalid mode used, otherwise it will + * return MP3_WTV020SD_SUCCESS + */ +int mp3_wtv020sd_gpio_play(void); +/** + * \brief Function to stop a current track + * + * \return MP3_WTV020SD_ERROR if invalid mode used, otherwise it will + * return MP3_WTV020SD_SUCCESS + */ +int mp3_wtv020sd_gpio_stop(void); +/** + * \brief Advances and play the next track, wraps over the playlist + * + * \return MP3_WTV020SD_ERROR if invalid mode used, otherwise it will + * return MP3_WTV020SD_SUCCESS + */ +int mp3_wtv020sd_gpio_next(void); +/** + * \brief Get the current status of the device (playing/stopped) + * + * \return MP3_WTV020SD_BUSY if a track is playing, otherwise it will + * return MP3_WTV020SD_IDLE + */ +int mp3_wtv020sd_busy(void); +/** + * \brief Trigger a module reset + * + * \return MP3_WTV020SD_ERROR if invalid mode used, otherwise it will + * return MP3_WTV020SD_SUCCESS + */ +int mp3_wtv020sd_reset(void); +/** + * \brief Plays the selected track and waits until it stops + * + * \param track forwards and play the selected track, starting from + * MP3_TRACK_BASE (0000.ad4) up to MP3_TRACK_BASE + 511 + * (0511.ad4) + * \return MP3_WTV020SD_ERROR if invalid mode used, otherwise it will + * return MP3_WTV020SD_SUCCESS + */ +int mp3_wtv020sd_sync_play(uint16_t track); +/** + * \brief Plays the selected track and returns immediately + * + * \param track forwards and play the selected track, starting from + * MP3_TRACK_BASE (0000.ad4) up to MP3_TRACK_BASE + 511 + * (0511.ad4) + * \return MP3_WTV020SD_ERROR if invalid mode used, otherwise it will + * return MP3_WTV020SD_SUCCESS + */ +int mp3_wtv020sd_async_play(uint16_t track); +/** + * \brief Stops the current track + * + * \return MP3_WTV020SD_ERROR if invalid mode used, otherwise it will + * return MP3_WTV020SD_SUCCESS + */ +int mp3_wtv020sd_stop(void); +/** + * \brief Pauses the current track + * + * \return MP3_WTV020SD_ERROR if invalid mode used, otherwise it will + * return MP3_WTV020SD_SUCCESS + */ +int mp3_wtv020sd_pause(void); + +/* -------------------------------------------------------------------------- */ +#endif /* ifndef MP3_WTV020SD_H_ */ +/* -------------------------------------------------------------------------- */ +/** + * @} + * @} + */ diff --git a/platform/remote/dev/phidget-sensor.c b/platform/remote/dev/phidget-sensor.c new file mode 100644 index 000000000..c400b8ad1 --- /dev/null +++ b/platform/remote/dev/phidget-sensor.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, 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 remote-phidget-sensor + * @{ + * + * \file + * Generic driver for the Re-Mote Phidget/ADC sensors + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "sys/clock.h" +#include "dev/ioc.h" +#include "dev/gpio.h" +#include "dev/adc.h" +#include "dev/phidget-sensor.h" +#include "dev/remote-sensors.h" + +#include +/*---------------------------------------------------------------------------*/ +#define ADC_PHIDGET_PORT_BASE GPIO_PORT_TO_BASE(ADC_PHIDGET_PORT) +#define ADC_PHIDGET_ADC2_PIN_MASK GPIO_PIN_MASK(ADC_PHIDGET_ADC2_PIN) +#define ADC_PHIDGET_ADC3_PIN_MASK GPIO_PIN_MASK(ADC_PHIDGET_ADC3_PIN) +/*---------------------------------------------------------------------------*/ +static uint8_t decimation_rate; +/*---------------------------------------------------------------------------*/ +static int +set_decimation_rate(uint8_t rate) +{ + switch(rate) { + case SOC_ADC_ADCCON_DIV_64: + case SOC_ADC_ADCCON_DIV_128: + case SOC_ADC_ADCCON_DIV_256: + case SOC_ADC_ADCCON_DIV_512: + decimation_rate = rate; + break; + default: + return REMOTE_SENSORS_ERROR; + } + + return decimation_rate; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + uint8_t channel; + int16_t res; + + switch(type) { + case PHIDGET_SENSORS_ADC2: + channel = SOC_ADC_ADCCON_CH_AIN0 + ADC_PHIDGET_ADC2_PIN; + break; + case PHIDGET_SENSORS_ADC3: + channel = SOC_ADC_ADCCON_CH_AIN0 + ADC_PHIDGET_ADC3_PIN; + break; + default: + return REMOTE_SENSORS_ERROR; + } + + res = adc_get(channel, SOC_ADC_ADCCON_REF_INT, decimation_rate); + + return res; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + switch(type) { + case SENSORS_HW_INIT: + GPIO_SOFTWARE_CONTROL(GPIO_A_BASE, ADC_PHIDGET_ADC2_PIN_MASK); + GPIO_SET_INPUT(GPIO_A_BASE, ADC_PHIDGET_ADC2_PIN_MASK); + ioc_set_over(GPIO_A_NUM, ADC_PHIDGET_ADC2_PIN, IOC_OVERRIDE_ANA); + + GPIO_SOFTWARE_CONTROL(GPIO_A_BASE, ADC_PHIDGET_ADC3_PIN_MASK); + GPIO_SET_INPUT(GPIO_A_BASE, ADC_PHIDGET_ADC3_PIN_MASK); + ioc_set_over(GPIO_A_NUM, ADC_PHIDGET_ADC3_PIN, IOC_OVERRIDE_ANA); + adc_init(); + set_decimation_rate(SOC_ADC_ADCCON_DIV_512); + break; + case REMOTE_SENSORS_CONFIGURE_TYPE_DECIMATION_RATE: + return set_decimation_rate((uint8_t)value); + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(phidget_sensor, PHIDGET_SENSOR, value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/sht-21-sensor.h b/platform/remote/dev/phidget-sensor.h similarity index 55% rename from platform/srf06-cc26xx/sensortag/sht-21-sensor.h rename to platform/remote/dev/phidget-sensor.h index af2f5d401..577c8f2c7 100644 --- a/platform/srf06-cc26xx/sensortag/sht-21-sensor.h +++ b/platform/remote/dev/phidget-sensor.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/ + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, University of Bristol - http://www.bristol.ac.uk * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -10,6 +11,7 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this 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. @@ -29,55 +31,52 @@ */ /*---------------------------------------------------------------------------*/ /** - * \addtogroup sensortag-cc26xx-peripherals + * \addtogroup remote-sensors * @{ * - * \defgroup sensortag-cc26xx-sht-sensor SensorTag 2.0 Humidity Sensor + * \defgroup remote-phidget-sensor Re-Mote Generic Phidget Sensor * - * Due to the time required between triggering a reading and the reading - * becoming available, this driver is meant to be used in an asynchronous - * fashion. The caller must first activate the sensor by calling - * SENSORS_ACTIVATE(). This will trigger a cycle which will read both - * temperature and humidity, but the call will not wait for the cycle to - * complete so that the CPU can perform other tasks or drop to a low power - * mode. + * Driver for the Re-Mote phidget ADC sensor * - * Once readings are available, the driver will generate a sensors_changed - * event. + * This driver supports phidgets connected to both the ADC2 and AND3 channels. + * This is controlled by the type argument of the value() function. Possible + * choices are: + * - PHIDGET_SENSORS_ADC2 (channel 2) + * - PHIDGET_SENSORS_ADC3 (channel 3) * - * Calls to .status() will return the driver's state which could indicate that - * a measurement is in progress (different return values for each) or that - * readings are ready. - * - * Multiple calls to value() will simply return the reading that was latched - * after the last cycle. In order to obtain fresh readings, a new cycle must be - * started by a new call to SENSORS_ACTIVATE. + * The decimation rate can be set by passing + * REMOTE_SENSORS_CONFIGURE_TYPE_DECIMATION_RATE as the type argument to the + * configure() function and then specifying the rate through the value + * argument. Valid values are: + * - SOC_ADC_ADCCON_DIV_64 (64 bit rate) + * - SOC_ADC_ADCCON_DIV_128 (128 bit rate) + * - SOC_ADC_ADCCON_DIV_256 (256 bit rate) + * - SOC_ADC_ADCCON_DIV_512 (512 bit rate) * @{ * * \file - * Header file for the Sensortag-CC26ss Sensirion SHT21 Humidity sensor + * Header file for the Re-Mote Generic Driver for Phidget/ADC sensors */ /*---------------------------------------------------------------------------*/ -#ifndef SHT_21_SENSOR_H_ -#define SHT_21_SENSOR_H_ +#ifndef PHIDGET_SENSOR_H_ +#define PHIDGET_SENSOR_H_ /*---------------------------------------------------------------------------*/ -#define SHT_21_SENSOR_TYPE_TEMP 1 -#define SHT_21_SENSOR_TYPE_HUMIDITY 2 +#include "lib/sensors.h" +#include "dev/soc-adc.h" /*---------------------------------------------------------------------------*/ /** - * \name SHT21 driver states + * \name Generic phidget sensor * @{ */ -#define SHT_21_SENSOR_STATUS_DISABLED 0 /**< Not initialised */ -#define SHT_21_SENSOR_STATUS_INITIALISED 1 /**< Initialised but idle */ -#define SHT_21_SENSOR_STATUS_READING_TEMP 2 /**< Temp reading in progress */ -#define SHT_21_SENSOR_STATUS_READING_HUMIDITY 3 /**< Humidity reading in progress */ -#define SHT_21_SENSOR_STATUS_READINGS_READY 4 /**< Both readings ready */ +#define PHIDGET_SENSOR "Phidget ADC" + +#define PHIDGET_SENSORS_ADC2 2 /**< 3V3 ADC phidget-like connector ADC2 */ +#define PHIDGET_SENSORS_ADC3 3 /**< 3V3 ADC phidget-like connector ADC3 */ /** @} */ /*---------------------------------------------------------------------------*/ -extern const struct sensors_sensor sht_21_sensor; +extern const struct sensors_sensor phidget_sensor; /*---------------------------------------------------------------------------*/ -#endif /* SHT_21_SENSOR_H_ */ +#endif /* PHIDGET_SENSOR_H_ */ /*---------------------------------------------------------------------------*/ /** * @} diff --git a/platform/remote/dev/remote-sensors.c b/platform/remote/dev/remote-sensors.c new file mode 100644 index 000000000..88daaa0cf --- /dev/null +++ b/platform/remote/dev/remote-sensors.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, 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 remote-sensors + * @{ + * + * Generic module controlling sensors on the Re-Mote platform + * @{ + * + * \file + * Implementation of a generic module controlling Re-Mote sensors + */ +#include "contiki.h" +#include "dev/cc2538-sensors.h" +#include "dev/button-sensor.h" +#include "dev/phidget-sensor.h" + +#include +/*---------------------------------------------------------------------------*/ +/* TODO: include the tmp102 sensor as well */ +/*---------------------------------------------------------------------------*/ +/** \brief Exports global symbols for the sensor API */ +SENSORS(&button_sensor, &vdd3_sensor, &cc2538_temp_sensor, &phidget_sensor); +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/remote/dev/remote-sensors.h b/platform/remote/dev/remote-sensors.h new file mode 100644 index 000000000..aa0ee03d8 --- /dev/null +++ b/platform/remote/dev/remote-sensors.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015, Zolertia - http://www.zolertia.com + * Copyright (c) 2015, 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 remote + * @{ + * + * \defgroup remote-sensors Re-Mote Sensors + * + * Generic module controlling sensors on the Re-Mote platform + * @{ + * + * \file + * Implementation of a generic module controlling Re-Mote sensors + */ +/*---------------------------------------------------------------------------*/ +#ifndef REMOTE_SENSORS_H_ +#define REMOTE_SENSORS_H_ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +#include "dev/cc2538-sensors.h" +#include "dev/button-sensor.h" +#include "dev/phidget-sensor.h" +/*---------------------------------------------------------------------------*/ +/** + * \name ReMote sensor constants + * + * These constants are used by various sensors on the ReMote. They can be used + * to configure ADC decimation rate (where applicable). + * @{ + */ +#define REMOTE_SENSORS_CONFIGURE_TYPE_DECIMATION_RATE 0x0100 /**< Change decimation rate (used with configure()) */ + +#define REMOTE_SENSORS_ERROR CC2538_SENSORS_ERROR /**< Error */ +/** @} */ +/*---------------------------------------------------------------------------*/ +#endif /* REMOTE_SENSORS_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/remote/dev/sht25.c b/platform/remote/dev/sht25.c new file mode 100644 index 000000000..0bc34f7c5 --- /dev/null +++ b/platform/remote/dev/sht25.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2015, 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-sht25-sensor + * @{ + * + * \file + * SHT25 temperature and humidity sensor driver + * \author + * Antonio Lignan + */ +/*---------------------------------------------------------------------------*/ +#include +#include "contiki.h" +#include "dev/i2c.h" +#include "dev/sht25.h" +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#warning I2C SDA AND SCL are inverted in JP8 connector, inverted in init() call +/*---------------------------------------------------------------------------*/ +static uint8_t enabled; +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + if(type != SENSORS_ACTIVE) { + return SHT25_ERROR; + } + if(value) { + i2c_init(I2C_SCL_PORT, I2C_SCL_PIN, I2C_SDA_PORT, I2C_SDA_PIN, + I2C_SCL_NORMAL_BUS_SPEED); + } + enabled = value; + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static uint16_t +sht25_read_reg(uint8_t reg, uint8_t *buf, uint8_t regNum) +{ + if(i2c_single_send(SHT25_ADDR, reg) == I2C_MASTER_ERR_NONE) { + if(i2c_burst_receive(SHT25_ADDR, buf, regNum) == I2C_MASTER_ERR_NONE) { + return SHT25_SUCCESS; + } + } + return SHT25_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int16_t +sht25_convert(uint8_t variable, uint16_t value) +{ + int16_t rd; + uint32_t buff; + buff = (uint32_t)value; + if(variable == SHT25_VAL_TEMP) { + buff *= 17572; + buff = buff >> 16; + rd = (int16_t)buff - 4685; + } else { + buff *= 12500; + buff = buff >> 16; + rd = (int16_t)buff - 600; + rd = (rd > 10000) ? 10000 : rd; + } + return rd; +} +/*---------------------------------------------------------------------------*/ +static int16_t +sht25_read(uint8_t variable, uint16_t *rd) +{ + uint8_t buf[2]; + uint16_t raw; + + if((variable != SHT25_VAL_TEMP) && (variable != SHT25_VAL_HUM)) { + return SHT25_ERROR; + } + + if (sht25_read_reg(variable, buf, 2) == SHT25_SUCCESS){ + raw = (buf[0] << 8) + buf[1]; + *rd = sht25_convert(variable, raw); + return SHT25_SUCCESS; + } + return SHT25_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + uint16_t val; + if (sht25_read(type, &val) == SHT25_SUCCESS){ + return val; + } + return SHT25_ERROR; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(sht25, SHT25_SENSOR, value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/remote/dev/sht25.h b/platform/remote/dev/sht25.h new file mode 100644 index 000000000..c1ee19391 --- /dev/null +++ b/platform/remote/dev/sht25.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015, 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-sensors + * @{ + * + * \defgroup remote-sht25-sensor Re-Mote SHT25 digital temperature sensor + * @{ + * + * \file + * SHT25 temperature and humidity sensor driver + * \author + * Antonio Lignan + */ +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" + +#ifndef SHT25_H_ +#define SHT25_H_ + +/* -------------------------------------------------------------------------- */ +#define SHT25_ADDR 0x40 +#define SHT25_TEMP_HOLD 0xE3 +#define SHT25_HUM_HOLD 0xE5 +#define SHT25_TEMP_NO_HOLD 0xF3 +#define SHT25_HUM_NO_HOLD 0xF5 +#define SHT2X_UREG_WRITE 0xE6 +#define SHT2X_UREG_READ 0xE7 +#define SHT2X_SOFT_RESET 0XFE +#define SHT2X_NULL 0x00 +/* -------------------------------------------------------------------------- */ +#define SHT2X_RES_14T_12RH 0x00 +#define SHT2X_RES_12T_08RH 0x01 +#define SHT2X_RES_13T_10RH 0x80 +#define SHT2X_RES_11T_11RH 0x81 +#define SHT2X_HEATER_ON 0x04 +#define SHT2X_HEATER_OFF 0x00 +#define SHT2X_OTP_RELOAD_EN 0x00 +#define SHT2X_OTP_RELOAD_DIS 0x02 +/* -------------------------------------------------------------------------- */ +#define SHT25_VAL_TEMP SHT25_TEMP_HOLD +#define SHT25_VAL_HUM SHT25_HUM_HOLD +#define SHT25_ERROR -1 +#define SHT25_SUCCESS 0x00 +/* -------------------------------------------------------------------------- */ +#define SHT25_SENSOR "SHT25 Sensor" +/* -------------------------------------------------------------------------- */ +extern const struct sensors_sensor sht25; +/* -------------------------------------------------------------------------- */ +#endif /* ifndef SHT25_H_ */ +/** + * @} + * @} + */ diff --git a/platform/remote/dev/tmp102.c b/platform/remote/dev/tmp102.c new file mode 100644 index 000000000..bdea73e87 --- /dev/null +++ b/platform/remote/dev/tmp102.c @@ -0,0 +1,73 @@ +/* + * 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. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup remote-tmp102-sensor + * @{ + * + * \file + * Driver for the Re-Mote TMP102 temperature sensor + */ +/*---------------------------------------------------------------------------*/ +#include +#include "contiki.h" +#include "dev/i2c.h" +#include "tmp102.h" + +void +tmp102_init(void) +{ + i2c_init(I2C_SDA_PORT, I2C_SDA_PIN, I2C_SCL_PORT, I2C_SCL_PIN, I2C_SCL_NORMAL_BUS_SPEED); +} +/*---------------------------------------------------------------------------*/ + +uint8_t +tmp102_read(uint16_t *data) +{ + uint8_t buf[2]; + uint16_t temp; + + /* Write to the temperature register to trigger a reading */ + if(i2c_single_send(TMP102_ADDR, TMP102_TEMP) == I2C_MASTER_ERR_NONE) { + /* Read two bytes only */ + if(i2c_burst_receive(TMP102_ADDR, buf, 2) == I2C_MASTER_ERR_NONE) { + temp = (buf[0] << 8) + buf[1]; + if(temp > 2047) { + temp -= (1 << 12); + } + temp *= 0.625; + *data = temp; + return I2C_MASTER_ERR_NONE; + } + } + return i2c_master_error(); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/remote/dev/tmp102.h b/platform/remote/dev/tmp102.h new file mode 100644 index 000000000..39da4408b --- /dev/null +++ b/platform/remote/dev/tmp102.h @@ -0,0 +1,75 @@ +/* + * 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. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup remote-sensors + * @{ + * + * \defgroup remote-tmp102-sensor Re-Mote TMP102 Sensor + * + * Driver for the Re-Mote TMP102 sensor + * + * The TMP102 driver returns the converted temperature value in centiCelsius + * with 2 digits precision, to get Celsius just divide by 100. + * @{ + * + * \file + * Header file for the Re-Mote TMP102 Sensor Driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef TMP102_H_ +#define TMP102_H_ +#include +#include "i2c.h" +/* -------------------------------------------------------------------------- */ +/** + * \name Generic TMP102 sensor + * @{ + */ +/* -------------------------------------------------------------------------- */ +#define TMP102_ADDR 0x48 /**< TMP102 slave address */ +#define TMP102_TEMP 0x00 /**< TMP102 temperature data register */ +/** @} */ +/* -------------------------------------------------------------------------- */ +#endif /* ifndef TMP102_H_ */ +/*---------------------------------------------------------------------------*/ + +/** \brief Initialiser for the TMP102 sensor driver */ +void tmp102_init(void); + +/** \brief Get a temperature reading from the TMP102 sensor */ +uint8_t tmp102_read(uint16_t *data); + +/** + * @} + * @} + */ diff --git a/platform/remote/dev/tsl2563.c b/platform/remote/dev/tsl2563.c new file mode 100644 index 000000000..c7e57f7ee --- /dev/null +++ b/platform/remote/dev/tsl2563.c @@ -0,0 +1,178 @@ +/* + * 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. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup remote-tsl2563-sensor + * @{ + * + * \file + * Driver for the Re-Mote external TSL2563 light sensor (Ziglet) + * + * \author + * Antonio Lignan + * Toni Lozano + */ +/*---------------------------------------------------------------------------*/ +#include +#include "contiki.h" +#include "dev/i2c.h" +#include "lib/sensors.h" +#include "tsl2563.h" +/*---------------------------------------------------------------------------*/ +#warning I2C SDA AND SCL are inverted in JP8 connector, inverted in init() call +/*---------------------------------------------------------------------------*/ +static uint8_t enabled; +/*---------------------------------------------------------------------------*/ +static uint16_t +calculateLux(uint8_t *buf) +{ + uint32_t ch0, ch1 = 0; + uint32_t aux = (1 << 14); + uint32_t ratio, lratio, tmp = 0; + uint16_t buffer[2]; + + buffer[0] = (buf[1] << 8 | (buf[0])); + buffer[1] = (buf[3] << 8 | (buf[2])); + ch0 = (buffer[0] * aux) >> 10; + ch1 = (buffer[1] * aux) >> 10; + ratio = (ch1 << 10); + ratio = ratio / ch0; + lratio = (ratio + 1) >> 1; + + if((lratio >= 0) && (lratio <= K1T)) { + tmp = (ch0 * B1T) - (ch1 * M1T); + } else if(lratio <= K2T) { + tmp = (ch0 * B2T) - (ch1 * M2T); + } else if(lratio <= K3T) { + tmp = (ch0 * B3T) - (ch1 * M3T); + } else if(lratio <= K4T) { + tmp = (ch0 * B4T) - (ch1 * M4T); + } else if(lratio <= K5T) { + tmp = (ch0 * B5T) - (ch1 * M5T); + } else if(lratio <= K6T) { + tmp = (ch0 * B6T) - (ch1 * M6T); + } else if(lratio <= K7T) { + tmp = (ch0 * B7T) - (ch1 * M7T); + } else if(lratio > K8T) { + tmp = (ch0 * B8T) - (ch1 * M8T); + } + + if(tmp < 0) { + tmp = 0; + } + + tmp += (1 << 13); + return tmp >> 14; +} +/*---------------------------------------------------------------------------*/ +static int +tsl2563_read_reg(uint8_t reg, uint8_t *buf, uint8_t regNum) +{ + if(i2c_single_send(TSL2563_ADDR, reg) == I2C_MASTER_ERR_NONE) { + if(i2c_burst_receive(TSL2563_ADDR, buf, regNum) == I2C_MASTER_ERR_NONE) { + return TSL2563_SUCCESS; + } + } + return TSL2563_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int +light_ziglet_on(void) +{ + if(i2c_single_send(TSL2563_ADDR, (uint8_t)TSL2563_PWRN) == I2C_MASTER_ERR_NONE) { + return TSL2563_SUCCESS; + } + return TSL2563_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int +light_ziglet_off(void) +{ + if(i2c_single_send(TSL2563_ADDR, (uint8_t)TSL2563_PWROFF) == I2C_MASTER_ERR_NONE) { + return TSL2563_SUCCESS; + } + return TSL2563_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int +light_ziglet_read(uint16_t *lux) +{ + uint8_t buf[4]; + if(light_ziglet_on() == TSL2563_SUCCESS) { + if(tsl2563_read_reg(TSL2563_READ, buf, 4) == TSL2563_SUCCESS) { + *lux = calculateLux(buf); + return light_ziglet_off(); + } + } + return TSL2563_ERROR; +} +/*---------------------------------------------------------------------------*/ +static int +configure(int type, int value) +{ + if(type != SENSORS_ACTIVE) { + return TSL2563_ERROR; + } + enabled = value; + if(value) { + i2c_init(I2C_SCL_PORT, I2C_SCL_PIN, I2C_SDA_PORT, I2C_SDA_PIN, + I2C_SCL_NORMAL_BUS_SPEED); + } else { + light_ziglet_off(); + } + return TSL2563_SUCCESS; +} +/*---------------------------------------------------------------------------*/ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +value(int type) +{ + uint16_t lux; + if(type == TSL2563_VAL_READ) { + if(light_ziglet_read(&lux) != TSL2563_ERROR) { + return lux; + } + } + return TSL2563_ERROR; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(tsl2563, TSL2563_SENSOR, value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/remote/dev/tsl2563.h b/platform/remote/dev/tsl2563.h new file mode 100644 index 000000000..6cd2d14dc --- /dev/null +++ b/platform/remote/dev/tsl2563.h @@ -0,0 +1,111 @@ +/* + * 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. + * + * This file is part of the Contiki operating system. + * + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup remote-sensors + * @{ + * + * \defgroup remote-tsl2563-sensor Re-Mote TSL2563 Sensor + * + * Driver for the Re-Mote TSL2563 sensor + * + * The TSL2563 driver returns the converted light value value in lux + * @{ + * + * \file + * Header file for the Re-Mote external TSL2563 Sensor Driver + * + * \author + * Antonio Lignan + * Toni Lozano + */ +/*---------------------------------------------------------------------------*/ +#ifndef LIGHT_SENSOR_H_ +#define LIGHT_SENSOR_H_ +#include +#include "lib/sensors.h" +#include "i2c.h" +/* -------------------------------------------------------------------------- */ +/** + * \name TSL2563 digital Light sensor + * @{ + */ +/* -------------------------------------------------------------------------- */ +#define TSL2563_ADDR 0x39 /**< TSL2563 slave address */ +/* -------------------------------------------------------------------------- */ +#define TSL2563_READ 0xAC /**< TSL2563 read register */ +#define TSL2563_PWRN 0x03 /**< TSL2563 enable register */ +#define TSL2563_PWROFF 0x00 /**< TSL2563 Power OFF */ +/* -------------------------------------------------------------------------- */ +#define K1T 0X0040 /**< Calibration values (hardcoded) */ +#define B1T 0x01f2 +#define M1T 0x01b2 +#define K2T 0x0080 +#define B2T 0x0214 +#define M2T 0x02d1 +#define K3T 0x00c0 +#define B3T 0x023f +#define M3T 0x037b +#define K4T 0x0100 +#define B4T 0x0270 +#define M4T 0x03fe +#define K5T 0x0138 +#define B5T 0x016f +#define M5T 0x01fc +#define K6T 0x019a +#define B6T 0x00d2 +#define M6T 0x00fb +#define K7T 0x029a +#define B7T 0x0018 +#define M7T 0x0012 +#define K8T 0x029a +#define B8T 0x0000 +#define M8T 0x0000 +/** @} */ +/* -------------------------------------------------------------------------- */ +#define TSL2563_SUCCESS 0x00 +#define TSL2563_LIGHT 0x01 +#define TSL2563_ERROR -1 +/* -------------------------------------------------------------------------- */ +#define TSL2563_VAL_READ 0x01 +/* -------------------------------------------------------------------------- */ +#define TSL2563_SENSOR "TSL2563 Light Sensor" +/* -------------------------------------------------------------------------- */ +extern const struct sensors_sensor tsl2563; +/* -------------------------------------------------------------------------- */ +#endif +/* -------------------------------------------------------------------------- */ +/** + * @} + * @} + */ + diff --git a/platform/srf06-cc26xx/README.md b/platform/srf06-cc26xx/README.md index 4cfb9945d..4188c59fb 100644 --- a/platform/srf06-cc26xx/README.md +++ b/platform/srf06-cc26xx/README.md @@ -39,7 +39,7 @@ In terms of hardware support, the following drivers have been implemented: * Motion Processing Unit (MPU9250 - Accelerometer, Gyro) * BMP280 sensor * TMP007 sensor - * SHT21 sensor + * HDC1000 sensor * OPT3001 sensor * Buzzer * External SPI flash @@ -59,7 +59,8 @@ Requirements ============ To use the port you need: -* TI's CC26xxware sources (more below) +* TI's CC26xxware sources. The correct version will be installed automatically + as a submodule when you clone Contiki. * Software to program the nodes. Use TI's SmartRF Flash Programmer * A toolchain to build firmware: The port has been developed and tested with GNU Tools for ARM Embedded Processors . @@ -69,45 +70,18 @@ To use the port you need: [...] gcc version 4.9.3 20141119 (release) [ARM/embedded-4_9-branch revision 218278] (GNU Tools for ARM Embedded Processors) +* srecord (http://srecord.sourceforge.net/) * You may also need other drivers so that the SmartRF can communicate with your operating system and so that you can use the chip's UART for I/O. Please read the section ["Drivers" in the CC2538DK readme](https://github.com/contiki-os/contiki/tree/master/platform/cc2538dk#drivers). -Environment -=========== -To use this port, you will need to download and extract CC26xxware sources, -provided by TI here http://www.ti.com/tool/cc26xxware. Once you have done this, you will need to configure the Contiki -build system so that it can locate and compile them as part of the build process. - -To do this, you will need to set the following environment variable: - -* `TI_CC26XXWARE` - - Stores the path to a directory containing the following: - - * cc26xxware sources under `$(TI_CC26XXWARE)/driverlib` - * cc26xxware includes under `$(TI_CC26XXWARE)/inc` - * Startup files under `$(TI_CC26XXWARE)/startup_files` - -This _must_ be a path relative to the Contiki source directory. For -example, if Contiki is in `/home/user/contiki-2.x` and the CC26xxware is in -`/home/user/cc26xxware`, then `TI_CC26XXWARE` must be set to `../cc26xxware` - -The variable can be set within the example's Makefile, by adding this: - - TI_CC26XXWARE=../cc26xxware - -or you can use an environment variable, like so: - - export TI_CC26XXWARE=../cc26xxware - Filename conflicts between Contiki and CC26xxware ================================================= There is a file called `timer.c` both in Contiki as well as in CC26xxware. The way things are configured now, we don't use the latter. However, if you need to start using it at some point, you will need to rename it: -From `$(TI_CC26XXWARE)/driverlib/cc26xx/source/timer.c` to `driverlib-timer.c` +From `cpu/cc26xx/lib/cc26xxware/driverlib/timer.c` to `driverlib-timer.c` Sensortag vs Srf06 ================== diff --git a/platform/srf06-cc26xx/contiki-conf.h b/platform/srf06-cc26xx/contiki-conf.h index 6a99c29b3..359c922df 100644 --- a/platform/srf06-cc26xx/contiki-conf.h +++ b/platform/srf06-cc26xx/contiki-conf.h @@ -220,7 +220,7 @@ #define UIP_CONF_TCP 1 #endif #ifndef UIP_CONF_TCP_MSS -#define UIP_CONF_TCP_MSS 128 +#define UIP_CONF_TCP_MSS 64 #endif #define UIP_CONF_UDP 1 @@ -244,10 +244,6 @@ #ifndef ENERGEST_CONF_ON #define ENERGEST_CONF_ON 0 /**< Energest Module */ #endif - -#ifndef STARTUP_CONF_VERBOSE -#define STARTUP_CONF_VERBOSE 1 /**< Set to 0 to decrease startup verbosity */ -#endif /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -273,29 +269,10 @@ * This will keep working while UIP_FALLBACK_INTERFACE and CMD_CONF_OUTPUT * keep using SLIP */ -#if defined (UIP_FALLBACK_INTERFACE) || defined (CMD_CONF_OUTPUT) +#if defined(UIP_FALLBACK_INTERFACE) || defined(CMD_CONF_OUTPUT) #define SLIP_ARCH_CONF_ENABLED 1 #endif #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 CC26XX_CONF_QUIET -#define CC26XX_CONF_QUIET 0 -#endif - -/* CC26XX_CONF_QUIET is hard and overrides all other related defines */ -#if CC26XX_CONF_QUIET -#undef CC26XX_UART_CONF_ENABLE -#define CC26XX_UART_CONF_ENABLE 0 - -#undef STARTUP_CONF_VERBOSE -#define STARTUP_CONF_VERBOSE 0 -#endif /* CC26XX_CONF_QUIET */ /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -310,6 +287,13 @@ /* 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_left_sensor +#define button_sensor2 button_right_sensor /** @} */ /*---------------------------------------------------------------------------*/ /* Platform-specific define to signify sensor reading failure */ @@ -332,14 +316,14 @@ 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 CLOCK_LT(a, b) ((signed long)((a) - (b)) < 0) /* * rtimer.h typedefs rtimer_clock_t as unsigned short. We need to define * RTIMER_CLOCK_LT to override this */ typedef uint32_t rtimer_clock_t; -#define RTIMER_CLOCK_LT(a,b) ((int32_t)((a)-(b)) < 0) +#define RTIMER_CLOCK_LT(a, b) ((int32_t)((a) - (b)) < 0) /** @} */ /*---------------------------------------------------------------------------*/ /* 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 d28643531..5cc5d83fa 100644 --- a/platform/srf06-cc26xx/contiki-main.c +++ b/platform/srf06-cc26xx/contiki-main.c @@ -46,6 +46,7 @@ #include "lpm.h" #include "gpio-interrupt.h" #include "dev/watchdog.h" +#include "dev/oscillators.h" #include "ieee-addr.h" #include "vims.h" #include "cc26xx-model.h" @@ -61,7 +62,7 @@ #include "dev/serial-line.h" #include "net/mac/frame802154.h" -#include "driverlib/driverlib_ver.h" +#include "driverlib/driverlib_release.h" #include /*---------------------------------------------------------------------------*/ @@ -119,23 +120,6 @@ set_rf_params(void) #endif } /*---------------------------------------------------------------------------*/ -static void -select_lf_xosc(void) -{ - ti_lib_osc_interface_enable(); - - /* 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); - - /* Switch LF clock source to the LF RCOSC if required */ - if(ti_lib_osc_clock_source_get(OSC_SRC_CLK_LF) != OSC_XOSC_LF) { - ti_lib_osc_clock_source_set(OSC_SRC_CLK_LF, OSC_XOSC_LF); - } - - ti_lib_osc_interface_disable(); -} -/*---------------------------------------------------------------------------*/ /** * \brief Main function for CC26xx-based platforms * @@ -144,41 +128,39 @@ select_lf_xosc(void) int main(void) { + /* Enable flash cache and prefetch. */ + ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_ENABLED); + ti_lib_vims_configure(VIMS_BASE, true, true); + + ti_lib_int_master_disable(); + /* Set the LF XOSC as the LF system clock source */ - select_lf_xosc(); - - /* - * Make sure to open the latches - this will be important when returning - * from shutdown - */ - ti_lib_pwr_ctrl_io_freeze_disable(); - - /* Use DCDC instead of LDO to save current */ - ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_DCDC); + oscillators_select_lf_xosc(); lpm_init(); board_init(); - /* Enable flash cache and prefetch. */ - ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_ENABLED); - ti_lib_vims_configure(VIMS_BASE, true, true); - gpio_interrupt_init(); - /* Clock must always be enabled for the semaphore module */ - HWREG(AUX_WUC_BASE + AUX_WUC_O_MODCLKEN1) = AUX_WUC_MODCLKEN1_SMPH; - leds_init(); + /* + * Disable I/O pad sleep mode and open I/O latches in the AON IOC interface + * This is only relevant when returning from shutdown (which is what froze + * latches in the first place. Before doing these things though, we should + * allow software to first regain control of pins + */ + ti_lib_pwr_ctrl_io_freeze_disable(); + fade(LEDS_RED); + ti_lib_int_master_enable(); + cc26xx_rtc_init(); clock_init(); rtimer_init(); - board_init(); - watchdog_init(); process_init(); @@ -187,14 +169,13 @@ main(void) /* Character I/O Initialisation */ #if CC26XX_UART_CONF_ENABLE cc26xx_uart_init(); - cc26xx_uart_set_input(serial_line_input_byte); #endif serial_line_init(); printf("Starting " CONTIKI_VERSION_STRING "\n"); - printf("With CC26xxware v%u.%02u.%02u.%u\n", DRIVERLIB_MAJOR_VER, - DRIVERLIB_MINOR_VER, DRIVERLIB_PATCH_VER, DRIVERLIB_BUILD_ID); + printf("With DriverLib v%u.%u\n", DRIVERLIB_RELEASE_GROUP, + DRIVERLIB_RELEASE_BUILD); printf(BOARD_STRING " using CC%u\n", CC26XX_MODEL_CPU_VARIANT); process_start(&etimer_process, NULL); diff --git a/platform/srf06-cc26xx/sensortag/Makefile.sensortag b/platform/srf06-cc26xx/sensortag/Makefile.sensortag index 98fad7a68..94de7711f 100644 --- a/platform/srf06-cc26xx/sensortag/Makefile.sensortag +++ b/platform/srf06-cc26xx/sensortag/Makefile.sensortag @@ -1,8 +1,8 @@ -CFLAGS += -DBOARD_SENSORTAG=1 -DTI_BSP_BOARD_HDR=\"ti-bsp-st.h\" +CFLAGS += -DBOARD_SENSORTAG=1 CFLAGS += -DBACKDOOR_IOID=0x00000000 BOARD_SOURCEFILES += leds-arch.c sensortag-sensors.c sensor-common.c BOARD_SOURCEFILES += bmp-280-sensor.c tmp-007-sensor.c opt-3001-sensor.c -BOARD_SOURCEFILES += sht-21-sensor.c mpu-9250-sensor.c button-sensor.c +BOARD_SOURCEFILES += hdc-1000-sensor.c mpu-9250-sensor.c button-sensor.c BOARD_SOURCEFILES += reed-relay.c ext-flash.c buzzer.c BOARD_SOURCEFILES += board.c board-spi.c board-i2c.c diff --git a/platform/srf06-cc26xx/sensortag/bmp-280-sensor.c b/platform/srf06-cc26xx/sensortag/bmp-280-sensor.c index a3b85ccc2..067fe79b9 100644 --- a/platform/srf06-cc26xx/sensortag/bmp-280-sensor.c +++ b/platform/srf06-cc26xx/sensortag/bmp-280-sensor.c @@ -136,7 +136,7 @@ static int enabled = SENSOR_STATUS_DISABLED; static uint8_t sensor_value[SENSOR_DATA_BUF_SIZE]; /*---------------------------------------------------------------------------*/ /* Wait SENSOR_STARTUP_DELAY clock ticks for the sensor to be ready - ~80ms */ -#define SENSOR_STARTUP_DELAY 11 +#define SENSOR_STARTUP_DELAY 3 static struct ctimer startup_timer; /*---------------------------------------------------------------------------*/ @@ -187,7 +187,7 @@ enable_sensor(bool enable) if(enable) { /* Enable forced mode */ - val = PM_NORMAL | OSRSP(1) | OSRST(1); + val = PM_FORCED | OSRSP(1) | OSRST(1); } else { val = PM_OFF; } @@ -345,6 +345,7 @@ configure(int type, int enable) case SENSORS_HW_INIT: enabled = SENSOR_STATUS_INITIALISED; init(); + enable_sensor(0); break; case SENSORS_ACTIVE: /* Must be initialised first */ diff --git a/platform/srf06-cc26xx/sensortag/bmp-280-sensor.h b/platform/srf06-cc26xx/sensortag/bmp-280-sensor.h index e27013c40..8bff65787 100644 --- a/platform/srf06-cc26xx/sensortag/bmp-280-sensor.h +++ b/platform/srf06-cc26xx/sensortag/bmp-280-sensor.h @@ -42,12 +42,10 @@ * * Once the sensor is stable, the driver will generate a sensors_changed event. * - * Once a reading has been taken, the caller has two options: - * - Turn the sensor off by calling SENSORS_DEACTIVATE, but in order to take - * subsequent readings SENSORS_ACTIVATE must be called again - * - Leave the sensor on. In this scenario, the caller can simply keep calling - * value() for subsequent readings, but having the sensor on will consume - * energy + * We take readings in "Forced" mode. In this mode, the BMP will take a single + * measurement and it will then automatically go to sleep. + * + * SENSORS_ACTIVATE must be called again to trigger a new reading cycle * @{ * * \file diff --git a/platform/srf06-cc26xx/sensortag/board-i2c.c b/platform/srf06-cc26xx/sensortag/board-i2c.c index 0e1f544a6..a2b0ba5d2 100644 --- a/platform/srf06-cc26xx/sensortag/board-i2c.c +++ b/platform/srf06-cc26xx/sensortag/board-i2c.c @@ -39,9 +39,53 @@ #include "contiki-conf.h" #include "ti-lib.h" #include "board-i2c.h" +#include "lpm.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +#define NO_INTERFACE 0xFF /*---------------------------------------------------------------------------*/ static uint8_t slave_addr = 0x00; -static uint8_t interface = 0xFF; +static uint8_t interface = NO_INTERFACE; +/*---------------------------------------------------------------------------*/ +static bool +accessible(void) +{ + /* First, check the PD */ + if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) + != PRCM_DOMAIN_POWER_ON) { + return false; + } + + /* Then check the 'run mode' clock gate */ + if(!(HWREG(PRCM_BASE + PRCM_O_I2CCLKGR) & PRCM_I2CCLKGR_CLK_EN)) { + return false; + } + + return true; +} +/*---------------------------------------------------------------------------*/ +void +board_i2c_wakeup() +{ + /* 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)); + + /* Enable the clock to I2C */ + ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_I2C0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + /* Reset the I2C controller */ + ti_lib_hapi_reset_peripheral(PRCM_PERIPH_I2C0); + + /* Enable and initialize the I2C master module */ + ti_lib_i2c_master_init_exp_clk(I2C0_BASE, ti_lib_sys_ctrl_clock_get(), + true); +} /*---------------------------------------------------------------------------*/ static bool i2c_status() @@ -57,21 +101,34 @@ i2c_status() } /*---------------------------------------------------------------------------*/ void -board_i2c_init() +board_i2c_shutdown() { - /* The I2C peripheral must be enabled */ - ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_I2C0); + interface = NO_INTERFACE; + + if(accessible()) { + ti_lib_i2c_master_disable(I2C0_BASE); + } + + ti_lib_prcm_peripheral_run_disable(PRCM_PERIPH_I2C0); ti_lib_prcm_load_set(); while(!ti_lib_prcm_load_get()); - /* Reset the I2C controller */ - HWREG(PRCM_BASE + PRCM_O_RESETI2C) = PRCM_RESETI2C_I2C; + /* + * Set all pins to GPIO Input and disable the output driver. Set internal + * pull to match external pull + * + * SDA and SCL: external PU resistor + * SDA HP and SCL HP: MPU PWR low + */ + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SDA_HP); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_SDA_HP, IOC_IOPULL_DOWN); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SCL_HP); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_SCL_HP, IOC_IOPULL_DOWN); - /* Enable and initialize the I2C master module */ - ti_lib_i2c_master_init_exp_clk(I2C0_BASE, - ti_lib_sys_ctrl_peripheral_clock_get( - PRCM_PERIPH_I2C0, SYSCTRL_SYSBUS_ON), - true); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SDA); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_SDA, IOC_IOPULL_UP); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SCL); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_SCL, IOC_IOPULL_UP); } /*---------------------------------------------------------------------------*/ bool @@ -248,8 +305,15 @@ board_i2c_select(uint8_t new_interface, uint8_t address) { slave_addr = address; + if(accessible() == false) { + board_i2c_wakeup(); + } + if(new_interface != interface) { interface = new_interface; + + ti_lib_i2c_master_disable(I2C0_BASE); + if(interface == BOARD_I2C_INTERFACE_0) { ti_lib_ioc_io_port_pull_set(BOARD_IOID_SDA, IOC_NO_IOPULL); ti_lib_ioc_io_port_pull_set(BOARD_IOID_SCL, IOC_NO_IOPULL); @@ -263,6 +327,10 @@ board_i2c_select(uint8_t new_interface, uint8_t address) ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SDA); ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SCL); } + + /* Enable and initialize the I2C master module */ + ti_lib_i2c_master_init_exp_clk(I2C0_BASE, ti_lib_sys_ctrl_clock_get(), + true); } } /*---------------------------------------------------------------------------*/ diff --git a/platform/srf06-cc26xx/sensortag/board-i2c.h b/platform/srf06-cc26xx/sensortag/board-i2c.h index bed78cf46..40832c9bd 100644 --- a/platform/srf06-cc26xx/sensortag/board-i2c.h +++ b/platform/srf06-cc26xx/sensortag/board-i2c.h @@ -48,13 +48,15 @@ #define BOARD_I2C_INTERFACE_0 0 #define BOARD_I2C_INTERFACE_1 1 /*---------------------------------------------------------------------------*/ -#define board_i2c_deselect(...) -/*---------------------------------------------------------------------------*/ /** - * \brief Initialise the I2C controller with defaults for the sensortag + * \brief Put the I2C controller in a known state + * + * In this state, pins SDA and SCL will be under i2c control and pins SDA HP + * and SCL HP will be configured as gpio inputs. This is equal to selecting + * BOARD_I2C_INTERFACE_0, but without selecting a slave device address */ -void board_i2c_init(void); - +#define board_i2c_deselect() board_i2c_select(BOARD_I2C_INTERFACE_0, 0) +/*---------------------------------------------------------------------------*/ /** * \brief Select an I2C slave * \param interface The I2C interface to be used (BOARD_I2C_INTERFACE_0 or _1) @@ -99,6 +101,27 @@ bool board_i2c_write_single(uint8_t data); */ bool board_i2c_write_read(uint8_t *wdata, uint8_t wlen, uint8_t *rdata, uint8_t rlen); + +/** + * \brief Enables the I2C peripheral with defaults + * + * This function is called to wakeup and initialise the I2C. + * + * This function can be called explicitly, but it will also be called + * automatically by board_i2c_select() when required. One of those two + * functions MUST be called before any other I2C operation after a chip + * sleep / wakeup cycle or after a call to board_i2c_shutdown(). Failing to do + * so will lead to a bus fault. + */ +void board_i2c_wakeup(void); + +/** + * \brief Stops the I2C peripheral and restores pins to s/w control + * + * This function is called automatically by the board's LPM logic, but it + * can also be called explicitly. + */ +void board_i2c_shutdown(void); /*---------------------------------------------------------------------------*/ #endif /* BOARD_I2C_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/platform/srf06-cc26xx/sensortag/board-peripherals.h b/platform/srf06-cc26xx/sensortag/board-peripherals.h index aa61ab333..9c994d9e6 100644 --- a/platform/srf06-cc26xx/sensortag/board-peripherals.h +++ b/platform/srf06-cc26xx/sensortag/board-peripherals.h @@ -43,7 +43,7 @@ #include "bmp-280-sensor.h" #include "tmp-007-sensor.h" #include "opt-3001-sensor.h" -#include "sht-21-sensor.h" +#include "hdc-1000-sensor.h" #include "mpu-9250-sensor.h" #include "reed-relay.h" #include "buzzer.h" diff --git a/platform/srf06-cc26xx/sensortag/board-spi.c b/platform/srf06-cc26xx/sensortag/board-spi.c index 01dd65857..640f8266c 100644 --- a/platform/srf06-cc26xx/sensortag/board-spi.c +++ b/platform/srf06-cc26xx/sensortag/board-spi.c @@ -40,12 +40,35 @@ #include "ti-lib.h" #include "board-spi.h" #include "board.h" + +#include /*---------------------------------------------------------------------------*/ #define CPU_FREQ 48000000ul /*---------------------------------------------------------------------------*/ +static bool +accessible(void) +{ + /* First, check the PD */ + if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) + != PRCM_DOMAIN_POWER_ON) { + return false; + } + + /* Then check the 'run mode' clock gate */ + if(!(HWREG(PRCM_BASE + PRCM_O_SSICLKGR) & PRCM_SSICLKGR_CLK_EN_SSI0)) { + return false; + } + + return true; +} +/*---------------------------------------------------------------------------*/ int board_spi_write(const uint8_t *buf, size_t len) { + if(accessible() == false) { + return 0; + } + while(len > 0) { uint32_t ul; @@ -61,6 +84,10 @@ board_spi_write(const uint8_t *buf, size_t len) int board_spi_read(uint8_t *buf, size_t len) { + if(accessible() == false) { + return 0; + } + while(len > 0) { uint32_t ul; @@ -79,6 +106,10 @@ board_spi_read(uint8_t *buf, size_t len) void board_spi_flush() { + if(accessible() == false) { + return; + } + uint32_t ul; while(ti_lib_rom_ssi_data_get_non_blocking(SSI0_BASE, &ul)); } @@ -88,7 +119,12 @@ board_spi_open(uint32_t bit_rate, uint32_t clk_pin) { uint32_t buf; - /* SPI power */ + /* 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)); + + /* Enable clock in active mode */ ti_lib_rom_prcm_peripheral_run_enable(PRCM_PERIPH_SSI0); ti_lib_prcm_load_set(); while(!ti_lib_prcm_load_get()); @@ -113,6 +149,16 @@ board_spi_close() ti_lib_rom_prcm_peripheral_run_disable(PRCM_PERIPH_SSI0); ti_lib_prcm_load_set(); while(!ti_lib_prcm_load_get()); + + /* Restore pins to a low-consumption state */ + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SPI_MISO); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_SPI_MISO, IOC_IOPULL_DOWN); + + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SPI_MOSI); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_SPI_MOSI, IOC_IOPULL_DOWN); + + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_SPI_CLK_FLASH); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_SPI_CLK_FLASH, IOC_IOPULL_DOWN); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/platform/srf06-cc26xx/sensortag/board.c b/platform/srf06-cc26xx/sensortag/board.c index 5246a85ef..f06545170 100644 --- a/platform/srf06-cc26xx/sensortag/board.c +++ b/platform/srf06-cc26xx/sensortag/board.c @@ -46,17 +46,16 @@ #include #include -/*---------------------------------------------------------------------------*/ -#define PRCM_DOMAINS (PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH) +#include /*---------------------------------------------------------------------------*/ static void power_domains_on(void) { - /* Turn on relevant power domains */ - ti_lib_prcm_power_domain_on(PRCM_DOMAINS); + /* Turn on the PERIPH PD */ + ti_lib_prcm_power_domain_on(PRCM_DOMAIN_PERIPH); /* Wait for domains to power on */ - while((ti_lib_prcm_power_domain_status(PRCM_DOMAINS) + while((ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) != PRCM_DOMAIN_POWER_ON)); } /*---------------------------------------------------------------------------*/ @@ -64,8 +63,6 @@ static void lpm_wakeup_handler(void) { power_domains_on(); - - board_i2c_init(); } /*---------------------------------------------------------------------------*/ static void @@ -76,9 +73,13 @@ shutdown_handler(uint8_t mode) SENSORS_DEACTIVATE(bmp_280_sensor); SENSORS_DEACTIVATE(opt_3001_sensor); SENSORS_DEACTIVATE(tmp_007_sensor); - SENSORS_DEACTIVATE(sht_21_sensor); - mpu_9250_sensor.configure(MPU_9250_SENSOR_SHUTDOWN, 0); + SENSORS_DEACTIVATE(hdc_1000_sensor); + SENSORS_DEACTIVATE(mpu_9250_sensor); + ti_lib_gpio_pin_clear(BOARD_MPU_POWER); } + + /* In all cases, stop the I2C */ + board_i2c_shutdown(); } /*---------------------------------------------------------------------------*/ /* @@ -88,23 +89,50 @@ shutdown_handler(uint8_t mode) * wake up so we can turn power domains back on for I2C and SSI, and to make * sure everything on the board is off before CM3 shutdown. */ -LPM_MODULE(sensortag_module, NULL, shutdown_handler, lpm_wakeup_handler); +LPM_MODULE(sensortag_module, NULL, shutdown_handler, lpm_wakeup_handler, + LPM_DOMAIN_NONE); +/*---------------------------------------------------------------------------*/ +static void +configure_unused_pins(void) +{ + /* DP[0..3] */ + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_DP0); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_DP0, IOC_IOPULL_DOWN); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_DP1); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_DP1, IOC_IOPULL_DOWN); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_DP2); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_DP2, IOC_IOPULL_DOWN); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_DP3); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_DP3, IOC_IOPULL_DOWN); + + /* Devpack ID */ + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_DEVPK_ID); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_DEVPK_ID, IOC_IOPULL_UP); + + /* Digital Microphone */ + ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_MIC_POWER); + ti_lib_gpio_pin_clear((1 << BOARD_IOID_MIC_POWER)); + ti_lib_ioc_io_drv_strength_set(BOARD_IOID_MIC_POWER, IOC_CURRENT_2MA, + IOC_STRENGTH_MIN); + + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_AUDIO_DI); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_AUDIO_DI, IOC_IOPULL_DOWN); + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_AUDIO_CLK); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_AUDIO_CLK, IOC_IOPULL_DOWN); + + /* UART over Devpack - TX only (ToDo: Map all UART pins to Debugger) */ + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_DP5_UARTTX); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_DP5_UARTTX, IOC_IOPULL_DOWN); +} /*---------------------------------------------------------------------------*/ void board_init() { /* Disable global interrupts */ - uint8_t int_disabled = ti_lib_int_master_disable(); + bool int_disabled = ti_lib_int_master_disable(); power_domains_on(); - /* Configure all clock domains to run at full speed */ - ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_SYSBUS, PRCM_CLOCK_DIV_1); - ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_CPU, PRCM_CLOCK_DIV_1); - ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_TIMER, PRCM_CLOCK_DIV_1); - ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_SERIAL, PRCM_CLOCK_DIV_1); - ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_PERIPH, PRCM_CLOCK_DIV_1); - /* Enable GPIO peripheral */ ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_GPIO); @@ -112,37 +140,19 @@ board_init() ti_lib_prcm_load_set(); while(!ti_lib_prcm_load_get()); - /* Enable GPT0 module - Wait for the clock to be enabled */ - ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0); - ti_lib_prcm_load_set(); - while(!ti_lib_prcm_load_get()); - - /* Keys (input pullup) */ - ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_KEY_LEFT); - ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_KEY_RIGHT); - ti_lib_ioc_io_port_pull_set(BOARD_IOID_KEY_LEFT, IOC_IOPULL_UP); - ti_lib_ioc_io_port_pull_set(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP); - /* I2C controller */ - board_i2c_init(); - - /* Sensor interface */ - ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_MPU_INT); - ti_lib_ioc_io_port_pull_set(BOARD_IOID_MPU_INT, IOC_IOPULL_DOWN); - - ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_REED_RELAY); - ti_lib_ioc_io_port_pull_set(BOARD_IOID_REED_RELAY, IOC_IOPULL_DOWN); - - ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_MPU_POWER); - - /* Flash interface */ - ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_FLASH_CS); - ti_lib_gpio_pin_write(BOARD_FLASH_CS, 1); + board_i2c_wakeup(); buzzer_init(); + /* Make sure the external flash is in the lower power mode */ + ext_flash_init(); + lpm_register_module(&sensortag_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/sensortag/board.h b/platform/srf06-cc26xx/sensortag/board.h index 00afb98f2..fc293f5c0 100644 --- a/platform/srf06-cc26xx/sensortag/board.h +++ b/platform/srf06-cc26xx/sensortag/board.h @@ -100,12 +100,16 @@ * Those values are not meant to be modified by the user * @{ */ -#define BOARD_IOID_UART_RX IOID_17 +#define BOARD_IOID_DP4_UARTRX IOID_28 +#define BOARD_IOID_DP5_UARTTX IOID_29 + +#define BOARD_IOID_UART_RX BOARD_IOID_DP4_UARTRX #define BOARD_IOID_UART_TX IOID_16 + #define BOARD_IOID_UART_CTS IOID_UNUSED #define BOARD_IOID_UART_RTS IOID_UNUSED -#define BOARD_UART_RXD (1 << BOARD_IOID_UART_RXD) -#define BOARD_UART_TXD (1 << BOARD_IOID_UART_TXD) +#define BOARD_UART_RX (1 << BOARD_IOID_UART_RX) +#define BOARD_UART_TX (1 << BOARD_IOID_UART_TX) #define BOARD_UART_CTS (1 << BOARD_IOID_UART_CTS) #define BOARD_UART_RTS (1 << BOARD_IOID_UART_RTS) /** @} */ @@ -156,7 +160,7 @@ */ #define BOARD_IOID_FLASH_CS IOID_14 #define BOARD_FLASH_CS (1 << BOARD_IOID_FLASH_CS) -#define BOARD_SPI_CLK_FLASH IOID_11 +#define BOARD_IOID_SPI_CLK_FLASH IOID_17 /** @} */ /*---------------------------------------------------------------------------*/ /** @@ -183,6 +187,44 @@ #define BOARD_MPU_POWER (1 << BOARD_IOID_MPU_POWER) /** @} */ /*---------------------------------------------------------------------------*/ +/** + * \brief Board devpack IOID mappings (LCD etc.) + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_AUDIOFS_TDO IOID_16 +#define BOARD_IOID_DEVPACK_CS IOID_20 +#define BOARD_IOID_DEVPK_LCD_EXTCOMIN IOID_22 +#define BOARD_IOID_AUDIODO IOID_22 +#define BOARD_IOID_DP2 IOID_23 +#define BOARD_IOID_DP1 IOID_24 +#define BOARD_IOID_DP0 IOID_25 +#define BOARD_IOID_DP3 IOID_27 +#define BOARD_IOID_DEVPK_ID IOID_30 +#define BOARD_DEVPACK_CS (1 << BOARD_IOID_DEVPACK_CS) +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief TMP Sensor + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_TMP_RDY IOID_1 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief Digital Microphone + * + * Those values are not meant to be modified by the user + * @{ + */ +#define BOARD_IOID_MIC_POWER IOID_13 +#define BOARD_IOID_AUDIO_DI IOID_2 +#define BOARD_IOID_AUDIO_CLK IOID_11 +/** @} */ +/*---------------------------------------------------------------------------*/ /** * \name Device string used on startup * @{ diff --git a/platform/srf06-cc26xx/sensortag/button-sensor.c b/platform/srf06-cc26xx/sensortag/button-sensor.c index 089ea7332..06a2d2eaa 100644 --- a/platform/srf06-cc26xx/sensortag/button-sensor.c +++ b/platform/srf06-cc26xx/sensortag/button-sensor.c @@ -55,10 +55,9 @@ /*---------------------------------------------------------------------------*/ #define BUTTON_GPIO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \ IOC_IOPULL_UP | IOC_SLEW_DISABLE | \ - IOC_HYST_DISABLE | IOC_BOTH_EDGES | \ + IOC_HYST_ENABLE | IOC_BOTH_EDGES | \ IOC_INT_ENABLE | IOC_IOMODE_NORMAL | \ - IOC_NO_WAKE_UP | IOC_INPUT_ENABLE | \ - IOC_JTAG_DISABLE) + IOC_NO_WAKE_UP | IOC_INPUT_ENABLE) /*---------------------------------------------------------------------------*/ #define DEBOUNCE_DURATION (CLOCK_SECOND >> 5) @@ -116,7 +115,7 @@ button_press_handler(uint8_t ioid) sensors_changed(&button_right_sensor); } } else { - lpm_shutdown(BOARD_IOID_KEY_RIGHT); + lpm_shutdown(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP, IOC_WAKE_ON_LOW); } } } @@ -227,7 +226,7 @@ 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; + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; } else if(type == BUTTON_SENSOR_VALUE_DURATION) { return (int)left_timer.duration; } @@ -239,7 +238,7 @@ 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; + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; } else if(type == BUTTON_SENSOR_VALUE_DURATION) { return (int)right_timer.duration; } diff --git a/platform/srf06-cc26xx/sensortag/button-sensor.h b/platform/srf06-cc26xx/sensortag/button-sensor.h index 6e15b4d4c..25acb104f 100644 --- a/platform/srf06-cc26xx/sensortag/button-sensor.h +++ b/platform/srf06-cc26xx/sensortag/button-sensor.h @@ -54,7 +54,6 @@ #define BUTTON_SENSOR_VALUE_RELEASED 0 #define BUTTON_SENSOR_VALUE_PRESSED 1 /*---------------------------------------------------------------------------*/ -#define button_sensor button_left_sensor extern const struct sensors_sensor button_left_sensor; extern const struct sensors_sensor button_right_sensor; /*---------------------------------------------------------------------------*/ diff --git a/platform/srf06-cc26xx/sensortag/buzzer.c b/platform/srf06-cc26xx/sensortag/buzzer.c index 57d063897..d7f48e4de 100644 --- a/platform/srf06-cc26xx/sensortag/buzzer.c +++ b/platform/srf06-cc26xx/sensortag/buzzer.c @@ -46,19 +46,12 @@ #include /*---------------------------------------------------------------------------*/ static uint8_t buzzer_on; -static lpm_power_domain_lock_t lock; +LPM_MODULE(buzzer_module, NULL, NULL, NULL, LPM_DOMAIN_PERIPH); /*---------------------------------------------------------------------------*/ void buzzer_init() { buzzer_on = 0; - - /* Drive the I/O ID with GPT0 / Timer A */ - ti_lib_ioc_port_configure_set(BOARD_IOID_BUZZER, IOC_PORT_MCU_PORT_EVENT0, - IOC_STD_OUTPUT); - - /* GPT0 / Timer A: PWM, Interrupt Enable */ - HWREG(GPT0_BASE + GPT_O_TAMR) = (TIMER_CFG_A_PWM & 0xFF) | GPT_TAMR_TAPWMIE; } /*---------------------------------------------------------------------------*/ uint8_t @@ -72,9 +65,28 @@ buzzer_start(int freq) { uint32_t load; + /* Enable GPT0 clocks under active, sleep, deep sleep */ + ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0); + ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_TIMER0); + ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_TIMER0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + /* Drive the I/O ID with GPT0 / Timer A */ + ti_lib_ioc_port_configure_set(BOARD_IOID_BUZZER, IOC_PORT_MCU_PORT_EVENT0, + IOC_STD_OUTPUT); + + /* GPT0 / Timer A: PWM, Interrupt Enable */ + HWREG(GPT0_BASE + GPT_O_TAMR) = (TIMER_CFG_A_PWM & 0xFF) | GPT_TAMR_TAPWMIE; + buzzer_on = 1; - lpm_pd_lock_obtain(&lock, PRCM_DOMAIN_PERIPH); + /* + * Register ourself with LPM. This will keep the PERIPH PD powered on + * during deep sleep, allowing the buzzer to keep working while the chip is + * being power-cycled + */ + lpm_register_module(&buzzer_module); /* Stop the timer */ ti_lib_timer_disable(GPT0_BASE, TIMER_A); @@ -88,12 +100,6 @@ buzzer_start(int freq) /* Start */ ti_lib_timer_enable(GPT0_BASE, TIMER_A); } - - /* Run in sleep mode */ - ti_lib_prcm_peripheral_sleep_enable(PRCM_PERIPH_TIMER0); - ti_lib_prcm_peripheral_deep_sleep_enable(PRCM_PERIPH_TIMER0); - ti_lib_prcm_load_set(); - while(!ti_lib_prcm_load_get()); } /*---------------------------------------------------------------------------*/ void @@ -101,24 +107,37 @@ buzzer_stop() { buzzer_on = 0; - lpm_pd_lock_release(&lock); + /* + * Unregister the buzzer module from LPM. This will effectively release our + * lock for the PERIPH PD allowing it to be powered down (unless some other + * module keeps it on) + */ + lpm_unregister_module(&buzzer_module); /* Stop the timer */ ti_lib_timer_disable(GPT0_BASE, TIMER_A); /* - * Stop running in sleep mode. - * ToDo: Currently GPT0 is in use by clock_delay_usec (GPT0/TB) and by this - * module here (GPT0/TA). clock_delay_usec will never need GPT0/TB in sleep - * mode and we control TA here. Thus, with the current setup, it's OK to - * control whether GPT0 runs in sleep mode in this module here. However, if - * some other module at some point starts using GPT0, we should change this - * to happen through an umbrella module + * Stop the module clock: + * + * Currently GPT0 is in use by clock_delay_usec (GPT0/TB) and by this + * module here (GPT0/TA). + * + * clock_delay_usec + * - is definitely not running when we enter here and + * - handles the module clock internally + * + * Thus, we can safely change the state of module clocks here. */ + ti_lib_prcm_peripheral_run_disable(PRCM_PERIPH_TIMER0); ti_lib_prcm_peripheral_sleep_disable(PRCM_PERIPH_TIMER0); ti_lib_prcm_peripheral_deep_sleep_disable(PRCM_PERIPH_TIMER0); ti_lib_prcm_load_set(); while(!ti_lib_prcm_load_get()); + + /* Un-configure the pin */ + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_BUZZER); + ti_lib_ioc_io_input_set(BOARD_IOID_BUZZER, IOC_INPUT_DISABLE); } /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/platform/srf06-cc26xx/sensortag/ext-flash.c b/platform/srf06-cc26xx/sensortag/ext-flash.c index 83d2758a4..d896473d3 100644 --- a/platform/srf06-cc26xx/sensortag/ext-flash.c +++ b/platform/srf06-cc26xx/sensortag/ext-flash.c @@ -72,7 +72,7 @@ /* Part specific constants */ #define BLS_MANUFACTURER_ID 0xEF -#define BLS_DEVICE_ID 0x11 +#define BLS_DEVICE_ID 0x12 #define BLS_PROGRAM_PAGE_SIZE 256 #define BLS_ERASE_SECTOR_SIZE 4096 @@ -140,50 +140,8 @@ wait_ready(void) } /*---------------------------------------------------------------------------*/ /** - * \brief Put the device in power save mode. No access to data; only - * the status register is accessible. - * \return True when SPI transactions succeed - */ -static bool -power_down(void) -{ - uint8_t cmd; - bool success; - - cmd = BLS_CODE_DP; - select(); - success = board_spi_write(&cmd, sizeof(cmd)); - deselect(); - - return success; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Take device out of power save mode and prepare it for normal operation - * \return True if the command was written successfully - */ -static bool -power_standby(void) -{ - uint8_t cmd; - bool success; - - cmd = BLS_CODE_RDP; - select(); - success = board_spi_write(&cmd, sizeof(cmd)); - - if(success) { - success = wait_ready() == 0; - } - - deselect(); - - return success; -} -/*---------------------------------------------------------------------------*/ -/** - * Verify the flash part. - * @return True when successful. + * \brief Verify the flash part. + * \return True when successful. */ static bool verify_part(void) @@ -210,6 +168,57 @@ verify_part(void) return true; } /*---------------------------------------------------------------------------*/ +/** + * \brief Put the device in power save mode. No access to data; only + * the status register is accessible. + */ +static void +power_down(void) +{ + uint8_t cmd; + uint8_t i; + + cmd = BLS_CODE_DP; + select(); + board_spi_write(&cmd, sizeof(cmd)); + deselect(); + + i = 0; + while(i < 10) { + if(!verify_part()) { + /* Verify Part failed: Device is powered down */ + return; + } + i++; + } + + /* Should not be required */ + deselect(); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Take device out of power save mode and prepare it for normal operation + * \return True if the command was written successfully + */ +static bool +power_standby(void) +{ + uint8_t cmd; + bool success; + + cmd = BLS_CODE_RDP; + select(); + success = board_spi_write(&cmd, sizeof(cmd)); + + if(success) { + success = wait_ready() == 0; + } + + deselect(); + + return success; +} +/*---------------------------------------------------------------------------*/ /** * \brief Enable write. * \return Zero when successful. @@ -232,7 +241,7 @@ write_enable(void) bool ext_flash_open() { - board_spi_open(4000000, BOARD_SPI_CLK_FLASH); + board_spi_open(4000000, BOARD_IOID_SPI_CLK_FLASH); /* GPIO pin configuration */ ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_FLASH_CS); @@ -406,4 +415,11 @@ ext_flash_test(void) return ret; } /*---------------------------------------------------------------------------*/ +void +ext_flash_init() +{ + ext_flash_open(); + ext_flash_close(); +} +/*---------------------------------------------------------------------------*/ /** @} */ diff --git a/platform/srf06-cc26xx/sensortag/ext-flash.h b/platform/srf06-cc26xx/sensortag/ext-flash.h index ca2ef80ea..3038872cd 100644 --- a/platform/srf06-cc26xx/sensortag/ext-flash.h +++ b/platform/srf06-cc26xx/sensortag/ext-flash.h @@ -54,6 +54,8 @@ bool ext_flash_open(void); /** * \brief Close the storage driver + * + * This call will put the device in its lower power mode (power down). */ void ext_flash_close(void); @@ -94,6 +96,17 @@ bool ext_flash_write(size_t offset, size_t length, const uint8_t *buf); * \return True when successful. */ bool ext_flash_test(void); + +/** + * \brief Initialise the external flash + * + * This function will explicitly put the part in its lowest power mode + * (power-down). + * + * In order to perform any operation, the caller must first wake the device + * up by calling ext_flash_open() + */ +void ext_flash_init(void); /*---------------------------------------------------------------------------*/ #endif /* EXT_FLASH_H_ */ /*---------------------------------------------------------------------------*/ diff --git a/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.c b/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.c new file mode 100644 index 000000000..8fdd6d847 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.c @@ -0,0 +1,304 @@ +/* + * 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. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup sensortag-cc26xx-hdc-sensor + * @{ + * + * \file + * Driver for the Sensortag-CC26xx HDC sensor + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "sys/ctimer.h" +#include "lib/sensors.h" +#include "hdc-1000-sensor.h" +#include "sensor-common.h" +#include "board-i2c.h" + +#include "ti-lib.h" + +#include +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +/* Sensor I2C address */ +#define SENSOR_I2C_ADDRESS 0x43 + +/* Registers */ +#define HDC1000_REG_TEMP 0x00 /* Temperature */ +#define HDC1000_REG_HUM 0x01 /* Humidity */ +#define HDC1000_REG_CONFIG 0x02 /* Configuration */ +#define HDC1000_REG_SERID_H 0xFB /* Serial ID high */ +#define HDC1000_REG_SERID_M 0xFC /* Serial ID middle */ +#define HDC1000_REG_SERID_L 0xFD /* Serial ID low */ +#define HDC1000_REG_MANF_ID 0xFE /* Manufacturer ID */ +#define HDC1000_REG_DEV_ID 0xFF /* Device ID */ + +/* Fixed values */ +#define HDC1000_VAL_MANF_ID 0x5449 +#define HDC1000_VAL_DEV_ID 0x1000 +#define HDC1000_VAL_CONFIG 0x1000 /* 14 bit, acquired in sequence */ + +/* Sensor selection/deselection */ +#define SENSOR_SELECT() board_i2c_select(BOARD_I2C_INTERFACE_0, SENSOR_I2C_ADDRESS) +#define SENSOR_DESELECT() board_i2c_deselect() +/*---------------------------------------------------------------------------*/ +/* Byte swap of 16-bit register value */ +#define HI_UINT16(a) (((a) >> 8) & 0xFF) +#define LO_UINT16(a) ((a) & 0xFF) + +#define SWAP(v) ((LO_UINT16(v) << 8) | HI_UINT16(v)) +/*---------------------------------------------------------------------------*/ +/* Raw data as returned from the sensor (Big Endian) */ +typedef struct sensor_data { + uint16_t temp; + uint16_t hum; +} sensor_data_t; + +/* Raw data, little endian */ +static uint16_t raw_temp; +static uint16_t raw_hum; +/*---------------------------------------------------------------------------*/ +static bool success; +static sensor_data_t data; +/*---------------------------------------------------------------------------*/ +static int enabled = HDC_1000_SENSOR_STATUS_DISABLED; +/*---------------------------------------------------------------------------*/ +/* + * Maximum measurement durations in clock ticks. We use 14bit resolution, thus: + * - Tmp: 6.35ms + * - RH: 6.5ms + */ +#define MEASUREMENT_DURATION 2 + +/* + * Wait SENSOR_STARTUP_DELAY clock ticks between activation and triggering a + * reading (max 15ms) + */ +#define SENSOR_STARTUP_DELAY 3 + +static struct ctimer startup_timer; +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise the humidity sensor driver + * \return True if I2C operation successful + */ +static bool +sensor_init(void) +{ + uint16_t val; + + SENSOR_SELECT(); + + /* Enable reading data in one operation */ + val = SWAP(HDC1000_VAL_CONFIG); + success = sensor_common_write_reg(HDC1000_REG_CONFIG, (uint8_t *)&val, 2); + + SENSOR_DESELECT(); + + return success; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Start measurement + */ +static void +start(void) +{ + if(success) { + SENSOR_SELECT(); + + success = board_i2c_write_single(HDC1000_REG_TEMP); + SENSOR_DESELECT(); + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Take readings from the sensor + * \return true of I2C operations successful + */ +static bool +read_data() +{ + bool valid; + + if(success) { + SENSOR_SELECT(); + + success = board_i2c_read((uint8_t *)&data, sizeof(data)); + SENSOR_DESELECT(); + + /* Store temperature */ + raw_temp = SWAP(data.temp); + + /* Store humidity */ + raw_hum = SWAP(data.hum); + } + + valid = success; + success = true; + + return valid; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Convert raw data to temperature and humidity + * \param temp - converted temperature + * \param hum - converted humidity + */ +static void +convert(float *temp, float *hum) +{ + /* Convert temperature to degrees C */ + *temp = ((double)(int16_t)raw_temp / 65536) * 165 - 40; + + /* Convert relative humidity to a %RH value */ + *hum = ((double)raw_hum / 65536) * 100; +} +/*---------------------------------------------------------------------------*/ +static void +notify_ready(void *not_used) +{ + enabled = HDC_1000_SENSOR_STATUS_READINGS_READY; + + /* Latch readings */ + read_data(); + + sensors_changed(&hdc_1000_sensor); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns a reading from the sensor + * \param type HDC_1000_SENSOR_TYPE_TEMP or HDC_1000_SENSOR_TYPE_HUMIDITY + * \return Temperature (centi degrees C) or Humidity (centi %RH) + */ +static int +value(int type) +{ + int rv; + float temp; + float hum; + + if(enabled != HDC_1000_SENSOR_STATUS_READINGS_READY) { + PRINTF("Sensor disabled or starting up (%d)\n", enabled); + return CC26XX_SENSOR_READING_ERROR; + } + + if((type != HDC_1000_SENSOR_TYPE_TEMP) && + type != HDC_1000_SENSOR_TYPE_HUMIDITY) { + PRINTF("Invalid type\n"); + return CC26XX_SENSOR_READING_ERROR; + } else { + convert(&temp, &hum); + PRINTF("HDC: %04X %04X t=%d h=%d\n", raw_temp, raw_hum, + (int)(temp * 100), (int)(hum * 100)); + + if(type == HDC_1000_SENSOR_TYPE_TEMP) { + rv = (int)(temp * 100); + } else if(type == HDC_1000_SENSOR_TYPE_HUMIDITY) { + rv = (int)(hum * 100); + } + } + return rv; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the HDC1000 sensor. + * + * \param type Activate, enable or disable the sensor. See below + * \param enable + * + * When type == SENSORS_HW_INIT we turn on the hardware + * When type == SENSORS_ACTIVE and enable==1 we enable the sensor + * When type == SENSORS_ACTIVE and enable==0 we disable the sensor + */ +static int +configure(int type, int enable) +{ + switch(type) { + case SENSORS_HW_INIT: + raw_temp = 0; + raw_hum = 0; + memset(&data, 0, sizeof(data)); + + sensor_init(); + enabled = HDC_1000_SENSOR_STATUS_INITIALISED; + break; + case SENSORS_ACTIVE: + /* Must be initialised first */ + if(enabled == HDC_1000_SENSOR_STATUS_DISABLED) { + return HDC_1000_SENSOR_STATUS_DISABLED; + } + if(enable) { + start(); + ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL); + enabled = HDC_1000_SENSOR_STATUS_TAKING_READINGS; + } else { + ctimer_stop(&startup_timer); + enabled = HDC_1000_SENSOR_STATUS_INITIALISED; + } + break; + default: + break; + } + return enabled; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the status of the sensor + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return One of the SENSOR_STATUS_xyz defines + */ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + break; + default: + break; + } + return HDC_1000_SENSOR_STATUS_DISABLED; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(hdc_1000_sensor, "HDC1000", value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.h b/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.h new file mode 100755 index 000000000..990b1ab69 --- /dev/null +++ b/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.h @@ -0,0 +1,116 @@ +/* + * 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. + */ +/* + * 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. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup sensortag-cc26xx-peripherals + * @{ + * + * \defgroup sensortag-cc26xx-hdc-sensor SensorTag 2.0 TI HDC1000 Sensor + * + * Due to the time required for the sensor to startup, this driver is meant to + * be used in an asynchronous fashion. The caller must first activate the + * sensor by calling SENSORS_ACTIVATE(). This will trigger the sensor's startup + * sequence, but the call will not wait for it to complete so that the CPU can + * perform other tasks or drop to a low power mode. Once the sensor has taken + * readings, it will automatically go back to low power mode. + * + * Once the sensor is stable, the driver will retrieve readings from the sensor + * and latch them. It will then generate a sensors_changed event. + * + * The user can then retrieve readings by calling .value() and by passing + * either HDC_1000_SENSOR_TYPE_TEMP or HDC_1000_SENSOR_TYPE_HUMIDITY as the + * argument. Multiple calls to value() will not trigger new readings, they will + * simply return the most recent latched values. + * + * The user can query the sensor's status by calling .status() + * + * To get a fresh reading, the user must trigger a new reading cycle by calling + * SENSORS_ACTIVATE(). + * @{ + * + * \file + * Header file for the Sensortag-CC26ss TI HDC1000 sensor + */ +/*---------------------------------------------------------------------------*/ +#ifndef HDC_1000_SENSOR_H +#define HDC_1000_SENSOR_H +/*---------------------------------------------------------------------------*/ +#include "lib/sensors.h" +/*---------------------------------------------------------------------------*/ +#define HDC_1000_SENSOR_TYPE_TEMP 1 +#define HDC_1000_SENSOR_TYPE_HUMIDITY 2 +/*---------------------------------------------------------------------------*/ +/** + * \name HDC1000 driver states + * @{ + */ +#define HDC_1000_SENSOR_STATUS_DISABLED 0 /**< Not initialised */ +#define HDC_1000_SENSOR_STATUS_INITIALISED 1 /**< Initialised but idle */ +#define HDC_1000_SENSOR_STATUS_TAKING_READINGS 2 /**< Readings in progress */ +#define HDC_1000_SENSOR_STATUS_READINGS_READY 3 /**< Both readings ready */ +/** @} */ +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor hdc_1000_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* HDC_1000_SENSOR_H */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.c b/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.c index fd7bff688..275f2b352 100644 --- a/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.c +++ b/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.c @@ -212,12 +212,12 @@ static uint8_t acc_range_reg; static uint8_t val; static uint8_t interrupt_status; /*---------------------------------------------------------------------------*/ -#define SENSOR_STATUS_DISABLED 0 -#define SENSOR_STATUS_BOOTING 1 -#define SENSOR_STATUS_ENABLED 2 +#define SENSOR_STATE_DISABLED 0 +#define SENSOR_STATE_BOOTING 1 +#define SENSOR_STATE_ENABLED 2 -static int enabled = SENSOR_STATUS_DISABLED; -static int elements; +static int state = SENSOR_STATE_DISABLED; +static int elements = MPU_9250_SENSOR_TYPE_NONE; /*---------------------------------------------------------------------------*/ /* 3 16-byte words for all sensor readings */ #define SENSOR_DATA_BUF_SIZE 3 @@ -289,7 +289,9 @@ static void select_axes(void) { val = ~mpu_config; + SENSOR_SELECT(); sensor_common_write_reg(PWR_MGMT_2, &val, 1); + SENSOR_DESELECT(); } /*---------------------------------------------------------------------------*/ static void @@ -334,37 +336,6 @@ acc_set_range(uint8_t new_range) return success; } /*---------------------------------------------------------------------------*/ -/** - * \brief Initialise the MPU - * \return True if success - */ -static bool -init_sensor(void) -{ - bool ret; - - interrupt_status = false; - acc_range = ACC_RANGE_INVALID; - mpu_config = 0; /* All axes off */ - - /* Device reset */ - val = 0x80; - SENSOR_SELECT(); - ret = sensor_common_write_reg(PWR_MGMT_1, &val, 1); - SENSOR_DESELECT(); - - if(ret) { - delay_ms(200); - - /* Initial configuration */ - acc_set_range(ACC_RANGE_8G); - /* Power save */ - sensor_sleep(); - } - - return ret; -} -/*---------------------------------------------------------------------------*/ /** * \brief Check whether a data or wake on motion interrupt has occurred * \return Return the interrupt status @@ -450,13 +421,13 @@ gyro_read(uint16_t *data) /* Burst read of all gyroscope values */ success = sensor_common_read_reg(GYRO_XOUT_H, (uint8_t *)data, DATA_SIZE); - SENSOR_DESELECT(); - if(success) { convert_to_le((uint8_t *)data, DATA_SIZE); } else { sensor_common_set_error_data((uint8_t *)data, DATA_SIZE); } + + SENSOR_DESELECT(); } else { success = false; } @@ -514,15 +485,13 @@ gyro_convert(int16_t raw_data) static void notify_ready(void *not_used) { - enabled = SENSOR_STATUS_ENABLED; + state = SENSOR_STATE_ENABLED; sensors_changed(&mpu_9250_sensor); } /*---------------------------------------------------------------------------*/ static void initialise(void *not_used) { - init_sensor(); - /* Configure the accelerometer range */ if((elements & MPU_9250_SENSOR_TYPE_ACC) != 0) { acc_set_range(MPU_9250_SENSOR_ACC_RANGE); @@ -537,7 +506,7 @@ static void power_up(void) { ti_lib_gpio_pin_write(BOARD_MPU_POWER, 1); - enabled = SENSOR_STATUS_BOOTING; + state = SENSOR_STATE_BOOTING; ctimer_set(&startup_timer, SENSOR_BOOT_DELAY, initialise, NULL); } @@ -553,7 +522,7 @@ value(int type) int rv; float converted_val = 0; - if(enabled == SENSOR_STATUS_DISABLED) { + if(state == SENSOR_STATE_DISABLED) { PRINTF("MPU: Sensor Disabled\n"); return CC26XX_SENSOR_READING_ERROR; } @@ -632,33 +601,42 @@ configure(int type, int enable) { switch(type) { case SENSORS_HW_INIT: + ti_lib_rom_ioc_pin_type_gpio_input(BOARD_IOID_MPU_INT); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_MPU_INT, IOC_IOPULL_DOWN); + ti_lib_ioc_io_hyst_set(BOARD_IOID_MPU_INT, IOC_HYST_ENABLE); + + ti_lib_rom_ioc_pin_type_gpio_output(BOARD_IOID_MPU_POWER); + ti_lib_ioc_io_drv_strength_set(BOARD_IOID_MPU_POWER, IOC_CURRENT_4MA, + IOC_STRENGTH_MAX); + ti_lib_gpio_pin_clear(BOARD_MPU_POWER); elements = MPU_9250_SENSOR_TYPE_NONE; break; case SENSORS_ACTIVE: - if((enable & MPU_9250_SENSOR_TYPE_ACC) != 0 || - (enable & MPU_9250_SENSOR_TYPE_GYRO) != 0) { + if(((enable & MPU_9250_SENSOR_TYPE_ACC) != 0) || + ((enable & MPU_9250_SENSOR_TYPE_GYRO) != 0)) { PRINTF("MPU: Enabling\n"); elements = enable & MPU_9250_SENSOR_TYPE_ALL; power_up(); - enabled = SENSOR_STATUS_BOOTING; + state = SENSOR_STATE_BOOTING; } else { PRINTF("MPU: Disabling\n"); - ctimer_stop(&startup_timer); - elements = MPU_9250_SENSOR_TYPE_NONE; - enable_sensor(0); - while(ti_lib_i2c_master_busy(I2C0_BASE)); - enabled = SENSOR_STATUS_DISABLED; + if(HWREG(GPIO_BASE + GPIO_O_DOUT31_0) & BOARD_MPU_POWER) { + /* Then check our state */ + elements = MPU_9250_SENSOR_TYPE_NONE; + ctimer_stop(&startup_timer); + sensor_sleep(); + while(ti_lib_i2c_master_busy(I2C0_BASE)); + state = SENSOR_STATE_DISABLED; + ti_lib_gpio_pin_clear(BOARD_MPU_POWER); + } } break; - case MPU_9250_SENSOR_SHUTDOWN: - ti_lib_gpio_pin_write(BOARD_MPU_POWER, 0); - break; default: break; } - return enabled; + return state; } /*---------------------------------------------------------------------------*/ /** @@ -672,12 +650,12 @@ status(int type) switch(type) { case SENSORS_ACTIVE: case SENSORS_READY: - return enabled; + return state; break; default: break; } - return SENSOR_STATUS_DISABLED; + return SENSOR_STATE_DISABLED; } /*---------------------------------------------------------------------------*/ SENSORS_SENSOR(mpu_9250_sensor, "MPU9250", value, configure, status); diff --git a/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.h b/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.h index 46836a538..c6c4d5534 100644 --- a/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.h +++ b/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.h @@ -86,8 +86,6 @@ #define MPU_9250_SENSOR_TYPE_NONE 0 #define MPU_9250_SENSOR_TYPE_ALL (MPU_9250_SENSOR_TYPE_ACC | \ MPU_9250_SENSOR_TYPE_GYRO) - -#define MPU_9250_SENSOR_SHUTDOWN 0xFF /*---------------------------------------------------------------------------*/ /* Accelerometer range */ #define MPU_9250_SENSOR_ACC_RANGE_2G 0 diff --git a/platform/srf06-cc26xx/sensortag/opt-3001-sensor.c b/platform/srf06-cc26xx/sensortag/opt-3001-sensor.c index 7cb41bf6d..f1cbf695e 100644 --- a/platform/srf06-cc26xx/sensortag/opt-3001-sensor.c +++ b/platform/srf06-cc26xx/sensortag/opt-3001-sensor.c @@ -69,16 +69,42 @@ #define REG_MANUFACTURER_ID 0x7E #define REG_DEVICE_ID 0x7F /*---------------------------------------------------------------------------*/ -/* Register values */ -#define MANUFACTURER_ID 0x5449 /* TI */ -#define DEVICE_ID 0x3001 /* Opt 3001 */ -#define CONFIG_RESET 0xC810 -#define CONFIG_TEST 0xCC10 -#define CONFIG_ENABLE 0x10CC /* 0xCC10 */ -#define CONFIG_DISABLE 0x108C /* 0xC810 */ -/*---------------------------------------------------------------------------*/ -/* Bit values */ -#define DATA_RDY_BIT 0x0080 /* Data ready */ +/* + * Configuration Register Bits and Masks. + * We use uint16_t to read from / write to registers, meaning that the + * register's MSB is the variable's LSB. + */ +#define CONFIG_RN 0x00F0 /* [15..12] Range Number */ +#define CONFIG_CT 0x0008 /* [11] Conversion Time */ +#define CONFIG_M 0x0006 /* [10..9] Mode of Conversion */ +#define CONFIG_OVF 0x0001 /* [8] Overflow */ +#define CONFIG_CRF 0x8000 /* [7] Conversion Ready Field */ +#define CONFIG_FH 0x4000 /* [6] Flag High */ +#define CONFIG_FL 0x2000 /* [5] Flag Low */ +#define CONFIG_L 0x1000 /* [4] Latch */ +#define CONFIG_POL 0x0800 /* [3] Polarity */ +#define CONFIG_ME 0x0400 /* [2] Mask Exponent */ +#define CONFIG_FC 0x0300 /* [1..0] Fault Count */ + +/* Possible Values for CT */ +#define CONFIG_CT_100 0x0000 +#define CONFIG_CT_800 CONFIG_CT + +/* Possible Values for M */ +#define CONFIG_M_CONTI 0x0004 +#define CONFIG_M_SINGLE 0x0002 +#define CONFIG_M_SHUTDOWN 0x0000 + +/* Reset Value for the register 0xC810. All zeros except: */ +#define CONFIG_RN_RESET 0x00C0 +#define CONFIG_CT_RESET CONFIG_CT_800 +#define CONFIG_L_RESET 0x1000 +#define CONFIG_DEFAULTS (CONFIG_RN_RESET | CONFIG_CT_100 | CONFIG_L_RESET) + +/* Enable / Disable */ +#define CONFIG_ENABLE_CONTINUOUS (CONFIG_M_CONTI | CONFIG_DEFAULTS) +#define CONFIG_ENABLE_SINGLE_SHOT (CONFIG_M_SINGLE | CONFIG_DEFAULTS) +#define CONFIG_DISABLE CONFIG_DEFAULTS /*---------------------------------------------------------------------------*/ /* Register length */ #define REGISTER_LENGTH 2 @@ -86,24 +112,22 @@ /* Sensor data size */ #define DATA_LENGTH 2 /*---------------------------------------------------------------------------*/ -#define SENSOR_STATUS_DISABLED 0 -#define SENSOR_STATUS_NOT_READY 1 -#define SENSOR_STATUS_ENABLED 2 +/* + * SENSOR_STATE_SLEEPING and SENSOR_STATE_ACTIVE are mutually exclusive. + * SENSOR_STATE_DATA_READY can be ORd with both of the above. For example the + * sensor may be sleeping but with a conversion ready to read out. + */ +#define SENSOR_STATE_SLEEPING 0 +#define SENSOR_STATE_ACTIVE 1 +#define SENSOR_STATE_DATA_READY 2 -static int enabled = SENSOR_STATUS_DISABLED; +static int state = SENSOR_STATE_SLEEPING; /*---------------------------------------------------------------------------*/ /* Wait SENSOR_STARTUP_DELAY for the sensor to be ready - 125ms */ #define SENSOR_STARTUP_DELAY (CLOCK_SECOND >> 3) static struct ctimer startup_timer; /*---------------------------------------------------------------------------*/ -static void -notify_ready(void *not_used) -{ - enabled = SENSOR_STATUS_ENABLED; - sensors_changed(&opt_3001_sensor); -} -/*---------------------------------------------------------------------------*/ /** * \brief Select the sensor on the I2C bus */ @@ -114,6 +138,28 @@ select(void) board_i2c_select(BOARD_I2C_INTERFACE_0, OPT3001_I2C_ADDRESS); } /*---------------------------------------------------------------------------*/ +static void +notify_ready(void *not_used) +{ + /* + * Depending on the CONFIGURATION.CONVERSION_TIME bits, a conversion will + * take either 100 or 800 ms. Here we inspect the CONVERSION_READY bit and + * if the reading is ready we notify, otherwise we just reschedule ourselves + */ + uint16_t val; + + select(); + + sensor_common_read_reg(REG_CONFIGURATION, (uint8_t *)&val, REGISTER_LENGTH); + + if(val & CONFIG_CRF) { + sensors_changed(&opt_3001_sensor); + state = SENSOR_STATE_DATA_READY; + } else { + ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL); + } +} +/*---------------------------------------------------------------------------*/ /** * \brief Turn the sensor on/off * \param enable TRUE: on, FALSE: off @@ -122,13 +168,20 @@ static void enable_sensor(bool enable) { uint16_t val; + uint16_t had_data_ready = state & SENSOR_STATE_DATA_READY; select(); if(enable) { - val = CONFIG_ENABLE; + val = CONFIG_ENABLE_SINGLE_SHOT; + + /* Writing CONFIG_ENABLE_SINGLE_SHOT to M bits will clear CRF bits */ + state = SENSOR_STATE_ACTIVE; } else { val = CONFIG_DISABLE; + + /* Writing CONFIG_DISABLE to M bits will not clear CRF bits */ + state = SENSOR_STATE_SLEEPING | had_data_ready; } sensor_common_write_reg(REG_CONFIGURATION, (uint8_t *)&val, REGISTER_LENGTH); @@ -145,15 +198,15 @@ read_data(uint16_t *raw_data) bool success; uint16_t val; + if((state & SENSOR_STATE_DATA_READY) != SENSOR_STATE_DATA_READY) { + return false; + } + select(); success = sensor_common_read_reg(REG_CONFIGURATION, (uint8_t *)&val, REGISTER_LENGTH); - if(success) { - success = (val & DATA_RDY_BIT) == DATA_RDY_BIT; - } - if(success) { success = sensor_common_read_reg(REG_RESULT, (uint8_t *)&val, DATA_LENGTH); } @@ -196,14 +249,9 @@ value(int type) uint16_t raw_val; float converted_val; - if(enabled != SENSOR_STATUS_ENABLED) { - PRINTF("Sensor disabled or starting up (%d)\n", enabled); - return CC26XX_SENSOR_READING_ERROR; - } - rv = read_data(&raw_val); - if(rv == 0) { + if(rv == false) { return CC26XX_SENSOR_READING_ERROR; } @@ -229,30 +277,38 @@ value(int type) static int configure(int type, int enable) { + int rv = 0; + switch(type) { case SENSORS_HW_INIT: + /* + * Device reset won't reset the sensor, so we put it to sleep here + * explicitly + */ + enable_sensor(0); + rv = 0; break; case SENSORS_ACTIVE: if(enable) { enable_sensor(1); ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL); - enabled = SENSOR_STATUS_NOT_READY; + rv = 1; } else { ctimer_stop(&startup_timer); enable_sensor(0); - enabled = SENSOR_STATUS_DISABLED; + rv = 0; } break; default: break; } - return enabled; + return rv; } /*---------------------------------------------------------------------------*/ /** * \brief Returns the status of the sensor - * \param type SENSORS_ACTIVE or SENSORS_READY - * \return 1 if the sensor is enabled + * \param type ignored + * \return The state of the sensor SENSOR_STATE_xyz */ static int status(int type) @@ -260,12 +316,10 @@ status(int type) switch(type) { case SENSORS_ACTIVE: case SENSORS_READY: - return enabled; - break; default: break; } - return SENSOR_STATUS_DISABLED; + return state; } /*---------------------------------------------------------------------------*/ SENSORS_SENSOR(opt_3001_sensor, "OPT3001", value, configure, status); diff --git a/platform/srf06-cc26xx/sensortag/opt-3001-sensor.h b/platform/srf06-cc26xx/sensortag/opt-3001-sensor.h index 205ab00ff..a4160b729 100644 --- a/platform/srf06-cc26xx/sensortag/opt-3001-sensor.h +++ b/platform/srf06-cc26xx/sensortag/opt-3001-sensor.h @@ -40,14 +40,16 @@ * sequence, but the call will not wait for it to complete so that the CPU can * perform other tasks or drop to a low power mode. * - * Once the sensor is stable, the driver will generate a sensors_changed event. + * Once the reading and conversion are complete, the driver will generate a + * sensors_changed event. * - * Once a reading has been taken, the caller has two options: - * - Turn the sensor off by calling SENSORS_DEACTIVATE, but in order to take - * subsequent readings SENSORS_ACTIVATE must be called again - * - Leave the sensor on. In this scenario, the caller can simply keep calling - * value() for subsequent readings, but having the sensor on will consume - * energy + * We use single-shot readings. In this mode, the hardware automatically goes + * back to its shutdown mode after the conversion is finished. However, it will + * still respond to I2C operations, so the last conversion can still be read + * out. + * + * In order to take a new reading, the caller has to use SENSORS_ACTIVATE + * again. * @{ * * \file diff --git a/platform/srf06-cc26xx/sensortag/reed-relay.c b/platform/srf06-cc26xx/sensortag/reed-relay.c index b5956f6f8..9be161b48 100644 --- a/platform/srf06-cc26xx/sensortag/reed-relay.c +++ b/platform/srf06-cc26xx/sensortag/reed-relay.c @@ -50,12 +50,11 @@ /*---------------------------------------------------------------------------*/ static struct timer debouncetimer; /*---------------------------------------------------------------------------*/ -#define REED_ISR_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \ +#define REED_IO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \ IOC_IOPULL_DOWN | IOC_SLEW_DISABLE | \ IOC_HYST_DISABLE | IOC_BOTH_EDGES | \ IOC_INT_DISABLE | IOC_IOMODE_NORMAL | \ - IOC_NO_WAKE_UP | IOC_INPUT_ENABLE | \ - IOC_JTAG_DISABLE) + IOC_NO_WAKE_UP | IOC_INPUT_ENABLE) /*---------------------------------------------------------------------------*/ /** * \brief Handler for Sensortag-CC26XX reed interrupts @@ -94,10 +93,12 @@ configure(int type, int value) ti_lib_ioc_int_disable(BOARD_IOID_REED_RELAY); ti_lib_gpio_event_clear(1 << BOARD_IOID_REED_RELAY); - /* Enabled the GPIO clock when the CM3 is running */ + /* Enable the GPIO clock when the CM3 is running */ ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_GPIO); + + /* S/W control, input, pull-down */ ti_lib_ioc_port_configure_set(BOARD_IOID_REED_RELAY, IOC_PORT_GPIO, - REED_ISR_CFG); + REED_IO_CFG); gpio_interrupt_register_handler(BOARD_IOID_REED_RELAY, reed_interrupt_handler); diff --git a/platform/srf06-cc26xx/sensortag/sensortag-sensors.c b/platform/srf06-cc26xx/sensortag/sensortag-sensors.c index a8f26aefe..bcd0fe367 100644 --- a/platform/srf06-cc26xx/sensortag/sensortag-sensors.c +++ b/platform/srf06-cc26xx/sensortag/sensortag-sensors.c @@ -41,7 +41,7 @@ #include "sensortag/bmp-280-sensor.h" #include "sensortag/tmp-007-sensor.h" #include "sensortag/opt-3001-sensor.h" -#include "sensortag/sht-21-sensor.h" +#include "sensortag/hdc-1000-sensor.h" #include "sensortag/mpu-9250-sensor.h" #include "sensortag/reed-relay.h" @@ -49,7 +49,7 @@ /*---------------------------------------------------------------------------*/ /** \brief Exports a global symbol to be used by the sensor API */ SENSORS(&button_left_sensor, &button_right_sensor, - &bmp_280_sensor, &tmp_007_sensor, &opt_3001_sensor, &sht_21_sensor, + &bmp_280_sensor, &tmp_007_sensor, &opt_3001_sensor, &hdc_1000_sensor, &mpu_9250_sensor, &reed_relay_sensor); /*---------------------------------------------------------------------------*/ /** @} */ diff --git a/platform/srf06-cc26xx/sensortag/sht-21-sensor.c b/platform/srf06-cc26xx/sensortag/sht-21-sensor.c deleted file mode 100644 index f90e12f55..000000000 --- a/platform/srf06-cc26xx/sensortag/sht-21-sensor.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * 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. - */ -/*---------------------------------------------------------------------------*/ -/** - * \addtogroup sensortag-cc26xx-sht-sensor - * @{ - * - * \file - * Driver for the Sensortag-CC26xx Sensirion SHT21 Humidity sensor - */ -/*---------------------------------------------------------------------------*/ -#include "contiki-conf.h" -#include "sys/ctimer.h" -#include "lib/sensors.h" -#include "sht-21-sensor.h" -#include "sensor-common.h" -#include "board-i2c.h" - -#include "ti-lib.h" - -#include -#include -#include -/*---------------------------------------------------------------------------*/ -#define DEBUG 0 -#if DEBUG -#define PRINTF(...) printf(__VA_ARGS__) -#else -#define PRINTF(...) -#endif -/*---------------------------------------------------------------------------*/ -/* Sensor I2C address */ -#define HAL_SHT21_I2C_ADDRESS 0x40 -/*---------------------------------------------------------------------------*/ -#define S_REG_LEN 2 -#define DATA_LEN 3 -/*---------------------------------------------------------------------------*/ -/* Internal commands */ -#define SHT21_CMD_TEMP_T_NH 0xF3 /* command trig. temp meas. no hold master */ -#define SHT21_CMD_HUMI_T_NH 0xF5 /* command trig. humidity meas. no hold master */ -#define SHT21_CMD_WRITE_U_R 0xE6 /* command write user register */ -#define SHT21_CMD_READ_U_R 0xE7 /* command read user register */ -#define SHT21_CMD_SOFT_RST 0xFE /* command soft reset */ -/*---------------------------------------------------------------------------*/ -#define HUMIDITY 0x00 -#define TEMPERATURE 0x01 -/*---------------------------------------------------------------------------*/ -#define USR_REG_MASK 0x38 /* Mask off reserved bits (3,4,5) */ -#define USR_REG_DEFAULT 0x02 /* Disable OTP reload */ -#define USR_REG_RES_MASK 0x7E /* Only change bits 0 and 7 (meas. res.) */ -#define USR_REG_11BITRES 0x81 /* 11-bit resolution */ -/*---------------------------------------------------------------------------*/ -#define USR_REG_TEST_VAL 0x83 -/*---------------------------------------------------------------------------*/ -#define DATA_SIZE 6 -/*---------------------------------------------------------------------------*/ -static uint8_t usr; /* User register value */ -static uint8_t buf[DATA_SIZE]; /* Data buffer */ -static bool success; -/*---------------------------------------------------------------------------*/ -static int enabled = SHT_21_SENSOR_STATUS_DISABLED; -/*---------------------------------------------------------------------------*/ -/* - * Maximum measurement durations in clock ticks. We use 11bit resolution, thus: - * - Tmp: 11ms - * - RH: 15ms - */ -#define MEASUREMENT_DURATION 3 - -/* - * Wait SENSOR_STARTUP_DELAY clock ticks between activation and triggering a - * reading - */ -#define SENSOR_STARTUP_DELAY 4 - -static struct ctimer startup_timer; -/*---------------------------------------------------------------------------*/ -/** - * \brief Select the SHT sensor on the I2C-bus - */ -static void -select(void) -{ - /* Select the SHT21 address */ - board_i2c_select(BOARD_I2C_INTERFACE_0, HAL_SHT21_I2C_ADDRESS); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Write a command over I2C - * \param cmd The command to send - * \return TRUE if the command was sent successfully - */ -static bool -write_cmd(uint8_t cmd) -{ - /* Send command */ - return board_i2c_write_single(cmd); -} -/*---------------------------------------------------------------------------*/ -/* - * \brief Read data from the SHT over I2C - * \param buf Pointer to buffer where data will be stored - * \param len Number of bytes to read - * \return TRUE if the required number of bytes were received - */ -static bool -read_data(uint8_t *buf, uint8_t len) -{ - /* Read data */ - return board_i2c_read(buf, len); -} -/*---------------------------------------------------------------------------*/ -/** - * @brief Initialise the SHT21 sensor - */ -static void -sensor_init(void) -{ - select(); - - /* Set 11 bit resolution */ - sensor_common_read_reg(SHT21_CMD_READ_U_R, &usr, 1); - usr &= USR_REG_RES_MASK; - usr |= USR_REG_11BITRES; - sensor_common_write_reg(SHT21_CMD_WRITE_U_R, &usr, 1); - success = true; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Start a temperature measurement - */ -static void -start_temp(void) -{ - if(success) { - select(); - success = write_cmd(SHT21_CMD_TEMP_T_NH); - } -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Latch the last temperature measurement - */ -static void -latch_temp(void) -{ - if(success) { - select(); - success = read_data(buf, DATA_LEN); - } -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Start a humidity measurement - */ -static void -start_humidity(void) -{ - if(success) { - select(); - success = write_cmd(SHT21_CMD_HUMI_T_NH); - } -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Latch the last humidity measurement - */ -static void -latch_humidity(void) -{ - if(success) { - select(); - success = read_data(buf + DATA_LEN, DATA_LEN); - } -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Retrieve latched raw readings from buffer and store in variables - * \param raw_temp Pointer to a buffer where the temperature reading will be - * stored - * \param raw_hum Pointer to a buffer where the humidity reading will be - * stored - * \return TRUE on success - */ -static bool -get_readings(uint16_t *raw_temp, uint16_t *raw_hum) -{ - bool valid; - - valid = success; - if(!success) { - sensor_common_set_error_data(buf, DATA_SIZE); - } - - /* Store temperature */ - *raw_temp = buf[0] << 8 | buf[1]; - - /* [2] We ignore the CRC */ - - /* Store humidity */ - *raw_hum = buf[3] << 8 | buf[4]; - - /* [5] We ignore the CRC */ - - success = true; - - return valid; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Convert raw data to temperature (degrees C) and rel. humidity (%RH) - * \param raw_temp Raw temperature data (little endian) - * \param raw_hum Raw humidity data (little endian) - * \param temp Converted temperature value - * \param hum Converted humidity value - */ -static void -convert(uint16_t raw_temp, uint16_t raw_hum, float *temp, float *hum) -{ - /* Convert temperature to degrees C */ - raw_temp &= ~0x0003; /* clear bits [1..0] (status bits) */ - *temp = -46.85 + 175.72 / 65536 * (double)(int16_t)raw_temp; - - /* Convert relative humidity to a %RH value */ - raw_hum &= ~0x0003; /* clear bits [1..0] (status bits) */ - - /* RH= -6 + 125 * SRH / 2^16 */ - *hum = -6.0 + 125.0 / 65536 * (double)raw_hum; -} -/*---------------------------------------------------------------------------*/ -static void -state_machine(void *not_used) -{ - switch(enabled) { - case SHT_21_SENSOR_STATUS_INITIALISED: - start_temp(); - enabled = SHT_21_SENSOR_STATUS_READING_TEMP; - break; - case SHT_21_SENSOR_STATUS_READING_TEMP: - latch_temp(); - start_humidity(); - enabled = SHT_21_SENSOR_STATUS_READING_HUMIDITY; - break; - case SHT_21_SENSOR_STATUS_READING_HUMIDITY: - latch_humidity(); - enabled = SHT_21_SENSOR_STATUS_READINGS_READY; - sensors_changed(&sht_21_sensor); - return; - case SHT_21_SENSOR_STATUS_READINGS_READY: - case SHT_21_SENSOR_STATUS_DISABLED: - default: - ctimer_stop(&startup_timer); - return; - } - - ctimer_set(&startup_timer, MEASUREMENT_DURATION, state_machine, NULL); -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Returns a reading from the sensor - * \param type SHT_21_SENSOR_TYPE_TEMP or SHT_21_SENSOR_TYPE_HUMIDITY - * \return Temperature (centi degrees C) or Humidity (centi %RH) - */ -static int -value(int type) -{ - int rv; - uint16_t raw_temp; - uint16_t raw_hum; - float temp; - float hum; - - if(enabled != SHT_21_SENSOR_STATUS_READINGS_READY) { - PRINTF("Sensor disabled or starting up (%d)\n", enabled); - return CC26XX_SENSOR_READING_ERROR; - } - - if((type != SHT_21_SENSOR_TYPE_TEMP) && type != SHT_21_SENSOR_TYPE_HUMIDITY) { - PRINTF("Invalid type\n"); - return CC26XX_SENSOR_READING_ERROR; - } else { - rv = get_readings(&raw_temp, &raw_hum); - - if(rv == 0) { - return CC26XX_SENSOR_READING_ERROR; - } - - convert(raw_temp, raw_hum, &temp, &hum); - PRINTF("SHT: %04X %04X t=%d h=%d\n", raw_temp, raw_hum, - (int)(temp * 100), (int)(hum * 100)); - - if(type == SHT_21_SENSOR_TYPE_TEMP) { - rv = (int)(temp * 100); - } else if(type == SHT_21_SENSOR_TYPE_HUMIDITY) { - rv = (int)(hum * 100); - } - } - return rv; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Configuration function for the SHT21 sensor. - * - * \param type Activate, enable or disable the sensor. See below - * \param enable - * - * When type == SENSORS_HW_INIT we turn on the hardware - * When type == SENSORS_ACTIVE and enable==1 we enable the sensor - * When type == SENSORS_ACTIVE and enable==0 we disable the sensor - */ -static int -configure(int type, int enable) -{ - switch(type) { - case SENSORS_HW_INIT: - sensor_init(); - enabled = SHT_21_SENSOR_STATUS_INITIALISED; - break; - case SENSORS_ACTIVE: - /* Must be initialised first */ - if(enabled == SHT_21_SENSOR_STATUS_DISABLED) { - return SHT_21_SENSOR_STATUS_DISABLED; - } - if(enable) { - enabled = SHT_21_SENSOR_STATUS_INITIALISED; - ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, state_machine, NULL); - } else { - ctimer_stop(&startup_timer); - enabled = SHT_21_SENSOR_STATUS_INITIALISED; - } - break; - default: - break; - } - return enabled; -} -/*---------------------------------------------------------------------------*/ -/** - * \brief Returns the status of the sensor - * \param type SENSORS_ACTIVE or SENSORS_READY - * \return One of the SENSOR_STATUS_xyz defines - */ -static int -status(int type) -{ - switch(type) { - case SENSORS_ACTIVE: - case SENSORS_READY: - return enabled; - break; - default: - break; - } - return SHT_21_SENSOR_STATUS_DISABLED; -} -/*---------------------------------------------------------------------------*/ -SENSORS_SENSOR(sht_21_sensor, "SHT21", value, configure, status); -/*---------------------------------------------------------------------------*/ -/** @} */ diff --git a/platform/srf06-cc26xx/sensortag/tmp-007-sensor.c b/platform/srf06-cc26xx/sensortag/tmp-007-sensor.c index 8f880cb54..1c462a0e0 100644 --- a/platform/srf06-cc26xx/sensortag/tmp-007-sensor.c +++ b/platform/srf06-cc26xx/sensortag/tmp-007-sensor.c @@ -88,7 +88,7 @@ #define SWAP(v) ((LO_UINT16(v) << 8) | HI_UINT16(v)) /*---------------------------------------------------------------------------*/ -#define SELECT() board_i2c_select(BOARD_I2C_INTERFACE_0, SENSOR_I2C_ADDRESS); +#define SELECT() board_i2c_select(BOARD_I2C_INTERFACE_0, SENSOR_I2C_ADDRESS) /*---------------------------------------------------------------------------*/ static uint8_t buf[DATA_SIZE]; static uint16_t val; @@ -124,7 +124,7 @@ enable_sensor(bool enable) { bool success; - SELECT() + SELECT(); if(enable) { val = TMP007_VAL_CONFIG_ON; @@ -267,6 +267,10 @@ configure(int type, int enable) { switch(type) { case SENSORS_HW_INIT: + ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_TMP_RDY); + ti_lib_ioc_io_port_pull_set(BOARD_IOID_TMP_RDY, IOC_IOPULL_UP); + ti_lib_ioc_io_hyst_set(BOARD_IOID_TMP_RDY, IOC_HYST_ENABLE); + enable_sensor(false); enabled = SENSOR_STATUS_INITIALISED; break; diff --git a/platform/srf06-cc26xx/srf06/Makefile.srf06 b/platform/srf06-cc26xx/srf06/Makefile.srf06 index 7d64aac94..ee64aa519 100644 --- a/platform/srf06-cc26xx/srf06/Makefile.srf06 +++ b/platform/srf06-cc26xx/srf06/Makefile.srf06 @@ -1,5 +1,3 @@ CFLAGS += -DBOARD_SMARTRF06EB=1 BOARD_SOURCEFILES += leds-arch.c srf06-sensors.c button-sensor.c board.c - -CONTIKI_TARGET_DIRS += $(BOARD)/bsp diff --git a/platform/srf06-cc26xx/srf06/board.c b/platform/srf06-cc26xx/srf06/board.c index b62f3fc24..1d98d4e0d 100644 --- a/platform/srf06-cc26xx/srf06/board.c +++ b/platform/srf06-cc26xx/srf06/board.c @@ -45,95 +45,60 @@ #include #include /*---------------------------------------------------------------------------*/ -#define PRCM_DOMAINS (PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_SERIAL | \ - PRCM_DOMAIN_PERIPH | PRCM_DOMAIN_CPU | \ - PRCM_DOMAIN_SYSBUS | PRCM_DOMAIN_VIMS) -/*---------------------------------------------------------------------------*/ -#define LPM_DOMAINS (PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH) -/*---------------------------------------------------------------------------*/ static void -power_domains_on(void) +wakeup_handler(void) { - /* Turn on relevant power domains */ - ti_lib_prcm_power_domain_on(LPM_DOMAINS); - - /* Wait for domains to power on */ - while((ti_lib_prcm_power_domain_status(LPM_DOMAINS) + /* 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)); } /*---------------------------------------------------------------------------*/ -static void -lpm_wakeup_handler(void) -{ - power_domains_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(srf_module, NULL, NULL, lpm_wakeup_handler); +LPM_MODULE(srf_module, NULL, NULL, wakeup_handler, LPM_DOMAIN_NONE); /*---------------------------------------------------------------------------*/ -void -board_init() +static void +configure_unused_pins(void) { - uint8_t int_disabled = ti_lib_int_master_disable(); - - /* Turn on all power domains */ - ti_lib_prcm_power_domain_on(PRCM_DOMAINS); - - /* Wait for power on domains */ - while((ti_lib_prcm_power_domain_status(PRCM_DOMAINS) - != PRCM_DOMAIN_POWER_ON)); - - /* Configure all clock domains to run at full speed */ - ti_lib_prcm_clock_configure_set(PRCM_DOMAIN_SYSBUS | PRCM_DOMAIN_CPU | - PRCM_DOMAIN_CPU | PRCM_DOMAIN_TIMER | - PRCM_DOMAIN_SERIAL | PRCM_DOMAIN_PERIPH, - PRCM_CLOCK_DIV_1); - - /* 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()) ; - - /* Keys (input pullup) */ - ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_KEY_UP); - ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_KEY_DOWN); - ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_KEY_LEFT); - ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_KEY_RIGHT); - ti_lib_ioc_pin_type_gpio_input(BOARD_IOID_KEY_SELECT); - - /* Turn off 3.3V domain (Powers the LCD and SD card reader): Output, low */ + /* Turn off 3.3-V domain (lcd/sdcard power, output low) */ ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_3V3_EN); ti_lib_gpio_pin_write(BOARD_3V3_EN, 0); - /* LCD CSn (output high) */ - ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_LCD_CS); - ti_lib_gpio_pin_write(BOARD_LCD_CS, 1); - - /* SD Card reader CSn (output high) */ - ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_SDCARD_CS); - ti_lib_gpio_pin_write(BOARD_SDCARD_CS, 1); - - /* Accelerometer (PWR output low, CSn output high) */ + /* 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); - ti_lib_ioc_pin_type_gpio_output(BOARD_IOID_ACC_CS); - ti_lib_gpio_pin_write(BOARD_IOID_ACC_CS, 1); /* 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 +board_init() +{ + uint8_t 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()); lpm_register_module(&srf_module); + configure_unused_pins(); + /* Re-enable interrupt if initially enabled. */ if(!int_disabled) { ti_lib_int_master_enable(); diff --git a/platform/srf06-cc26xx/srf06/board.h b/platform/srf06-cc26xx/srf06/board.h index 42c060b9b..b222bb17c 100644 --- a/platform/srf06-cc26xx/srf06/board.h +++ b/platform/srf06-cc26xx/srf06/board.h @@ -107,8 +107,8 @@ */ #define BOARD_IOID_UART_RX IOID_2 #define BOARD_IOID_UART_TX IOID_3 -#define BOARD_IOID_UART_CTS IOID_0 -#define BOARD_IOID_UART_RTS IOID_21 +#define BOARD_IOID_UART_CTS IOID_UNUSED +#define BOARD_IOID_UART_RTS IOID_UNUSED #define BOARD_UART_RX (1 << BOARD_IOID_UART_RX) #define BOARD_UART_TX (1 << BOARD_IOID_UART_TX) #define BOARD_UART_CTS (1 << BOARD_IOID_UART_CTS) diff --git a/platform/srf06-cc26xx/srf06/button-sensor.c b/platform/srf06-cc26xx/srf06/button-sensor.c index 5c6dae6f1..5cd541e6c 100644 --- a/platform/srf06-cc26xx/srf06/button-sensor.c +++ b/platform/srf06-cc26xx/srf06/button-sensor.c @@ -55,10 +55,9 @@ /*---------------------------------------------------------------------------*/ #define BUTTON_GPIO_CFG (IOC_CURRENT_2MA | IOC_STRENGTH_AUTO | \ IOC_IOPULL_UP | IOC_SLEW_DISABLE | \ - IOC_HYST_DISABLE | IOC_BOTH_EDGES | \ + IOC_HYST_ENABLE | IOC_BOTH_EDGES | \ IOC_INT_ENABLE | IOC_IOMODE_NORMAL | \ - IOC_NO_WAKE_UP | IOC_INPUT_ENABLE | \ - IOC_JTAG_DISABLE) + IOC_NO_WAKE_UP | IOC_INPUT_ENABLE) /*---------------------------------------------------------------------------*/ #define DEBOUNCE_DURATION (CLOCK_SECOND >> 5) @@ -137,7 +136,7 @@ button_press_handler(uint8_t ioid) sensors_changed(&button_right_sensor); } } else { - lpm_shutdown(BOARD_IOID_KEY_RIGHT); + lpm_shutdown(BOARD_IOID_KEY_RIGHT, IOC_IOPULL_UP, IOC_WAKE_ON_LOW); } } @@ -329,7 +328,7 @@ value_select(int type) { if(type == BUTTON_SENSOR_VALUE_STATE) { return ti_lib_gpio_pin_read(BOARD_KEY_SELECT) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; } else if(type == BUTTON_SENSOR_VALUE_DURATION) { return (int)sel_timer.duration; } @@ -341,7 +340,7 @@ 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; + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; } else if(type == BUTTON_SENSOR_VALUE_DURATION) { return (int)left_timer.duration; } @@ -353,7 +352,7 @@ 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; + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; } else if(type == BUTTON_SENSOR_VALUE_DURATION) { return (int)right_timer.duration; } @@ -365,7 +364,7 @@ value_up(int type) { if(type == BUTTON_SENSOR_VALUE_STATE) { return ti_lib_gpio_pin_read(BOARD_KEY_UP) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; } else if(type == BUTTON_SENSOR_VALUE_DURATION) { return (int)up_timer.duration; } @@ -377,7 +376,7 @@ value_down(int type) { if(type == BUTTON_SENSOR_VALUE_STATE) { return ti_lib_gpio_pin_read(BOARD_KEY_DOWN) == 0 ? - BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; + BUTTON_SENSOR_VALUE_PRESSED : BUTTON_SENSOR_VALUE_RELEASED; } else if(type == BUTTON_SENSOR_VALUE_DURATION) { return (int)down_timer.duration; } diff --git a/platform/srf06-cc26xx/srf06/button-sensor.h b/platform/srf06-cc26xx/srf06/button-sensor.h index 1f5752059..2c47f9118 100644 --- a/platform/srf06-cc26xx/srf06/button-sensor.h +++ b/platform/srf06-cc26xx/srf06/button-sensor.h @@ -49,7 +49,6 @@ #define BUTTON_SENSOR_VALUE_RELEASED 0 #define BUTTON_SENSOR_VALUE_PRESSED 1 /*---------------------------------------------------------------------------*/ -#define button_sensor button_select_sensor extern const struct sensors_sensor button_select_sensor; extern const struct sensors_sensor button_left_sensor; extern const struct sensors_sensor button_right_sensor; diff --git a/platform/z1/dev/tmp102.c b/platform/z1/dev/tmp102.c index 11844acb0..cc9394b7b 100644 --- a/platform/z1/dev/tmp102.c +++ b/platform/z1/dev/tmp102.c @@ -185,5 +185,6 @@ tmp102_read_temp_x100(void) int8_t tmp102_read_temp_simple(void) { - return (int8_t)tmp102_read_temp_x100() / 100; + /* Casted to int8_t: We don't expect temperatures outside -128 to 127 C */ + return tmp102_read_temp_x100() / 100; } diff --git a/regression-tests/00-doxygen/doxyerrors.cnt b/regression-tests/00-doxygen/doxyerrors.cnt index 485369e4e..360b9e4ba 100644 --- a/regression-tests/00-doxygen/doxyerrors.cnt +++ b/regression-tests/00-doxygen/doxyerrors.cnt @@ -1 +1,2 @@ -205 +209 + diff --git a/regression-tests/01-compile-base/Makefile b/regression-tests/01-compile-base/Makefile index d6fb60a91..e756bf5a6 100644 --- a/regression-tests/01-compile-base/Makefile +++ b/regression-tests/01-compile-base/Makefile @@ -20,7 +20,6 @@ powertrace/sky \ rime/sky \ rime/z1 \ ravenusbstick/avr-ravenusb \ -rest-example/sky \ servreg-hack/sky \ sky/sky \ sky-ip/sky \ @@ -30,7 +29,6 @@ sky-shell-webserver/sky \ tcp-socket/minimal-net \ telnet-server/minimal-net \ webserver/minimal-net \ -webserver-ipv6/exp5438 \ webserver-ipv6/eval-adf7xxxmb4z \ wget/minimal-net \ z1/z1 \ diff --git a/regression-tests/12-rpl/09-rpl-probing.csc b/regression-tests/12-rpl/09-rpl-probing.csc new file mode 100644 index 000000000..bc29029af --- /dev/null +++ b/regression-tests/12-rpl/09-rpl-probing.csc @@ -0,0 +1,258 @@ + + + [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/15-compile-arm-apcs-ports/Makefile b/regression-tests/15-compile-arm-apcs-ports/Makefile index 394c11414..e73a9a39f 100644 --- a/regression-tests/15-compile-arm-apcs-ports/Makefile +++ b/regression-tests/15-compile-arm-apcs-ports/Makefile @@ -4,19 +4,10 @@ TOOLSDIR=../../tools EXAMPLES = \ hello-world/econotag \ hello-world/mbxxx \ -hello-world/cc2538dk \ ipv6/rpl-border-router/econotag \ -ipv6/rpl-border-router/cc2538dk \ er-rest-example/econotag \ -er-rest-example/cc2538dk \ webserver-ipv6/econotag \ -webserver-ipv6/cc2538dk \ -cc2538dk/cc2538dk \ -cc2538dk/udp-ipv6-echo-server/cc2538dk \ -cc2538dk/sniffer/cc2538dk \ -cc2538dk/mqtt-demo/cc2538dk \ ipv6/multicast/econotag \ -ipv6/multicast/cc2538dk \ TOOLS= diff --git a/regression-tests/18-compile-arm-ports/Makefile b/regression-tests/18-compile-arm-ports/Makefile index 4389c6d86..217b5eef9 100644 --- a/regression-tests/18-compile-arm-ports/Makefile +++ b/regression-tests/18-compile-arm-ports/Makefile @@ -8,6 +8,15 @@ webserver-ipv6/ev-aducrf101mkxz \ ipv6/multicast/ev-aducrf101mkxz \ cc2538dk/sniffer/ev-aducrf101mkxz \ cc26xx/cc26xx-web-demo/srf06-cc26xx \ +hello-world/cc2538dk \ +ipv6/rpl-border-router/cc2538dk \ +er-rest-example/cc2538dk \ +webserver-ipv6/cc2538dk \ +cc2538dk/cc2538dk \ +cc2538dk/udp-ipv6-echo-server/cc2538dk \ +cc2538dk/sniffer/cc2538dk \ +cc2538dk/mqtt-demo/cc2538dk \ +ipv6/multicast/cc2538dk \ TOOLS= diff --git a/regression-tests/20-compile-tools/Makefile b/regression-tests/20-compile-tools/Makefile new file mode 100644 index 000000000..7ec956683 --- /dev/null +++ b/regression-tests/20-compile-tools/Makefile @@ -0,0 +1,72 @@ +# Copyright (c) 2014, Friedrich-Alexander University Erlangen-Nuremberg +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. Neither the name of the University nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED 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. + +TOOLS=sky tools stm32w z80=hex2bin sensinode=nano_programmer +FAILTOOLS=stm32w=uip6_bridge sky=uip6-bridge sensinode=nano_usb_programmer + + +TOOLSDIR=../../tools +LOGS=$(patsubst %,%.log, $(TOOLS)) + +all: summary + +FRC: + + +sky.log: RMFILES=serialdump-linux +stm32w.log: RMFILES=serialdump-linux + + +tools.log: + @$(MAKE) -C $(TOOLSDIR) > $@ 2>&1 && $(RM) $@.failed || touch $@.failed + + +%.log: FRC + @( cd $(TOOLSDIR)/$(subst =,/,$*) && $(RM) $(RMFILES) ) + @touch $@ + @$(MAKE) -C $(TOOLSDIR)/$(subst =,/,$*) > $@ 2>&1 && $(RM) $@.failed || touch $@.failed + + +summary: $(LOGS) + @(\ + for T in $(TOOLS) ; do \ + if [ -f $$T.log.failed ] ; then \ + echo tools/$$T: FAIL ಠ_ಠ >> $@;\ + cat $$T.log >> $@;\ + else \ + echo tools/$$T: OK >> $@;\ + fi\ + done \ + ) + @echo "Info: The following tools need fixing and are not tested:" $(subst =,/,$(FAILTOOLS)) >> $@ + @echo $@ + +clean: + @make -C $(DOCDIR) clean + + +.PHONY: %.log diff --git a/regression-tests/20-ip64/01-cooja-ip64-http-socket.csc b/regression-tests/20-ip64/01-cooja-ip64-http-socket.csc new file mode 100644 index 000000000..c30af5032 --- /dev/null +++ b/regression-tests/20-ip64/01-cooja-ip64-http-socket.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 + 1.0 + generated + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 100.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype503 + ip64-router/ip64-router.c TARGET=cooja-ip64 + [CONTIKI_DIR]/examples/ip64-router/ip64-router.c + make ip64-router.cooja-ip64 TARGET=cooja-ip64 + 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 + mtype555 + examples/http-socket/http-example.c + [CONTIKI_DIR]/examples/http-socket/http-example.c + make http-example.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 + 55.719691912311305 + 37.8697579181178 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype503 + + + + org.contikios.cooja.interfaces.Position + 65.60514720922419 + 33.88871867406431 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + mtype555 + + + + org.contikios.cooja.plugins.SimControl + 280 + 1 + 160 + 606 + 15 + + + org.contikios.cooja.plugins.Visualizer + + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.TrafficVisualizerSkin + org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin + org.contikios.cooja.plugins.skins.LEDVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + 8.230641272440463 0.0 0.0 8.230641272440463 -395.6087959411366 -239.69239249818943 + + 219 + 3 + 171 + 29 + 27 + + + org.contikios.cooja.plugins.LogListener + + + + + + 888 + 2 + 603 + 34 + 307 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 960 + 0 + 682 + 528 + 192 + + + org.contikios.cooja.serialsocket.SerialSocketServer + 0 + + 60001 + true + + 362 + 4 + 116 + 234 + 101 + + + diff --git a/regression-tests/20-ip64/Makefile b/regression-tests/20-ip64/Makefile new file mode 100644 index 000000000..272bc7da1 --- /dev/null +++ b/regression-tests/20-ip64/Makefile @@ -0,0 +1 @@ +include ../Makefile.simulation-test diff --git a/tools/Makefile b/tools/Makefile index a1529c352..87f14d317 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,4 +1,4 @@ -all: codeprop tunslip +all: tunslip gitclean: @git clean -d -x -n .. @@ -20,4 +20,4 @@ cleantargets: @rm -f -v ${addprefix ../examples/*/*., ${shell ls ../platform/}} @rm -f -v ${addprefix ../examples/*/*/*., ${shell ls ../platform/}} cleandone: - @echo ${info All done!} \ No newline at end of file + @echo ${info All done!} diff --git a/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMote.java b/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMote.java index 0819b616e..21ed157ce 100644 --- a/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMote.java +++ b/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/MicaZMote.java @@ -44,6 +44,7 @@ import org.contikios.cooja.MoteType; import org.contikios.cooja.Simulation; import org.contikios.cooja.mote.memory.MemoryInterface; import org.contikios.cooja.motes.AbstractEmulatedMote; + import avrora.arch.avr.AVRProperties; import avrora.core.LoadableProgram; import avrora.sim.AtmelInterpreter; @@ -54,6 +55,8 @@ import avrora.sim.mcu.EEPROM; import avrora.sim.platform.MicaZ; import avrora.sim.platform.PlatformFactory; +import org.contikios.cooja.avrmote.interfaces.MicaClock; + /** * @author Joakim Eriksson, Fredrik Osterlind */ @@ -74,6 +77,10 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote { private EEPROM eeprom = null; + private long executed = 0; + private long skipped = 0; + + /* Stack monitoring variables */ private boolean stopNextInstruction = false; @@ -184,6 +191,10 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote { private long cyclesExecuted = 0; private long cyclesUntil = 0; public void execute(long t) { + MicaClock clock = ((MicaClock) (myMoteInterfaceHandler.getClock())); + double deviation = clock.getDeviation(); + long drift = clock.getDrift(); + /* Wait until mote boots */ if (myMoteInterfaceHandler.getClock().getTime() < 0) { scheduleNextWakeup(t - myMoteInterfaceHandler.getClock().getTime()); @@ -196,13 +207,22 @@ public class MicaZMote extends AbstractEmulatedMote implements Mote { } /* TODO Poll mote interfaces? */ - + + /* skip if necessary */ + if (((1-deviation) * executed) > skipped) { + skipped += 1; + scheduleNextWakeup(t + Simulation.MILLISECOND); + } + /* Execute one millisecond */ cyclesUntil += NR_CYCLES_PER_MSEC; while (cyclesExecuted < cyclesUntil) { cyclesExecuted += interpreter.step(); } + /* book keeping */ + executed += 1; + /* TODO Poll mote interfaces? */ /* Schedule wakeup every millisecond */ diff --git a/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/interfaces/MicaClock.java b/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/interfaces/MicaClock.java index 468e07a73..569e08dfd 100644 --- a/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/interfaces/MicaClock.java +++ b/tools/cooja/apps/avrora/src/org/contikios/cooja/avrmote/interfaces/MicaClock.java @@ -54,10 +54,12 @@ public class MicaClock extends Clock { private MicaZMote myMote; private long timeDrift; /* Microseconds */ + private double deviation; public MicaClock(Mote mote) { simulation = mote.getSimulation(); myMote = (MicaZMote) mote; + deviation = 1.0; } public void setTime(long newTime) { @@ -68,6 +70,15 @@ public class MicaClock extends Clock { return simulation.getSimulationTime() + timeDrift; } + public double getDeviation() { + return deviation; + } + + public void setDeviation(double deviation) { + assert (deviation>0.0) && (deviation<=1.0); + this.deviation = deviation; + } + public void setDrift(long drift) { timeDrift = drift; } @@ -75,19 +86,4 @@ public class MicaClock extends Clock { public long getDrift() { return timeDrift; } - - public JPanel getInterfaceVisualizer() { - return null; - } - - public void releaseInterfaceVisualizer(JPanel panel) { - } - - public Collection getConfigXML() { - return null; - } - - public void setConfigXML(Collection configXML, boolean visAvailable) { - } - } diff --git a/tools/cooja/apps/mrm/java/org/contikios/mrm/MRM.java b/tools/cooja/apps/mrm/java/org/contikios/mrm/MRM.java index 70e304d02..a19dcee58 100644 --- a/tools/cooja/apps/mrm/java/org/contikios/mrm/MRM.java +++ b/tools/cooja/apps/mrm/java/org/contikios/mrm/MRM.java @@ -169,6 +169,7 @@ public class MRM extends AbstractRadioMedium { if (sender.getChannel() >= 0 && recv.getChannel() >= 0 && sender.getChannel() != recv.getChannel()) { + newConnection.addInterfered(recv); continue; } final Radio recvFinal = recv; @@ -313,15 +314,15 @@ public class MRM extends AbstractRadioMedium { /* Interfering/colliding radio connections */ for (RadioConnection conn : conns) { for (Radio intfRadio : ((MRMRadioConnection) conn).getInterfered()) { - double signalStrength = ((MRMRadioConnection) conn).getInterferenceSignalStrength(intfRadio); - if (intfRadio.getCurrentSignalStrength() < signalStrength) { - intfRadio.setCurrentSignalStrength(signalStrength); - } if (conn.getSource().getChannel() >= 0 && intfRadio.getChannel() >= 0 && conn.getSource().getChannel() != intfRadio.getChannel()) { continue; } + double signalStrength = ((MRMRadioConnection) conn).getInterferenceSignalStrength(intfRadio); + if (intfRadio.getCurrentSignalStrength() < signalStrength) { + intfRadio.setCurrentSignalStrength(signalStrength); + } if (!intfRadio.isInterfered()) { /*logger.warn("Radio was not interfered: " + intfRadio);*/ diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/MspMote.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/MspMote.java index 403376583..b22fbc145 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/MspMote.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/MspMote.java @@ -78,6 +78,8 @@ import se.sics.mspsim.util.MapEntry; import se.sics.mspsim.util.MapTable; import se.sics.mspsim.profiler.SimpleProfiler; +import org.contikios.cooja.mspmote.interfaces.MspClock; + /** * @author Fredrik Osterlind */ @@ -288,13 +290,22 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc private long lastExecute = -1; /* Last time mote executed */ private long nextExecute; + + private long executed = 0; + private long skipped = 0; + public void execute(long time) { execute(time, EXECUTE_DURATION_US); } + public void execute(long t, int duration) { + MspClock clock = ((MspClock) (myMoteInterfaceHandler.getClock())); + double deviation = clock.getDeviation(); + long drift = clock.getDrift(); + /* Wait until mote boots */ - if (!booted && myMoteInterfaceHandler.getClock().getTime() < 0) { - scheduleNextWakeup(t - myMoteInterfaceHandler.getClock().getTime()); + if (!booted && clock.getTime() < 0) { + scheduleNextWakeup(t - clock.getTime()); return; } booted = true; @@ -313,12 +324,17 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc throw new RuntimeException("Bad event ordering: " + lastExecute + " < " + t); } + if (((1-deviation) * executed) > skipped) { + lastExecute = lastExecute + duration; // (t+duration) - (t-lastExecute); + nextExecute = t+duration; + skipped += duration; + scheduleNextWakeup(nextExecute); + } + /* Execute MSPSim-based mote */ /* TODO Try-catch overhead */ try { - nextExecute = - t + duration + - myCpu.stepMicros(t - lastExecute, duration); + nextExecute = myCpu.stepMicros(Math.max(0, t-lastExecute), duration) + t + duration; lastExecute = t; } catch (EmulationException e) { String trace = e.getMessage() + "\n\n" + getStackTrace(); @@ -330,7 +346,9 @@ public abstract class MspMote extends AbstractEmulatedMote implements Mote, Watc if (nextExecute < t) { throw new RuntimeException(t + ": MSPSim requested early wakeup: " + nextExecute); } + /*logger.debug(t + ": Schedule next wakeup at " + nextExecute);*/ + executed += duration; scheduleNextWakeup(nextExecute); if (stopNextInstruction) { diff --git a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/MspClock.java b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/MspClock.java index c66352e98..10aacffad 100644 --- a/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/MspClock.java +++ b/tools/cooja/apps/mspsim/src/org/contikios/cooja/mspmote/interfaces/MspClock.java @@ -52,9 +52,11 @@ public class MspClock extends Clock { private Simulation simulation; private long timeDrift; /* Microseconds */ + private double deviation; public MspClock(Mote mote) { simulation = mote.getSimulation(); + deviation = 1.0; } public void setTime(long newTime) { @@ -72,20 +74,13 @@ public class MspClock extends Clock { public long getDrift() { return timeDrift; } - - public JPanel getInterfaceVisualizer() { - /* TODO Show current CPU speed */ - return null; + + public void setDeviation(double deviation) { + assert (deviation>0.0) && (deviation<=1.0); + this.deviation = deviation; } - public void releaseInterfaceVisualizer(JPanel panel) { + public double getDeviation() { + return deviation; } - - public Collection getConfigXML() { - return null; - } - - public void setConfigXML(Collection configXML, boolean visAvailable) { - } - } diff --git a/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiClock.java b/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiClock.java index 127a7a3a7..b033ef06d 100644 --- a/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiClock.java +++ b/tools/cooja/java/org/contikios/cooja/contikimote/interfaces/ContikiClock.java @@ -114,6 +114,14 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB public long getTime() { return moteTime; } + + public void setDeviation(double deviation) { + logger.fatal("Can't change deviation");; + } + + public double getDeviation() { + return 1.0; + } public void doActionsBeforeTick() { /* Update time */ @@ -161,5 +169,4 @@ public class ContikiClock extends Clock implements ContikiMoteInterface, PolledB public void setConfigXML(Collection configXML, boolean visAvailable) { } - } diff --git a/tools/cooja/java/org/contikios/cooja/interfaces/Clock.java b/tools/cooja/java/org/contikios/cooja/interfaces/Clock.java index faefaddfc..58ec05fa5 100644 --- a/tools/cooja/java/org/contikios/cooja/interfaces/Clock.java +++ b/tools/cooja/java/org/contikios/cooja/interfaces/Clock.java @@ -30,7 +30,19 @@ package org.contikios.cooja.interfaces; +import java.awt.GridLayout; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.Collection; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + import org.contikios.cooja.*; +import org.jdom.Element; /** * Represents a mote's internal clock. Notice that the overall @@ -39,10 +51,10 @@ import org.contikios.cooja.*; * This observable never notifies. * * @author Fredrik Osterlind + * Andreas Löscher */ @ClassDescription("Clock") public abstract class Clock extends MoteInterface { - /** * Set mote's time to given time. * @@ -76,4 +88,88 @@ public abstract class Clock extends MoteInterface { */ public abstract long getDrift(); + + /** + * The clock deviation is a factor that represents with how much speed the + * mote progresses through the simulation in relation to the simulation speed. + * + * A value of 1.0 results in the mote being simulated with the same speed + * as the simulation. A value of 0.5 results in the mote being simulation + * at half of the simulation speed. + * + * @param deviation Deviation factor + */ + public abstract void setDeviation(double deviation); + + /** + * Get deviation factor + */ + public abstract double getDeviation(); + + @Override + public JPanel getInterfaceVisualizer() { + JPanel panel = new JPanel(); + GridLayout layout = new GridLayout(0,2); + + /* elements */ + final JLabel timeLabel = new JLabel("Time (ms)"); + final JTextField timeField = new JTextField(String.valueOf(getTime() / 1000)); + final JLabel deviationLabel = new JLabel("Deviation Factor"); + final JTextField deviationField = new JTextField(String.valueOf(getDeviation())); + final JButton readButton = new JButton("Read Clock Values"); + final JButton updateButton = new JButton("Write Clock Values"); + /* set layout */ + panel.setLayout(layout); + /* add components */ + panel.add(timeLabel); + panel.add(timeField); + panel.add(deviationLabel); + panel.add(deviationField); + panel.add(readButton); + panel.add(updateButton); + + readButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent ev) { + if (ev.getButton()==1) { + timeField.setText(String.valueOf(getTime() / 1000)); + deviationField.setText(String.valueOf(getDeviation())); + } + } + }); + + updateButton.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent ev) { + if (ev.getButton()==1) { + setTime(Long.parseLong(timeField.getText()) * 1000); + setDeviation(Double.parseDouble(deviationField.getText())); + } + } + }); + + return panel; + } + + @Override + public void releaseInterfaceVisualizer(JPanel panel) { + } + + @Override + public Collection getConfigXML() { + ArrayList config = new ArrayList(); + Element element = new Element("deviation"); + element.setText(String.valueOf(getDeviation())); + config.add(element); + return config; + } + + @Override + public void setConfigXML(Collection configXML, boolean visAvailable) { + for (Element element : configXML) { + if (element.getName().equals("deviation")) { + setDeviation(Double.parseDouble(element.getText())); + } + } + } } diff --git a/tools/cooja/java/org/contikios/cooja/radiomediums/AbstractRadioMedium.java b/tools/cooja/java/org/contikios/cooja/radiomediums/AbstractRadioMedium.java index 0aed97d52..fce97e927 100644 --- a/tools/cooja/java/org/contikios/cooja/radiomediums/AbstractRadioMedium.java +++ b/tools/cooja/java/org/contikios/cooja/radiomediums/AbstractRadioMedium.java @@ -236,8 +236,9 @@ public abstract class AbstractRadioMedium extends RadioMedium { case RECEPTION_STARTED: case RECEPTION_INTERFERED: case RECEPTION_FINISHED: + break; + case UNKNOWN: - return; case HW_ON: { /* Update signal strengths */ updateSignalStrengths(); @@ -292,7 +293,7 @@ public abstract class AbstractRadioMedium extends RadioMedium { break; case TRANSMISSION_FINISHED: { /* Remove radio connection */ - + /* Connection */ RadioConnection connection = getActiveConnectionFrom(radio); if (connection == null) { @@ -322,7 +323,10 @@ public abstract class AbstractRadioMedium extends RadioMedium { COUNTER_RX += connection.getDestinations().length; COUNTER_INTERFERED += connection.getInterfered().length; for (Radio intRadio : connection.getInterferedNonDestinations()) { - intRadio.signalReceptionEnd(); + + if (intRadio.isInterfered()) { + intRadio.signalReceptionEnd(); + } } /* Update signal strengths */ diff --git a/tools/cooja/java/org/contikios/cooja/radiomediums/DGRMDestinationRadio.java b/tools/cooja/java/org/contikios/cooja/radiomediums/DGRMDestinationRadio.java index fb182f2d4..1147890c8 100644 --- a/tools/cooja/java/org/contikios/cooja/radiomediums/DGRMDestinationRadio.java +++ b/tools/cooja/java/org/contikios/cooja/radiomediums/DGRMDestinationRadio.java @@ -42,6 +42,7 @@ public class DGRMDestinationRadio extends DestinationRadio { public double signal = AbstractRadioMedium.SS_STRONG; /* RSSI */ public long delay = 0; /* EXPERIMENTAL: Propagation delay (us). */ public int lqi = 105; + public int channel = -1; /* not set by default */ public DGRMDestinationRadio() { super(); @@ -50,12 +51,17 @@ public class DGRMDestinationRadio extends DestinationRadio { super(dest); } + public int getChannel() { + return channel; + } + protected Object clone() { DGRMDestinationRadio clone = new DGRMDestinationRadio(this.radio); clone.ratio = this.ratio; clone.delay = this.delay; clone.signal = this.signal; clone.lqi = this.lqi; + clone.channel = this.channel; return clone; } @@ -75,10 +81,13 @@ public class DGRMDestinationRadio extends DestinationRadio { element.setText("" + lqi); config.add(element); - element = new Element("delay"); element.setText("" + delay); config.add(element); + + element = new Element("channel"); + element.setText("" + channel); + config.add(element); return config; } @@ -96,6 +105,8 @@ public class DGRMDestinationRadio extends DestinationRadio { lqi = Integer.parseInt(element.getText()); } else if (element.getName().equals("delay")) { delay = Long.parseLong(element.getText()); + } else if (element.getName().equals("channel")) { + channel = Integer.parseInt(element.getText()); } } return true; diff --git a/tools/cooja/java/org/contikios/cooja/radiomediums/DirectedGraphMedium.java b/tools/cooja/java/org/contikios/cooja/radiomediums/DirectedGraphMedium.java index 23db83c3c..57876357c 100644 --- a/tools/cooja/java/org/contikios/cooja/radiomediums/DirectedGraphMedium.java +++ b/tools/cooja/java/org/contikios/cooja/radiomediums/DirectedGraphMedium.java @@ -166,6 +166,19 @@ public class DirectedGraphMedium extends AbstractRadioMedium { DGRMDestinationRadio dstRadios[] = getPotentialDestinations(conn.getSource()); if (dstRadios == null) continue; for (DGRMDestinationRadio dstRadio : dstRadios) { + + int activeSourceChannel = conn.getSource().getChannel(); + int edgeChannel = dstRadio.channel; + int activeDstChannel = dstRadio.radio.getChannel(); + if (activeSourceChannel != -1) { + if (edgeChannel != -1 && activeSourceChannel != edgeChannel) { + continue; + } + if (activeDstChannel != -1 && activeSourceChannel != activeDstChannel) { + continue; + } + } + if (dstRadio.radio.getCurrentSignalStrength() < dstRadio.signal) { dstRadio.radio.setCurrentSignalStrength(dstRadio.signal); } @@ -247,13 +260,27 @@ public class DirectedGraphMedium extends AbstractRadioMedium { /*logger.info(source + ": " + destinations.length + " potential destinations");*/ for (DGRMDestinationRadio dest: destinations) { - + if (dest.radio == source) { /* Fail: cannot receive our own transmission */ /*logger.info(source + ": Fail, receiver is sender");*/ continue; } + int srcc = source.getChannel(); + int dstc = dest.radio.getChannel(); + int edgeChannel = dest.getChannel(); + + if (edgeChannel >= 0 && dstc >= 0 && edgeChannel != dstc) { + /* Fail: the edge is configured for a different radio channel */ + continue; + } + + if (srcc >= 0 && dstc >= 0 && srcc != dstc) { + /* Fail: radios are on different (but configured) channels */ + newConn.addInterfered(dest.radio); + continue; + } if (!dest.radio.isRadioOn()) { /* Fail: radio is off */ @@ -268,14 +295,7 @@ public class DirectedGraphMedium extends AbstractRadioMedium { newConn.addInterfered(dest.radio); continue; } - - int srcc = source.getChannel(); - int dstc = dest.radio.getChannel(); - if ( srcc >= 0 && dstc >= 0 && srcc != dstc) { - /* Fail: radios are on different (but configured) channels */ - continue; - } - + if (dest.radio.isReceiving()) { /* Fail: radio is already actively receiving */ /*logger.info(source + ": Fail, receiving");*/ diff --git a/tools/cooja/java/org/contikios/cooja/radiomediums/UDGM.java b/tools/cooja/java/org/contikios/cooja/radiomediums/UDGM.java index e0ff8af38..9d7b752fc 100644 --- a/tools/cooja/java/org/contikios/cooja/radiomediums/UDGM.java +++ b/tools/cooja/java/org/contikios/cooja/radiomediums/UDGM.java @@ -192,6 +192,13 @@ public class UDGM extends AbstractRadioMedium { if (sender.getChannel() >= 0 && recv.getChannel() >= 0 && sender.getChannel() != recv.getChannel()) { + + /* Add the connection in a dormant state; + it will be activated later when the radio will be + turned on and switched to the right channel. This behavior + is consistent with the case when receiver is turned off. */ + newConnection.addInterfered(recv); + continue; } Position recvPos = recv.getPosition(); diff --git a/tools/sky/Makefile b/tools/sky/Makefile index 0b1fa08db..be3caa44b 100644 --- a/tools/sky/Makefile +++ b/tools/sky/Makefile @@ -22,4 +22,4 @@ endif all: $(SERIALDUMP) $(SERIALDUMP): serialdump.c - $(CC) -o $@ $< + $(CC) -O2 -o $@ $< diff --git a/tools/sky/serialdump-linux b/tools/sky/serialdump-linux index 8c7af779d..8bb8192c2 100755 Binary files a/tools/sky/serialdump-linux and b/tools/sky/serialdump-linux differ diff --git a/tools/sky/serialdump.c b/tools/sky/serialdump.c index ce6c2ae32..e3e47092b 100644 --- a/tools/sky/serialdump.c +++ b/tools/sky/serialdump.c @@ -1,3 +1,4 @@ +#define _GNU_SOURCE #include #include #include @@ -6,35 +7,36 @@ #include #include #include +#include -#define BAUDRATE B57600 -#define BAUDRATE_S "57600" +#define BAUDRATE B115200 +#define BAUDRATE_S "115200" #ifdef linux #define MODEMDEVICE "/dev/ttyS0" #else #define MODEMDEVICE "/dev/com1" #endif /* linux */ -#define SLIP_END 0300 -#define SLIP_ESC 0333 -#define SLIP_ESC_END 0334 -#define SLIP_ESC_ESC 0335 +#define SLIP_END 0300 +#define SLIP_ESC 0333 +#define SLIP_ESC_END 0334 +#define SLIP_ESC_ESC 0335 -#define CSNA_INIT 0x01 +#define CSNA_INIT 0x01 -#define BUFSIZE 40 -#define HCOLS 20 -#define ICOLS 18 +#define BUFSIZE 40 +#define HCOLS 20 +#define ICOLS 18 -#define MODE_START_DATE 0 -#define MODE_DATE 1 -#define MODE_START_TEXT 2 -#define MODE_TEXT 3 -#define MODE_INT 4 -#define MODE_HEX 5 -#define MODE_SLIP_AUTO 6 -#define MODE_SLIP 7 -#define MODE_SLIP_HIDE 8 +#define MODE_START_DATE 0 +#define MODE_DATE 1 +#define MODE_START_TEXT 2 +#define MODE_TEXT 3 +#define MODE_INT 4 +#define MODE_HEX 5 +#define MODE_SLIP_AUTO 6 +#define MODE_SLIP 7 +#define MODE_SLIP_HIDE 8 static unsigned char rxbuf[2048]; @@ -80,7 +82,8 @@ print_hex_line(unsigned char *prefix, unsigned char *outbuf, int index) } } -int main(int argc, char **argv) +int +main(int argc, char **argv) { struct termios options; fd_set mask, smask; @@ -95,100 +98,103 @@ int main(int argc, char **argv) unsigned char lastc = '\0'; int index = 1; - while (index < argc) { - if (argv[index][0] == '-') { + while(index < argc) { + if(argv[index][0] == '-') { switch(argv[index][1]) { - case 'b': - /* set speed */ - if (strcmp(&argv[index][2], "38400") == 0) { - speed = B38400; - speedname = "38400"; - } else if (strcmp(&argv[index][2], "19200") == 0) { - speed = B19200; - speedname = "19200"; - } else if (strcmp(&argv[index][2], "57600") == 0) { - speed = B57600; - speedname = "57600"; - } else if (strcmp(&argv[index][2], "115200") == 0) { - speed = B115200; - speedname = "115200"; - } else { - fprintf(stderr, "unsupported speed: %s\n", &argv[index][2]); - return usage(1); - } - break; - case 'x': - mode = MODE_HEX; - break; - case 'i': - mode = MODE_INT; - break; - case 's': - switch(argv[index][2]) { - case 'n': - mode = MODE_SLIP_HIDE; - break; - case 'o': - mode = MODE_SLIP; - break; - default: - mode = MODE_SLIP_AUTO; - break; - } - break; - case 'T': - if(strlen(&argv[index][2]) == 0) { - timeformat = "%Y-%m-%d %H:%M:%S"; - } else { - timeformat = &argv[index][2]; - } - mode = MODE_START_DATE; - break; - case 'h': - return usage(0); - default: - fprintf(stderr, "unknown option '%c'\n", argv[index][1]); - return usage(1); + case 'b': + /* set speed */ + if(strcmp(&argv[index][2], "38400") == 0) { + speed = B38400; + speedname = "38400"; + } else if(strcmp(&argv[index][2], "19200") == 0) { + speed = B19200; + speedname = "19200"; + } else if(strcmp(&argv[index][2], "57600") == 0) { + speed = B57600; + speedname = "57600"; + } else if(strcmp(&argv[index][2], "115200") == 0) { + speed = B115200; + speedname = "115200"; + } else { + fprintf(stderr, "unsupported speed: %s\n", &argv[index][2]); + return usage(1); + } + break; + case 'x': + mode = MODE_HEX; + break; + case 'i': + mode = MODE_INT; + break; + case 's': + switch(argv[index][2]) { + case 'n': + mode = MODE_SLIP_HIDE; + break; + case 'o': + mode = MODE_SLIP; + break; + default: + mode = MODE_SLIP_AUTO; + break; + } + break; + case 'T': + if(strlen(&argv[index][2]) == 0) { + timeformat = "%Y-%m-%d %H:%M:%S"; + } else { + timeformat = &argv[index][2]; + } + mode = MODE_START_DATE; + break; + case 'h': + return usage(0); + default: + fprintf(stderr, "unknown option '%c'\n", argv[index][1]); + return usage(1); } index++; } else { device = argv[index++]; - if (index < argc) { - fprintf(stderr, "too many arguments\n"); - return usage(1); + if(index < argc) { + fprintf(stderr, "too many arguments\n"); + return usage(1); } } } fprintf(stderr, "connecting to %s (%s)", device, speedname); -#ifndef __APPLE__ - fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_DIRECT | O_SYNC ); +#ifdef O_SYNC + fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_DIRECT | O_SYNC); + if(fd < 0 && errno == EINVAL){ // O_SYNC not supported (e.g. raspberian) + fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_DIRECT); + } #else fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_SYNC ); #endif - if (fd <0) { + if(fd < 0) { fprintf(stderr, "\n"); - perror(device); + perror("open"); exit(-1); } fprintf(stderr, " [OK]\n"); - if (fcntl(fd, F_SETFL, 0) < 0) { + if(fcntl(fd, F_SETFL, 0) < 0) { perror("could not set fcntl"); exit(-1); } - if (tcgetattr(fd, &options) < 0) { + if(tcgetattr(fd, &options) < 0) { perror("could not get options"); exit(-1); } -/* fprintf(stderr, "serial options set\n"); */ + /* fprintf(stderr, "serial options set\n"); */ cfsetispeed(&options, speed); cfsetospeed(&options, speed); /* Enable the receiver and set local mode */ options.c_cflag |= (CLOCAL | CREAD); /* Mask the character size bits and turn off (odd) parity */ - options.c_cflag &= ~(CSIZE|PARENB|PARODD); + options.c_cflag &= ~(CSIZE | PARENB | PARODD); /* Select 8 data bits */ options.c_cflag |= CS8; @@ -197,30 +203,29 @@ int main(int argc, char **argv) /* Raw output */ options.c_oflag &= ~OPOST; - if (tcsetattr(fd, TCSANOW, &options) < 0) { + if(tcsetattr(fd, TCSANOW, &options) < 0) { perror("could not set options"); exit(-1); } /* Make read() return immediately */ -/* if (fcntl(fd, F_SETFL, FNDELAY) < 0) { */ -/* perror("\ncould not set fcntl"); */ -/* exit(-1); */ -/* } */ + /* if (fcntl(fd, F_SETFL, FNDELAY) < 0) { */ + /* perror("\ncould not set fcntl"); */ + /* exit(-1); */ + /* } */ FD_ZERO(&mask); FD_SET(fd, &mask); FD_SET(fileno(stdin), &mask); index = 0; - for (;;) { + for(;;) { smask = mask; - nfound = select(FD_SETSIZE, &smask, (fd_set *) 0, (fd_set *) 0, - (struct timeval *) 0); + nfound = select(FD_SETSIZE, &smask, (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0); if(nfound < 0) { - if (errno == EINTR) { - fprintf(stderr, "interrupted system call\n"); - continue; + if(errno == EINTR) { + fprintf(stderr, "interrupted system call\n"); + continue; } /* something is very wrong! */ perror("select"); @@ -230,143 +235,142 @@ int main(int argc, char **argv) if(FD_ISSET(fileno(stdin), &smask)) { /* data from standard in */ int n = read(fileno(stdin), buf, sizeof(buf)); - if (n < 0) { - perror("could not read"); - exit(-1); - } else if (n > 0) { - /* because commands might need parameters, lines needs to be - separated which means the terminating LF must be sent */ -/* while(n > 0 && buf[n - 1] < 32) { */ -/* n--; */ -/* } */ - if(n > 0) { - int i; - /* fprintf(stderr, "SEND %d bytes\n", n);*/ - /* write slowly */ - for (i = 0; i < n; i++) { - if (write(fd, &buf[i], 1) <= 0) { - perror("write"); - exit(1); - } else { - fflush(NULL); - usleep(6000); - } - } - } + if(n < 0) { + perror("could not read"); + exit(-1); + } else if(n > 0) { + /* because commands might need parameters, lines needs to be + separated which means the terminating LF must be sent */ + /* while(n > 0 && buf[n - 1] < 32) { */ + /* n--; */ + /* } */ + if(n > 0) { + int i; + /* fprintf(stderr, "SEND %d bytes\n", n);*/ + /* write slowly */ + for(i = 0; i < n; i++) { + if(write(fd, &buf[i], 1) <= 0) { + perror("write"); + exit(1); + } else { + fflush(NULL); + usleep(6000); + } + } + } } else { - /* End of input, exit. */ - exit(0); + /* End of input, exit. */ + exit(0); } } if(FD_ISSET(fd, &smask)) { int i, j, n = read(fd, buf, sizeof(buf)); - if (n < 0) { - perror("could not read"); - exit(-1); + if(n < 0) { + perror("could not read"); + exit(-1); } for(i = 0; i < n; i++) { - switch(mode) { - case MODE_START_TEXT: - case MODE_TEXT: - printf("%c", buf[i]); - break; - case MODE_START_DATE: { - time_t t; - t = time(&t); - strftime(outbuf, HCOLS, timeformat, localtime(&t)); - printf("%s|", outbuf); - mode = MODE_DATE; - } - /* continue into the MODE_DATE */ - case MODE_DATE: - printf("%c", buf[i]); - if(buf[i] == '\n') { - mode = MODE_START_DATE; - } - break; - case MODE_INT: - printf("%03d ", buf[i]); - if(++index >= ICOLS) { - index = 0; - printf("\n"); - } - break; - case MODE_HEX: - rxbuf[index++] = buf[i]; - if(index >= HCOLS) { - print_hex_line("", rxbuf, index); - index = 0; - printf("\n"); - } - break; + switch(mode) { + case MODE_START_TEXT: + case MODE_TEXT: + printf("%c", buf[i]); + break; + case MODE_START_DATE: { + time_t t; + t = time(&t); + strftime(outbuf, HCOLS, timeformat, localtime(&t)); + printf("%s|", outbuf); + mode = MODE_DATE; + } + /* continue into the MODE_DATE */ + case MODE_DATE: + printf("%c", buf[i]); + if(buf[i] == '\n') { + mode = MODE_START_DATE; + } + break; + case MODE_INT: + printf("%03d ", buf[i]); + if(++index >= ICOLS) { + index = 0; + printf("\n"); + } + break; + case MODE_HEX: + rxbuf[index++] = buf[i]; + if(index >= HCOLS) { + print_hex_line("", rxbuf, index); + index = 0; + printf("\n"); + } + break; - case MODE_SLIP_AUTO: - case MODE_SLIP_HIDE: - if(!flags && (buf[i] != SLIP_END)) { - /* Not a SLIP packet? */ - printf("%c", buf[i]); - break; - } - /* continue to slip only mode */ - case MODE_SLIP: - switch(buf[i]) { - case SLIP_ESC: - lastc = SLIP_ESC; - break; + case MODE_SLIP_AUTO: + case MODE_SLIP_HIDE: + if(!flags && (buf[i] != SLIP_END)) { + /* Not a SLIP packet? */ + printf("%c", buf[i]); + break; + } + /* continue to slip only mode */ + case MODE_SLIP: + switch(buf[i]) { + case SLIP_ESC: + lastc = SLIP_ESC; + break; - case SLIP_END: - if(index > 0) { - if(flags != 2 && mode != MODE_SLIP_HIDE) { - /* not overflowed: show packet */ - print_hex_line("SLIP: ", rxbuf, - index > HCOLS ? HCOLS : index); - printf("\n"); - } - lastc = '\0'; - index = 0; - flags = 0; - } else { - flags = !flags; - } - break; + case SLIP_END: + if(index > 0) { + if(flags != 2 && mode != MODE_SLIP_HIDE) { + /* not overflowed: show packet */ + print_hex_line("SLIP: ", rxbuf, index > HCOLS ? HCOLS : index); + printf("\n"); + } + lastc = '\0'; + index = 0; + flags = 0; + } else { + flags = !flags; + } + break; - default: - if(lastc == SLIP_ESC) { - lastc = '\0'; + default: + if(lastc == SLIP_ESC) { + lastc = '\0'; - /* Previous read byte was an escape byte, so this byte will be - interpreted differently from others. */ - switch(buf[i]) { - case SLIP_ESC_END: - buf[i] = SLIP_END; - break; - case SLIP_ESC_ESC: - buf[i] = SLIP_ESC; - break; - } - } + /* Previous read byte was an escape byte, so this byte will be + interpreted differently from others. */ + switch(buf[i]) { + case SLIP_ESC_END: + buf[i] = SLIP_END; + break; + case SLIP_ESC_ESC: + buf[i] = SLIP_ESC; + break; + } + } - rxbuf[index++] = buf[i]; - if(index >= sizeof(rxbuf)) { - fprintf(stderr, "**** slip overflow\n"); - index = 0; - flags = 2; - } - break; - } - break; - } + rxbuf[index++] = buf[i]; + if(index >= sizeof(rxbuf)) { + fprintf(stderr, "**** slip overflow\n"); + index = 0; + flags = 2; + } + break; + } + break; + } } /* after processing for some output modes */ if(index > 0) { - switch(mode) { - case MODE_HEX: - print_hex_line("", rxbuf, index); - break; - } + switch(mode) { + case MODE_HEX: + print_hex_line("", rxbuf, index); + break; + } } fflush(stdout); } diff --git a/tools/stm32w/Makefile b/tools/stm32w/Makefile new file mode 100644 index 000000000..be3caa44b --- /dev/null +++ b/tools/stm32w/Makefile @@ -0,0 +1,25 @@ +ifndef HOST_OS + ifeq ($(OS),Windows_NT) + HOST_OS := Windows + else + HOST_OS := $(shell uname) + endif +endif + +ifeq ($(HOST_OS),Windows) + SERIALDUMP = serialdump-windows +endif + +ifeq ($(HOST_OS),Darwin) + SERIALDUMP = serialdump-macos +endif + +ifndef SERIALDUMP + # Assume Linux + SERIALDUMP = serialdump-linux +endif + +all: $(SERIALDUMP) + +$(SERIALDUMP): serialdump.c + $(CC) -O2 -o $@ $< diff --git a/tools/wpcapslip/Connect.java b/tools/wpcapslip/Connect.java new file mode 100644 index 000000000..7ec6a0699 --- /dev/null +++ b/tools/wpcapslip/Connect.java @@ -0,0 +1,193 @@ +/* + * 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. + * + */ + +import java.io.BufferedOutputStream; +import java.io.BufferedReader; +import java.io.DataInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; + +public class Connect { + private static Process cmd1Process; + private static Process cmd2Process; + private static BufferedOutputStream cmd1Out = null; + private static BufferedOutputStream cmd2Out = null; + + private static final int BUFSIZE = 512; + + public static void main(String[] args) throws Exception { + if (args.length != 2) { + System.err.println("Usage: " + Connect.class.getName() + " [cmd1] [cmd2]"); + System.exit(1); + } + + /* Command 1 */ + String cmd1 = args[0]; + System.out.println("> " + cmd1); + cmd1Process = Runtime.getRuntime().exec(cmd1, null, new File(".")); + final DataInputStream cmd1Input = new DataInputStream( + cmd1Process.getInputStream()); + final BufferedReader cmd1Err = new BufferedReader( + new InputStreamReader(cmd1Process.getErrorStream())); + cmd1Out = new BufferedOutputStream(cmd1Process.getOutputStream()); + Thread readInput = new Thread(new Runnable() { + + public void run() { + int numRead = 0; + byte[] buf = new byte[BUFSIZE]; + try { + while (true) { + numRead = cmd1Input.read(buf, 0, BUFSIZE); + if (numRead > 0 && cmd2Out != null) { + /* System.err.println("1>2 " + numRead); */ + cmd2Out.write(buf, 0, numRead); + cmd2Out.flush(); + } + Thread.sleep(1); + } + } catch (Exception e) { + e.printStackTrace(); + } + String exitVal = "?"; + try { + if (cmd1Process != null) { + exitVal = "" + cmd1Process.exitValue(); + } + } catch (IllegalStateException e) { + e.printStackTrace(); + exitVal = "!"; + } + System.out.println("cmd1 terminated: " + exitVal); + exit(); + } + }, "read stdout cmd1"); + Thread readError = new Thread(new Runnable() { + public void run() { + String line; + try { + while ((line = cmd1Err.readLine()) != null) { + System.err.println("cmd1 err: " + line); + } + cmd1Err.close(); + } catch (IOException e) { + } + System.err.println("cmd1 terminated."); + exit(); + } + }, "read error cmd1"); + readInput.start(); + readError.start(); + + /* Command 2 */ + String cmd2 = args[1]; + System.err.println("> " + cmd2); + cmd2Process = Runtime.getRuntime().exec(cmd2, null, new File(".")); + final DataInputStream cmd2Input = new DataInputStream( + cmd2Process.getInputStream()); + final BufferedReader cmd2Err = new BufferedReader( + new InputStreamReader(cmd2Process.getErrorStream())); + cmd2Out = new BufferedOutputStream(cmd2Process.getOutputStream()); + readInput = new Thread(new Runnable() { + public void run() { + int numRead = 0; + byte[] buf = new byte[BUFSIZE]; + try { + while (true) { + numRead = cmd2Input.read(buf, 0, BUFSIZE); + if (numRead > 0 && cmd1Out != null) { + /* System.err.println("2>1 " + numRead); */ + cmd1Out.write(buf, 0, numRead); + cmd1Out.flush(); + } + Thread.sleep(1); + } + } catch (Exception e) { + e.printStackTrace(); + } + String exitVal = "?"; + try { + if (cmd2Process != null) { + exitVal = "" + cmd2Process.exitValue(); + } + } catch (IllegalStateException e) { + e.printStackTrace(); + exitVal = "!"; + } + System.out.println("cmd2 terminated: " + exitVal); + exit(); + } + }, "read stdout cmd2"); + readError = new Thread(new Runnable() { + public void run() { + String line; + try { + while ((line = cmd2Err.readLine()) != null) { + System.err.println("cmd2 err: " + line); + } + cmd2Err.close(); + } catch (IOException e) { + } + System.err.println("cmd2 terminated."); + exit(); + } + }, "read error cmd2"); + readInput.start(); + readError.start(); + + while (true) { + Thread.sleep(100); + } + } + + private static void exit() { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + } + try { + if (cmd1Process != null) { + cmd1Process.destroy(); + } + } catch (Exception e) { + } + try { + if (cmd2Process != null) { + cmd2Process.destroy(); + } + } catch (Exception e) { + } + System.err.flush(); + System.exit(1); + } + +} diff --git a/tools/wpcapslip/ConnectSocket.java b/tools/wpcapslip/ConnectSocket.java new file mode 100644 index 000000000..417ebac1d --- /dev/null +++ b/tools/wpcapslip/ConnectSocket.java @@ -0,0 +1,115 @@ +/* + * Copyright (c) 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. + * + */ + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.DataInputStream; +import java.net.Socket; + +public class ConnectSocket { + private static BufferedOutputStream stdoutOutput = null; + private static BufferedOutputStream networkServerOutput = null; + + private static final int BUFSIZE = 512; + + public static void main(String[] args) throws Exception { + if (args.length != 2) { + System.err.println("Usage: " + ConnectSocket.class.getName() + " [server ip] [server port]"); + System.exit(1); + } + + /* Stdin */ + final BufferedInputStream stdinInput = new BufferedInputStream(new DataInputStream(System.in)); + stdoutOutput = new BufferedOutputStream(System.out); + Thread readInput = new Thread(new Runnable() { + public void run() { + int numRead = 0; + byte[] buf = new byte[BUFSIZE]; + try { + while (true) { + numRead = stdinInput.read(buf, 0, BUFSIZE); + if (numRead > 0 && networkServerOutput != null) { + /* System.err.println("1>2 " + numRead); */ + + networkServerOutput.write(buf, 0, numRead); + networkServerOutput.flush(); + } + Thread.sleep(1); + } + } catch (Exception e) { + e.printStackTrace(); + } + exit(); + } + }, "read stdin"); + readInput.start(); + + /* Network server */ + Socket networkServer = new Socket(args[0], Integer.parseInt(args[1])); + final BufferedInputStream networkServerInput = new BufferedInputStream(new DataInputStream(networkServer.getInputStream())); + networkServerOutput = new BufferedOutputStream(networkServer.getOutputStream()); + readInput = new Thread(new Runnable() { + public void run() { + int numRead = 0; + byte[] buf = new byte[BUFSIZE]; + try { + while (true) { + numRead = networkServerInput.read(buf, 0, BUFSIZE); + if (numRead > 0 && stdoutOutput != null) { + /* System.err.println("2>1 " + numRead); */ + stdoutOutput.write(buf, 0, numRead); + stdoutOutput.flush(); + } + Thread.sleep(1); + } + } catch (Exception e) { + e.printStackTrace(); + } + exit(); + } + }, "read network server"); + readInput.start(); + + while (true) { + Thread.sleep(100); + } + } + + private static void exit() { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + } + System.err.flush(); + System.exit(1); + } +} diff --git a/tools/wpcapslip/Makefile b/tools/wpcapslip/Makefile index 1ab2caff2..fb11826eb 100644 --- a/tools/wpcapslip/Makefile +++ b/tools/wpcapslip/Makefile @@ -1,12 +1,21 @@ CONTIKI=../.. -CFLAGS=-Wall -Werror -I$(CONTIKI)/core -I. +CC=gcc +CFLAGS=-Wall -I$(CONTIKI)/core -I. -all: wpcapslip +all: wpcapslip wpcapstdio Connect.class ConnectSocket.class +%.class: %.java + javac $*.java + vpath %.c $(CONTIKI)/core/net wpcapslip: wpcapslip.o wpcap.o tcpdump.o +wpcapstdio: wpcapstdio.o wpcap.o tcpdump.o + %: %.o $(CC) $(LDFLAGS) $^ /lib/w32api/libws2_32.a /lib/w32api/libiphlpapi.a -o $@ + +clean: + rm -f *.class *.exe *.o \ No newline at end of file diff --git a/apps/shell/shell-netfile.h b/tools/wpcapslip/net/tcpdump.h similarity index 83% rename from apps/shell/shell-netfile.h rename to tools/wpcapslip/net/tcpdump.h index 2cbe362f0..bfa9fdd3e 100644 --- a/apps/shell/shell-netfile.h +++ b/tools/wpcapslip/net/tcpdump.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Swedish Institute of Computer Science. + * Copyright (c) 2005, Swedish Institute of Computer Science * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -29,19 +29,12 @@ * This file is part of the Contiki operating system. * */ +#ifndef __TCPDUMP_H__ +#define __TCPDUMP_H__ -/** - * \file - * A brief description of what this file is. - * \author - * Adam Dunkels - */ +#include "net/ip/uip.h" -#ifndef SHELL_NETFILE_H_ -#define SHELL_NETFILE_H_ +int tcpdump_format(uint8_t *packet, uint16_t packetlen, + char *printbuf, uint16_t printbuflen); -#include "shell.h" - -void shell_netfile_init(void); - -#endif /* SHELL_NETFILE_H_ */ +#endif /* __TCPDUMP_H__ */ diff --git a/tools/wpcapslip/tcpdump.c b/tools/wpcapslip/tcpdump.c new file mode 100644 index 000000000..6883cfec3 --- /dev/null +++ b/tools/wpcapslip/tcpdump.c @@ -0,0 +1,289 @@ +/* + * 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. + * + */ + +#include "contiki-net.h" + +#include +#include + + struct ip_hdr { + /* IP header. */ + uint8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + uint16_t ipchksum; + uint8_t srcipaddr[4], + destipaddr[4]; + }; + +#define TCP_FIN 0x01 +#define TCP_SYN 0x02 +#define TCP_RST 0x04 +#define TCP_PSH 0x08 +#define TCP_ACK 0x10 +#define TCP_URG 0x20 +#define TCP_CTL 0x3f + +struct tcpip_hdr { + /* IP header. */ + uint8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + uint16_t ipchksum; + uint8_t srcipaddr[4], + destipaddr[4]; + /* TCP header. */ + uint16_t srcport, + destport; + uint8_t seqno[4], + ackno[4], + tcpoffset, + flags, + wnd[2]; + uint16_t tcpchksum; + uint8_t urgp[2]; + uint8_t optdata[4]; +}; + +#define ICMP_ECHO_REPLY 0 +#define ICMP_ECHO 8 + +struct icmpip_hdr { + /* IP header. */ + uint8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + uint16_t ipchksum; + uint8_t srcipaddr[4], + destipaddr[4]; + /* The ICMP and IP headers. */ + /* ICMP (echo) header. */ + uint8_t type, icode; + uint16_t icmpchksum; + uint16_t id, seqno; +}; + + +/* The UDP and IP headers. */ +struct udpip_hdr { + /* IP header. */ + uint8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + uint16_t ipchksum; + uint8_t srcipaddr[4], + destipaddr[4]; + + /* UDP header. */ + uint16_t srcport, + destport; + uint16_t udplen; + uint16_t udpchksum; +}; + +#define ETHBUF ((struct eth_hdr *)&packet[0]) +#define IPBUF ((struct ip_hdr *)&packet[0]) +#define UDPBUF ((struct udpip_hdr *)&packet[0]) +#define ICMPBUF ((struct icmpip_hdr *)&packet[0]) +#define TCPBUF ((struct tcpip_hdr *)&packet[0]) + + +/*---------------------------------------------------------------------------*/ +static void +tcpflags(unsigned char flags, char *flagsstr) +{ + if(flags & TCP_FIN) { + *flagsstr++ = 'F'; + } + if(flags & TCP_SYN) { + *flagsstr++ = 'S'; + } + if(flags & TCP_RST) { + *flagsstr++ = 'R'; + } + if(flags & TCP_ACK) { + *flagsstr++ = 'A'; + } + if(flags & TCP_URG) { + *flagsstr++ = 'U'; + } + + *flagsstr = 0; +} +/*---------------------------------------------------------------------------*/ +static char * CC_FASTCALL +n(uint16_t num, char *ptr) +{ + uint16_t d; + uint8_t a, f; + + if(num == 0) { + *ptr = '0'; + return ptr + 1; + } else { + f = 0; + for(d = 10000; d >= 1; d /= 10) { + a = (num / d) % 10; + if(f == 1 || a > 0) { + *ptr = a + '0'; + ++ptr; + f = 1; + } + } + } + return ptr; +} +/*---------------------------------------------------------------------------*/ +static char * CC_FASTCALL +d(char *ptr) +{ + *ptr = '.'; + return ptr + 1; +} +/*---------------------------------------------------------------------------*/ +static char * CC_FASTCALL +s(char *str, char *ptr) +{ + strcpy(ptr, str); + return ptr + strlen(str); +} +/*---------------------------------------------------------------------------*/ +int +tcpdump_format(uint8_t *packet, uint16_t packetlen, + char *buf, uint16_t buflen) +{ + char flags[8]; + if(IPBUF->proto == UIP_PROTO_ICMP) { + if(ICMPBUF->type == ICMP_ECHO) { + return s(" ping", + n(IPBUF->destipaddr[3], d( + n(IPBUF->destipaddr[2], d( + n(IPBUF->destipaddr[1], d( + n(IPBUF->destipaddr[0], + s(" ", + n(IPBUF->srcipaddr[3], d( + n(IPBUF->srcipaddr[2], d( + n(IPBUF->srcipaddr[1], d( + n(IPBUF->srcipaddr[0], + buf)))))))))))))))) - buf; + + /* return sprintf(buf, "%d.%d.%d.%d %d.%d.%d.%d ping", + IPBUF->srcipaddr[0], IPBUF->srcipaddr[1], + IPBUF->srcipaddr[2], IPBUF->srcipaddr[3], + IPBUF->destipaddr[0], IPBUF->destipaddr[1], + IPBUF->destipaddr[2], IPBUF->destipaddr[3]);*/ + } else if(ICMPBUF->type == ICMP_ECHO_REPLY) { + return s(" pong", + n(IPBUF->destipaddr[3], d( + n(IPBUF->destipaddr[2], d( + n(IPBUF->destipaddr[1], d( + n(IPBUF->destipaddr[0], + s(" ", + n(IPBUF->srcipaddr[3], d( + n(IPBUF->srcipaddr[2], d( + n(IPBUF->srcipaddr[1], d( + n(IPBUF->srcipaddr[0], + buf)))))))))))))))) - buf; + /* return sprintf(buf, "%d.%d.%d.%d %d.%d.%d.%d pong", + IPBUF->srcipaddr[0], IPBUF->srcipaddr[1], + IPBUF->srcipaddr[2], IPBUF->srcipaddr[3], + IPBUF->destipaddr[0], IPBUF->destipaddr[1], + IPBUF->destipaddr[2], IPBUF->destipaddr[3]);*/ + } + } else if(IPBUF->proto == UIP_PROTO_UDP) { + return s(" UDP", + n(uip_htons(UDPBUF->destport), d( + n(IPBUF->destipaddr[3], d( + n(IPBUF->destipaddr[2], d( + n(IPBUF->destipaddr[1], d( + n(IPBUF->destipaddr[0], + s(" ", + n(uip_htons(UDPBUF->srcport), d( + n(IPBUF->srcipaddr[3], d( + n(IPBUF->srcipaddr[2], d( + n(IPBUF->srcipaddr[1], d( + n(IPBUF->srcipaddr[0], + buf)))))))))))))))))))) - buf; + /* return sprintf(buf, "%d.%d.%d.%d.%d %d.%d.%d.%d.%d UDP", + IPBUF->srcipaddr[0], IPBUF->srcipaddr[1], + IPBUF->srcipaddr[2], IPBUF->srcipaddr[3], + uip_htons(UDPBUF->srcport), + IPBUF->destipaddr[0], IPBUF->destipaddr[1], + IPBUF->destipaddr[2], IPBUF->destipaddr[3], + uip_htons(UDPBUF->destport));*/ + } else if(IPBUF->proto == UIP_PROTO_TCP) { + tcpflags(TCPBUF->flags, flags); + return s(flags, + s(" ", + n(uip_htons(TCPBUF->destport), d( + n(IPBUF->destipaddr[3], d( + n(IPBUF->destipaddr[2], d( + n(IPBUF->destipaddr[1], d( + n(IPBUF->destipaddr[0], + s(" ", + n(uip_htons(TCPBUF->srcport), d( + n(IPBUF->srcipaddr[3], d( + n(IPBUF->srcipaddr[2], d( + n(IPBUF->srcipaddr[1], d( + n(IPBUF->srcipaddr[0], + buf))))))))))))))))))))) - buf; + /* return sprintf(buf, "%d.%d.%d.%d.%d %d.%d.%d.%d.%d %s", + IPBUF->srcipaddr[0], IPBUF->srcipaddr[1], + IPBUF->srcipaddr[2], IPBUF->srcipaddr[3], + uip_htons(TCPBUF->srcport), + IPBUF->destipaddr[0], IPBUF->destipaddr[1], + IPBUF->destipaddr[2], IPBUF->destipaddr[3], + uip_htons(TCPBUF->destport), + flags); */ + } else { + strcpy(buf, "Unrecognized protocol"); + } + + return 0; +} +/*---------------------------------------------------------------------------*/ diff --git a/tools/wpcapslip/wpcap.c b/tools/wpcapslip/wpcap.c index 5584557a9..b8127d47c 100644 --- a/tools/wpcapslip/wpcap.c +++ b/tools/wpcapslip/wpcap.c @@ -58,7 +58,6 @@ #include #include -#include #include #include #include @@ -69,7 +68,7 @@ #define PROGRESS(x) -static void raw_send(void *buf, int len); +void raw_send(void *buf, int len); struct pcap; @@ -150,7 +149,7 @@ struct arp_entry { struct uip_eth_addr ethaddr; uint8_t time; }; -static struct uip_eth_addr uip_lladdr = {{0,0,0,0,0,0}}; +struct uip_eth_addr uip_ethaddr = {{0,0,0,0,0,0}}; static const uip_ipaddr_t all_zeroes_addr = { { 0x0, /* rest is 0 */ } }; static const struct uip_eth_addr broadcast_ethaddr = {{0xff,0xff,0xff,0xff,0xff,0xff}}; @@ -164,18 +163,20 @@ static int arptime; static int logging; +uip_lladdr_t uip_lladdr; + static void log_message(char *msg1, char *msg2) { if(logging) { - printf("Log: %s %s\n", msg1, msg2); + fprintf(stderr, "Log: %s %s\n", msg1, msg2); } } /*---------------------------------------------------------------------------*/ static void error_exit(char *msg1) { - printf("error_exit: %s", msg1); + fprintf(stderr, "error_exit: %s", msg1); exit(EXIT_FAILURE); } /*---------------------------------------------------------------------------*/ @@ -198,11 +199,11 @@ init_pcap(struct in_addr addr) paddr != NULL; paddr = paddr->next) { if(paddr->addr != NULL && paddr->addr->sa_family == AF_INET) { - + struct in_addr interface_addr; interface_addr = ((struct sockaddr_in *)paddr->addr)->sin_addr; log_message("init_pcap: with address: ", inet_ntoa(interface_addr)); - + if(interface_addr.s_addr == addr.s_addr) { pcap = pcap_open_live(interfaces->name, BUFSIZE, 0, -1, error); if(pcap == NULL) { @@ -263,7 +264,7 @@ set_ethaddr(struct in_addr addr) log_message("set_ethaddr: with address: ", inet_ntoa(adapter_addr)); if(adapter_addr.s_addr == addr.s_addr) { - printf("Using local network interface with address %s\n", + fprintf(stderr, "Using local network interface with address %s\n", inet_ntoa(adapter_addr)); if(adapters->PhysicalAddressLength != 6) { error_exit("ip addr specified on cmdline does not belong to an ethernet card\n"); @@ -292,12 +293,12 @@ print_packet(unsigned char *buf, int len) int i; for(i = 0; i < len; ++i) { - printf("0x%02x, ", buf[i]); + fprintf(stderr, "0x%02x, ", buf[i]); if(i % 8 == 7) { - printf("\n"); + fprintf(stderr, "\n"); } } - printf("\n\n"); + fprintf(stderr, "\n\n"); } /*---------------------------------------------------------------------------*/ static void @@ -305,7 +306,7 @@ uip_arp_update(uip_ipaddr_t *ipaddr, struct uip_eth_addr *ethaddr) { struct arp_entry *tabptr; int i, tmpage, c; - + /* Walk through the ARP mapping table and try to find an entry to update. If none is found, the IP -> MAC address mapping is inserted in the ARP table. */ @@ -318,7 +319,7 @@ uip_arp_update(uip_ipaddr_t *ipaddr, struct uip_eth_addr *ethaddr) /* Check if the source IP address of the incoming packet matches the IP address in this ARP table entry. */ if(uip_ipaddr_cmp(ipaddr, &tabptr->ipaddr)) { - + /* An old entry found, update this and return. */ memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6); tabptr->time = arptime; @@ -399,7 +400,7 @@ arp_out(struct ethip_hdr *iphdr, int len) int i; #endif -#if 1 +#if 0 /* Find the destination IP address in the ARP table and construct the Ethernet header. If the destination IP addres isn't on the local network, we use the default router's IP address instead. @@ -425,7 +426,7 @@ arp_out(struct ethip_hdr *iphdr, int len) /* Else, we use the destination IP address. */ uip_ipaddr_copy(&ipaddr, &iphdr->destipaddr); } - + for(i = 0; i < UIP_ARPTAB_SIZE; ++i) { tabptr = &arp_table[i]; if(uip_ipaddr_cmp(&ipaddr, &tabptr->ipaddr)) { @@ -439,9 +440,9 @@ arp_out(struct ethip_hdr *iphdr, int len) memset(arphdr->ethhdr.dest.addr, 0xff, 6); memset(arphdr->dhwaddr.addr, 0x00, 6); - memcpy(arphdr->ethhdr.src.addr, uip_lladdr.addr, 6); - memcpy(arphdr->shwaddr.addr, uip_lladdr.addr, 6); - + memcpy(arphdr->ethhdr.src.addr, uip_ethaddr.addr, 6); + memcpy(arphdr->shwaddr.addr, uip_ethaddr.addr, 6); + uip_ipaddr_copy(&arphdr->dipaddr, &ipaddr); uip_ipaddr_copy(&arphdr->sipaddr, &netaddr); arphdr->opcode = UIP_HTONS(ARP_REQUEST); /* ARP request. */ @@ -476,27 +477,27 @@ do_arp(void *buf, int len) if(hdr->ethhdr.type == UIP_HTONS(UIP_ETHTYPE_ARP)) { if(hdr->opcode == UIP_HTONS(ARP_REQUEST)) { /* Check if the ARP is for our network */ - /* printf("ARP for %d.%d.%d.%d we are %d.%d.%d.%d/%d.%d.%d.%d\n", + /* fprintf(stderr, "ARP for %d.%d.%d.%d we are %d.%d.%d.%d/%d.%d.%d.%d\n", uip_ipaddr_to_quad(&hdr->dipaddr), uip_ipaddr_to_quad(&netaddr), uip_ipaddr_to_quad(&netmask));*/ if(uip_ipaddr_maskcmp(&hdr->dipaddr, &netaddr, &netmask)) { uip_ipaddr_t tmpaddr; - - /* printf("ARP for us.\n");*/ + + /* fprintf(stderr, "ARP for us.\n");*/ uip_arp_update(&hdr->sipaddr, &hdr->shwaddr); - + hdr->opcode = UIP_HTONS(ARP_REPLY); - + memcpy(&hdr->dhwaddr.addr, &hdr->shwaddr.addr, 6); memcpy(&hdr->shwaddr.addr, &uip_lladdr.addr, 6); memcpy(&hdr->ethhdr.src.addr, &uip_lladdr.addr, 6); memcpy(&hdr->ethhdr.dest.addr, &hdr->dhwaddr.addr, 6); - + uip_ipaddr_copy(&tmpaddr, &hdr->dipaddr); uip_ipaddr_copy(&hdr->dipaddr, &hdr->sipaddr); uip_ipaddr_copy(&hdr->sipaddr, &tmpaddr); - + hdr->ethhdr.type = UIP_HTONS(UIP_ETHTYPE_ARP); raw_send(hdr, sizeof(struct arp_hdr)); return NULL; @@ -521,8 +522,8 @@ cleanup(void) char buf[1024]; snprintf(buf, sizeof(buf), "route delete %d.%d.%d.%d", - uip_ipaddr_to_quad(&ifaddr)); - printf("%s\n", buf); + uip_ipaddr_to_quad(&netaddr)); + fprintf(stderr, "%s\n", buf); system(buf); } @@ -540,9 +541,9 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log) struct in_addr addr; char buf[4000]; uint32_t tmpaddr; - + logging = log; - + addr.s_addr = inet_addr(ethcardaddr); tmpaddr = inet_addr(ethcardaddr); memcpy(&ifaddr.u16[0], &tmpaddr, sizeof(tmpaddr)); @@ -551,21 +552,21 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log) tmpaddr = inet_addr(slipnetmask); memcpy(&netmask.u16[0], &tmpaddr, sizeof(tmpaddr)); - printf("Network address %d.%d.%d.%d/%d.%d.%d.%d\n", + fprintf(stderr, "Network address %d.%d.%d.%d/%d.%d.%d.%d\n", uip_ipaddr_to_quad(&netaddr), uip_ipaddr_to_quad(&netmask)); - + snprintf(buf, sizeof(buf), "route add %d.%d.%d.%d mask %d.%d.%d.%d %d.%d.%d.%d", uip_ipaddr_to_quad(&netaddr), uip_ipaddr_to_quad(&netmask), uip_ipaddr_to_quad(&ifaddr)); - printf("%s\n", buf); + fprintf(stderr, "%s\n", buf); system(buf); signal(SIGTERM, remove_route); log_message("wpcap_init: cmdline address: ", inet_ntoa(addr)); - + wpcap = LoadLibrary("wpcap.dll"); pcap_findalldevs = (int (*)(struct pcap_if **, char *)) GetProcAddress(wpcap, "pcap_findalldevs"); @@ -588,12 +589,12 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log) #if 0 while(1) { int ret; - + ret = wpcap_poll(buf); if(ret > 0) { /* print_packet(buf, ret);*/ if(do_arp(buf, ret)) { - printf("IP packet\n"); + fprintf(stderr, "IP packet\n"); } } sleep(1); @@ -602,17 +603,16 @@ wpcap_start(char *ethcardaddr, char *slipnetaddr, char *slipnetmask, int log) } /*---------------------------------------------------------------------------*/ uint16_t -wpcap_poll(char **buf) +wpcap_poll(char **buf, int eth) { struct pcap_pkthdr *packet_header; unsigned char *packet; int len; + int ret; char *buf2; - switch(pcap_next_ex(pcap, &packet_header, &packet)) { - case -1: - error_exit("error on poll\n"); - case 0: + ret = pcap_next_ex(pcap, &packet_header, &packet); + if (ret != 1) { return 0; } @@ -622,13 +622,20 @@ wpcap_poll(char **buf) CopyMemory(*buf, packet, packet_header->caplen); len = packet_header->caplen; - /* printf("len %d\n", len);*/ + + if(eth) { + /* poll requested us to return the raw ethernet packet */ + return len; + } + + buf2 = do_arp(*buf, len); if(buf2 == NULL) { return 0; } else { len = len - (buf2 - *buf); *buf = buf2; + /*fprintf(stderr, "wpcap_poll() %d\n", len);*/ return len; } } @@ -644,7 +651,7 @@ wpcap_send(void *buf, int len) raw_send(buf2, len); } /*---------------------------------------------------------------------------*/ -static void +void raw_send(void *buf, int len) { /* printf("sending len %d\n", len);*/ diff --git a/tools/wpcapslip/wpcapslip.c b/tools/wpcapslip/wpcapslip.c index e6e193f90..b60af7f6a 100644 --- a/tools/wpcapslip/wpcapslip.c +++ b/tools/wpcapslip/wpcapslip.c @@ -47,8 +47,6 @@ #include #include #include -#include -#include #include #include @@ -75,6 +73,18 @@ static int should_print = 0; #define IP_HLEN 20 +/*---------------------------------------------------------------------------*/ +uint16_t +uip_htons(uint16_t val) +{ + return UIP_HTONS(val); +} +/*---------------------------------------------------------------------------*/ +uint32_t +uip_htonl(uint32_t val) +{ + return UIP_HTONL(val); +} /*---------------------------------------------------------------------------*/ static void print_packet(uint8_t *packet, int len) @@ -289,8 +299,9 @@ serial_to_wpcap(FILE *inslip) */ #define DEBUG_LINE_MARKER '\r' int ecode; + ecode = check_ip(&uip.iphdr, inbufptr); - if(ecode < 0 && inbufptr == 8 && strncmp(uip.inbuf, "=IPA", 4) == 0) { + if(ecode < 0 && inbufptr == 8 && strncmp((const char*)uip.inbuf, "=IPA", 4) == 0) { static struct in_addr ipa; inbufptr = 0; @@ -902,7 +913,7 @@ main(int argc, char **argv) if(iphdr->ip_id != last_id) { last_id = iphdr->ip_id; /* printf("------ wpcap_poll ret %d\n", ret);*/ - print_packet(pbuf, ret); + print_packet((uint8_t*)pbuf, ret); write_to_serial(slipfd, pbuf, ret); slip_flushbuf(slipfd); sigalarm_reset(); diff --git a/tools/wpcapslip/wpcapstdio.c b/tools/wpcapslip/wpcapstdio.c new file mode 100644 index 000000000..88f1eace4 --- /dev/null +++ b/tools/wpcapslip/wpcapstdio.c @@ -0,0 +1,597 @@ +/* + * 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. + * + * This file is part of the Contiki operating system. + * + * Author: Fredrik Osterlind + * Based on wpcapslip.c by : Oliver Schmidt + */ + +/* This is a stripped-down version of wpcapslip: Instead of reading from and writing + * to a serial port, this program just reads and writes to stdin/stdout. To + * achieve the same functionality as wpcapslip, this program can hence be connected + * to serialdump. But, in contrast to wpcapslip, this program can easily be connected + * to networked or simulated serial ports. -- Fredrik, 2012 */ + +#include +#include +#include +#ifdef __CYGWIN__ +#include +#else /* __CYGWIN__ */ +#include +#endif /* __CYGWIN__ */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#define PROGRESS(x) + +void wpcap_start(char *ethifaddr, char *netaddr, char *netmask, int logging); + +void wpcap_send(void *buf, int len); +void raw_send(void *buf, int len); + +uint16_t wpcap_poll(char **buf, int eth); + +#include "net/tcpdump.h" +static int should_print = 0; + +static int send_eth = 0; /* Sends ethernet frames or IP packets */ + +#define IP_HLEN 20 + +/*---------------------------------------------------------------------------*/ +uint16_t +uip_htons(uint16_t val) +{ + return UIP_HTONS(val); +} +/*---------------------------------------------------------------------------*/ +uint32_t +uip_htonl(uint32_t val) +{ + return UIP_HTONL(val); +} +/*---------------------------------------------------------------------------*/ +static void +print_packet(char* prefix, uint8_t *packet, int len) +{ + char buf[2000]; + if(should_print) { + tcpdump_format(packet, len, buf, sizeof(buf)); + fprintf(stderr, "%s: %s\n", prefix, buf); + } +} +/*---------------------------------------------------------------------------*/ +void cleanup(void); +/*---------------------------------------------------------------------------*/ +void +sigcleanup(int signo) +{ + fprintf(stderr, "signal %d\n", signo); + exit(0); /* exit(0) will call cleanup() */ +} +/*---------------------------------------------------------------------------*/ +#define SLIP_END 0300 +#define SLIP_ESC 0333 +#define SLIP_ESC_END 0334 +#define SLIP_ESC_ESC 0335 + +struct ip { + u_int8_t ip_vhl; /* version and header length */ +#define IP_V4 0x40 +#define IP_V 0xf0 +#define IP_HL 0x0f + u_int8_t ip_tos; /* type of service */ + u_int16_t ip_len; /* total length */ + u_int16_t ip_id; /* identification */ + u_int16_t ip_off; /* fragment offset field */ +#define IP_RF 0x8000 /* reserved fragment flag */ +#define IP_DF 0x4000 /* dont fragment flag */ +#define IP_MF 0x2000 /* more fragments flag */ +#define IP_OFFMASK 0x1fff /* mask for fragmenting bits */ + u_int8_t ip_ttl; /* time to live */ + u_int8_t ip_p; /* protocol */ + u_int16_t ip_sum; /* checksum */ + u_int32_t ip_src, ip_dst; /* source and dest address */ + u_int16_t uh_sport; /* source port */ + u_int16_t uh_dport; /* destination port */ + u_int16_t uh_ulen; /* udp length */ + u_int16_t uh_sum; /* udp checksum */ +}; + +static int ip_id, last_id; + +int +ssystem(const char *fmt, ...) __attribute__((__format__ (__printf__, 1, 2))); + +int +ssystem(const char *fmt, ...) +{ + char cmd[128]; + va_list ap; + va_start(ap, fmt); + vsnprintf(cmd, sizeof(cmd), fmt, ap); + va_end(ap); + fprintf(stderr, "%s\n", cmd); + fflush(stderr); + return system(cmd); +} +/*---------------------------------------------------------------------------*/ +int +is_sensible_string(const unsigned char *s, int len) +{ + int i; + for(i = 1; i < len; i++) { + if(s[i] == 0 || s[i] == '\r' || s[i] == '\n' || s[i] == '\t') { + continue; + } else if(s[i] < ' ' || '~' < s[i]) { + return 0; + } + } + return 1; +} +/*---------------------------------------------------------------------------*/ +u_int16_t +ip4sum(u_int16_t sum, const void *_p, u_int16_t len) +{ + u_int16_t t; + const u_int8_t *p = _p; + const u_int8_t *end = p + len; + + while(p < (end - 1)) { + t = (p[0] << 8) + p[1]; + sum += t; + if(sum < t) + sum++; + p += 2; + } + if(p < end) { + t = (p[0] << 8) + 0; + sum += t; + if(sum < t) + sum++; + } + return sum; +} +/*---------------------------------------------------------------------------*/ +static uint16_t +chksum(const void *p, uint16_t len) +{ + uint16_t sum = ip4sum(0, p, len); + return (sum == 0) ? 0xffff : uip_htons(sum); +} +/*---------------------------------------------------------------------------*/ +int +check_ip(const struct ip *ip, unsigned ip_len) +{ + u_int16_t sum, ip_hl; + + if(send_eth) { + return 0; + } + + /* Check IP version and length. */ + if((ip->ip_vhl & IP_V) != IP_V4) { + return -1; + } + + if(uip_ntohs(ip->ip_len) > ip_len) { + return -2; + } + + if(uip_ntohs(ip->ip_len) < ip_len) { + return -3; + } + + /* Check IP header. */ + ip_hl = 4 * (ip->ip_vhl & IP_HL); + sum = ip4sum(0, ip, ip_hl); + if(sum != 0xffff && sum != 0x0) { + return -4; + } + + if(ip->ip_p == 6 || ip->ip_p == 17) { /* Check TCP or UDP header. */ + u_int16_t tcp_len = ip_len - ip_hl; + + /* Sum pseudoheader. */ + sum = ip->ip_p + tcp_len; /* proto and len, no carry */ + sum = ip4sum(sum, &ip->ip_src, 8); /* src and dst */ + + /* Sum TCP/UDP header and data. */ + sum = ip4sum(sum, (u_int8_t*)ip + ip_hl, tcp_len); + + /* Failed checksum test? */ + if(sum != 0xffff && sum != 0x0) { + if(ip->ip_p == 6) { /* TCP == 6 */ + return -5; + } else { /* UDP */ + /* Deal with disabled UDP checksums. */ + if(ip->uh_sum != 0) { + return -6; + } + } + } + } else if(ip->ip_p == 1) { /* ICMP */ + u_int16_t icmp_len = ip_len - ip_hl; + + sum = ip4sum(0, (u_int8_t*)ip + ip_hl, icmp_len); + if(sum != 0xffff && sum != 0x0) { + return -7; + } + } + return 0; +} +/*---------------------------------------------------------------------------*/ +/* + * Read a single character from stdin. When we have a full packet, write it to + * the network interface. + */ +void +serial_to_wpcap(void) +{ + static union { + unsigned char inbuf[2000]; + struct ip iphdr; + } uip; + static int inbufptr = 0; + + int ret; + unsigned char c; + + if(inbufptr >= sizeof(uip.inbuf)) { + inbufptr = 0; + return; + } + ret = read(STDIN_FILENO, &c, 1); + + if(ret <= 0) { + err(1, "serial_to_wpcap: read"); + inbufptr = 0; + return; + } + + switch (c) { + case SLIP_END: + if(inbufptr > 0) { + /* + * Sanity checks. + */ +#define DEBUG_LINE_MARKER '\r' + int ecode; + + ecode = check_ip(&uip.iphdr, inbufptr); + if(ecode < 0 && inbufptr == 8 + && strncmp((const char*)uip.inbuf, "=IPA", 4) == 0) { + static struct in_addr ipa; + + inbufptr = 0; + if(memcmp(&ipa, &uip.inbuf[4], sizeof(ipa)) == 0) { + break; + } + + memcpy(&ipa, &uip.inbuf[4], sizeof(ipa)); + break; + } else if(ecode < 0) { + /* + * If sensible ASCII string, print it as debug info! + */ + /* printf("----------------------------------\n");*/ + if(uip.inbuf[0] == DEBUG_LINE_MARKER) { + fwrite(uip.inbuf + 1, inbufptr - 1, 1, stderr); + } else if(is_sensible_string(uip.inbuf, inbufptr)) { + fwrite(uip.inbuf, inbufptr, 1, stderr); + } else { + fprintf(stderr, "serial_to_wpcap: drop packet len=%d ecode=%d\n", + inbufptr, ecode); + } + inbufptr = 0; + break; + } + PROGRESS("s"); + + if(send_eth) { + raw_send(uip.inbuf, inbufptr); + } else { + /* printf("Sending to wpcap\n");*/ + if(uip.iphdr.ip_id != last_id) { + last_id = uip.iphdr.ip_id; + print_packet("to wpcap: ", uip.inbuf, inbufptr); + wpcap_send(uip.inbuf, inbufptr); + } else { + /*print_packet("IGNORED to wpcap: ", uip.inbuf, inbufptr);*/ + } + } + /* printf("After sending to wpcap\n");*/ + inbufptr = 0; + } + break; + + case SLIP_ESC: + /* TODO We do not actually check that we have another byte incoming, so + * we may block here */ + read(STDIN_FILENO, &c, 1); + + switch (c) { + case SLIP_ESC_END: + c = SLIP_END; + break; + case SLIP_ESC_ESC: + c = SLIP_ESC; + break; + } + + /* FALLTHROUGH */ + default: + uip.inbuf[inbufptr++] = c; + break; + } +} +/*---------------------------------------------------------------------------*/ +unsigned char stdout_buf[2000]; +int stdout_buf_cnt; +/*---------------------------------------------------------------------------*/ +void +stdout_write(unsigned char c) +{ + if(stdout_buf_cnt >= sizeof(stdout_buf)) { + err(1, "stdout_write overflow"); + } + stdout_buf[stdout_buf_cnt] = c; + stdout_buf_cnt++; +} +/*---------------------------------------------------------------------------*/ +int +stdout_buf_empty(void) +{ + return stdout_buf_cnt == 0; +} +/*---------------------------------------------------------------------------*/ +void +stdout_flushbuf(void) +{ + if(stdout_buf_empty()) { + return; + } + + fwrite(stdout_buf, stdout_buf_cnt, 1, stdout); + stdout_buf_cnt = 0; + fflush(stdout); +} +/*---------------------------------------------------------------------------*/ +void +write_slip_stdout(void *inbuf, int len) +{ + u_int8_t *p = inbuf; + int i, ecode; + struct ip *iphdr = inbuf; + + if(!send_eth) { + /* + * Sanity checks. + */ + /*fprintf(stderr, "write_slip_stdout: %d\n", len);*/ + ecode = check_ip(inbuf, len); + if(ecode < 0) { + fprintf(stderr, "write_slip_stdout: drop packet %d\n", ecode); + return; + } + + if(iphdr->ip_id == 0 && iphdr->ip_off & IP_DF) { + uint16_t nid = uip_htons(ip_id++); + iphdr->ip_id = nid; + nid = ~nid; /* negate */ + iphdr->ip_sum += nid; /* add */ + if(iphdr->ip_sum < nid) { /* 1-complement overflow? */ + iphdr->ip_sum++; + } + ecode = check_ip(inbuf, len); + if(ecode < 0) { + fprintf(stderr, "write_slip_stdout: drop packet %d\n", ecode); + return; + } + } + + iphdr->ip_ttl = uip_htons(uip_htons(iphdr->ip_ttl) + 1); + if(iphdr->ip_ttl == 0) { + fprintf(stderr, "Packet with ttl %d dropped\n", iphdr->ip_ttl); + return; + } + iphdr->ip_sum = 0; + iphdr->ip_sum = ~chksum(iphdr, 4 * (iphdr->ip_vhl & IP_HL)); + ecode = check_ip(inbuf, len); + if(ecode < 0) { + fprintf(stderr, "write_slip_stdout: drop packet %d\n", ecode); + return; + } + } + + for(i = 0; i < len; i++) { + switch (p[i]) { + case SLIP_END: + stdout_write(SLIP_ESC); + stdout_write(SLIP_ESC_END); + break; + case SLIP_ESC: + stdout_write(SLIP_ESC); + stdout_write(SLIP_ESC_ESC); + break; + default: + stdout_write(p[i]); + break; + } + } + stdout_write(SLIP_END); + /* printf("slip end\n");*/ + PROGRESS("t"); +} +/*---------------------------------------------------------------------------*/ +/*const char *ipaddr;*/ +/*const char *netmask;*/ +static int got_sigalarm; +void +sigalarm(int signo) +{ + got_sigalarm = 1; + return; +} +/*---------------------------------------------------------------------------*/ +void +sigalarm_reset(void) +{ +#ifdef linux +#define TIMEOUT (997*1000) +#else +#define TIMEOUT (2451*1000) +#endif + ualarm(TIMEOUT, TIMEOUT); + got_sigalarm = 0; +} +/*---------------------------------------------------------------------------*/ +int +main(int argc, char **argv) +{ + int c; + int ret; + char buf[4000]; + int logging = 0; + + ip_id = getpid() * time(NULL); + + while((c = getopt(argc, argv, "E:D:hl:t:T")) != -1) { + switch (c) { + case 'E': + send_eth = 1; + break; + + case 'T': + should_print = 1; + break; + + case 'l': + logging = 1; + break; + + case '?': + case 'h': + default: + err(1, + "usage: wpcapstdio [-E] [-l] [-T] "); + break; + } + } + argc -= (optind - 1); + argv += (optind - 1); + + if(argc != 4) { + err(1, "usage: wpcapstdio [-E] [-T] "); + } + + wpcap_start(argv[1], argv[2], argv[3], logging); + stdout_write(SLIP_END); + + atexit(cleanup); + signal(SIGHUP, sigcleanup); + signal(SIGTERM, sigcleanup); + signal(SIGINT, sigcleanup); + signal(SIGALRM, sigalarm); + + while(1) { + if(got_sigalarm) { + /* Send "?IPA". */ + stdout_write('?'); + stdout_write('I'); + stdout_write('P'); + stdout_write('A'); + stdout_write(SLIP_END); + got_sigalarm = 0; + } + + if(stdout_buf_empty()) { + char *pbuf = buf; + + ret = wpcap_poll(&pbuf, send_eth); + if(ret > 0) { + if(send_eth) { + write_slip_stdout(pbuf, ret); + stdout_flushbuf(); + } else { + struct ip *iphdr = (struct ip *)pbuf; + if(iphdr->ip_id != last_id) { + /*last_id = iphdr->ip_id;*/ + print_packet("to stdout: ", (uint8_t*)pbuf, ret); + write_slip_stdout(pbuf, ret); + stdout_flushbuf(); + } else { + /*print_packet("IGNORED to stdout: ", (uint8_t*)pbuf, ret);*/ + } + } + } + } + + if(!stdout_buf_empty()) { + stdout_flushbuf(); + } + + { + fd_set s_rd; + struct timeval tv; + + tv.tv_sec = 0; + tv.tv_usec = 100; + + do { + FD_ZERO(&s_rd); + FD_SET(fileno(stdin), &s_rd); + select(fileno(stdin) + 1, &s_rd, NULL, NULL, &tv); + if(FD_ISSET(fileno(stdin), &s_rd)) { + serial_to_wpcap(); + } + } while(FD_ISSET(fileno(stdin), &s_rd)); + } + } +} +/*---------------------------------------------------------------------------*/ diff --git a/tools/z1/z1-bsl-nopic b/tools/z1/z1-bsl-nopic index db2435b92..802c84642 100755 --- a/tools/z1/z1-bsl-nopic +++ b/tools/z1/z1-bsl-nopic @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 # Serial Bootstrap Loader software for the MSP430 embedded proccessor. # # (C) 2001-2003 Chris Liechti @@ -293,9 +293,9 @@ class LowLevel: #used for some hardware self.invertRST = 0 self.invertTEST = 0 - self.swapRSTTEST = 0 - self.telosLatch = 0 - self.telosI2C = 0 + self.swapRSTTEST = 0 + self.telosLatch = 0 + self.telosI2C = 0 self.z1 = 0 @@ -581,22 +581,22 @@ class LowLevel: self.serialport.setDTR(not level) def telosI2CStart(self): - self.telosSetSDA(1) - self.telosSetSCL(1) - self.telosSetSDA(0) + self.telosSetSDA(1) + self.telosSetSCL(1) + self.telosSetSDA(0) def telosI2CStop(self): - self.telosSetSDA(0) - self.telosSetSCL(1) - self.telosSetSDA(1) + self.telosSetSDA(0) + self.telosSetSCL(1) + self.telosSetSDA(1) def telosI2CWriteBit(self, bit): - self.telosSetSCL(0) - self.telosSetSDA(bit) + self.telosSetSCL(0) + self.telosSetSDA(bit) time.sleep(2e-6) - self.telosSetSCL(1) + self.telosSetSCL(1) time.sleep(1e-6) - self.telosSetSCL(0) + self.telosSetSCL(0) def telosI2CWriteByte(self, byte): self.telosI2CWriteBit( byte & 0x80 ); @@ -610,34 +610,34 @@ class LowLevel: self.telosI2CWriteBit( 0 ); # "acknowledge" def telosI2CWriteCmd(self, addr, cmdbyte): - self.telosI2CStart() + self.telosI2CStart() self.telosI2CWriteByte( 0x90 | (addr << 1) ) - self.telosI2CWriteByte( cmdbyte ) - self.telosI2CStop() + self.telosI2CWriteByte( cmdbyte ) + self.telosI2CStop() def telosBReset(self,invokeBSL=0): - # "BSL entry sequence at dedicated JTAG pins" + # "BSL entry sequence at dedicated JTAG pins" # rst !s0: 0 0 0 0 1 1 - # tck !s1: 1 0 1 0 0 1 + # tck !s1: 1 0 1 0 0 1 # s0|s1: 1 3 1 3 2 0 - # "BSL entry sequence at shared JTAG pins" + # "BSL entry sequence at shared JTAG pins" # rst !s0: 0 0 0 0 1 1 - # tck !s1: 0 1 0 1 1 0 + # tck !s1: 0 1 0 1 1 0 # s0|s1: 3 1 3 1 0 2 - if invokeBSL: - self.telosI2CWriteCmd(0,1) - self.telosI2CWriteCmd(0,3) - self.telosI2CWriteCmd(0,1) - self.telosI2CWriteCmd(0,3) - self.telosI2CWriteCmd(0,2) - self.telosI2CWriteCmd(0,0) - else: - self.telosI2CWriteCmd(0,3) - self.telosI2CWriteCmd(0,2) - self.telosI2CWriteCmd(0,0) + if invokeBSL: + self.telosI2CWriteCmd(0,1) + self.telosI2CWriteCmd(0,3) + self.telosI2CWriteCmd(0,1) + self.telosI2CWriteCmd(0,3) + self.telosI2CWriteCmd(0,2) + self.telosI2CWriteCmd(0,0) + else: + self.telosI2CWriteCmd(0,3) + self.telosI2CWriteCmd(0,2) + self.telosI2CWriteCmd(0,0) time.sleep(0.250) #give MSP430's oscillator time to stabilize - self.serialport.flushInput() #clear buffers + self.serialport.flushInput() #clear buffers def bslReset(self, invokeBSL=0): """Applies BSL entry sequence on RST/NMI and TEST/VPP pins @@ -651,9 +651,9 @@ class LowLevel: #print 'goint to reset!' - if self.telosI2C: - self.telosBReset(invokeBSL) - return + if self.telosI2C: + self.telosBReset(invokeBSL) + return if self.z1: if DEBUG > 1: sys.stderr.write("* entering bsl with z1\n") @@ -665,10 +665,10 @@ class LowLevel: self.SetTESTpin(1) #power suply time.sleep(0.250) #charge capacitor on boot loader hardware - if self.telosLatch: - self.SetTESTpin(0) - self.SetRSTpin(0) - self.SetTESTpin(1) + if self.telosLatch: + self.SetTESTpin(0) + self.SetRSTpin(0) + self.SetTESTpin(1) self.SetRSTpin(0) #RST pin: GND if invokeBSL: @@ -1599,11 +1599,11 @@ def main(itest=1): "upload=", "download=", "size=", "hex", "bin", "intelhex", "titext", "notimeout", "bsl=", "speed=", "bslversion", "f1x", "f2x", "f4x", "invert-reset", "invert-test", - "swap-reset-test", "telos-latch", "telos-i2c", "telos", "telosb", + "swap-reset-test", "telos-latch", "telos-i2c", "telos", "telosb", "tmote","no-BSL-download", "force-BSL-download", "slow", "dumpivt", "dumpinfo", "fromweb", - "goodfet30", "goodfet20", "goodfet10", "z1", "mainerase" - ] + "goodfet30", "goodfet20", "goodfet10", "z1", "mainerase" + ] ) except getopt.GetoptError: # print help information and exit: @@ -1755,15 +1755,15 @@ def main(itest=1): bsl.invertTEST = 1 bsl.swapRSTTEST = 1 bsl.telosLatch = 1 - elif o in ("--goodfet10", ): - bsl.invertRST = 1 - bsl.invertTEST = 1 - elif o in ("--goodfet20", ): - bsl.invertRST = 1 - bsl.invertTEST = 1 - elif o in ("--goodfet30", ): - bsl.invertRST = 1 - bsl.invertTEST = 0 + elif o in ("--goodfet10", ): + bsl.invertRST = 1 + bsl.invertTEST = 1 + elif o in ("--goodfet20", ): + bsl.invertRST = 1 + bsl.invertTEST = 1 + elif o in ("--goodfet30", ): + bsl.invertRST = 1 + bsl.invertTEST = 0 elif o in ("--telosb", ): bsl.swapRSTTEST = 1 bsl.telosI2C = 1