diff --git a/.gitignore b/.gitignore index 7286a98ba..d8874dffb 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ *.c128 *.c64 *.cc2538dk +*.srf06-cc26xx *.ev-aducrf101mkxz *.report summary diff --git a/.travis.yml b/.travis.yml index bb3900287..03559d8a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,6 +48,13 @@ before_script: 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 && @@ -115,6 +122,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' - BUILD_TYPE='slip-radio' MAKE_TARGETS='cooja' - BUILD_TYPE='llsec' MAKE_TARGETS='cooja' diff --git a/apps/dhcp/dhcp.c b/apps/dhcp/dhcp.c index 9ac20b102..2c9d35003 100644 --- a/apps/dhcp/dhcp.c +++ b/apps/dhcp/dhcp.c @@ -88,7 +88,7 @@ makestrings(void) uip_getdraddr(&addr); makeaddr(&addr, gateway); - addrptr = resolv_getserver(); + addrptr = uip_nameserver_get(0); if(addrptr != NULL) { makeaddr(addrptr, dnsserver); } @@ -147,7 +147,7 @@ dhcpc_configured(const struct dhcpc_state *s) uip_sethostaddr(&s->ipaddr); uip_setnetmask(&s->netmask); uip_setdraddr(&s->default_router); - resolv_conf(&s->dnsaddr); + uip_nameserver_update(&s->dnsaddr, UIP_NAMESERVER_INFINITE_LIFETIME); set_statustext("Configured."); process_post(PROCESS_CURRENT(), SHOWCONFIG, NULL); } diff --git a/apps/er-coap/Makefile.er-coap b/apps/er-coap/Makefile.er-coap index 096b10e2e..23b70613e 100755 --- a/apps/er-coap/Makefile.er-coap +++ b/apps/er-coap/Makefile.er-coap @@ -1,4 +1,6 @@ -er-coap_src = er-coap.c er-coap-engine.c er-coap-transactions.c er-coap-observe.c er-coap-separate.c er-coap-res-well-known-core.c er-coap-block1.c +er-coap_src = er-coap.c er-coap-engine.c er-coap-transactions.c \ + er-coap-observe.c er-coap-separate.c er-coap-res-well-known-core.c \ + er-coap-block1.c er-coap-observe-client.c # Erbium will implement the REST Engine CFLAGS += -DREST=coap_rest_implementation diff --git a/apps/er-coap/er-coap-engine.c b/apps/er-coap/er-coap-engine.c index 3a7af5e5f..76a230545 100644 --- a/apps/er-coap/er-coap-engine.c +++ b/apps/er-coap/er-coap-engine.c @@ -253,6 +253,16 @@ coap_receive(void) } /* if(ACKed transaction) */ transaction = NULL; + +#if COAP_OBSERVE_CLIENT + /* if observe notification */ + if((message->type == COAP_TYPE_CON || message->type == COAP_TYPE_NON) + && IS_OPTION(message, COAP_OPTION_OBSERVE)) { + PRINTF("Observe [%u]\n", message->observe); + coap_handle_notification(&UIP_IP_BUF->srcipaddr, UIP_UDP_BUF->srcport, + message); + } +#endif /* COAP_OBSERVE_CLIENT */ } /* request or response */ } /* parsed correctly */ diff --git a/apps/er-coap/er-coap-engine.h b/apps/er-coap/er-coap-engine.h index d77d1fa78..c6c6ae676 100644 --- a/apps/er-coap/er-coap-engine.h +++ b/apps/er-coap/er-coap-engine.h @@ -44,6 +44,7 @@ #include "er-coap-transactions.h" #include "er-coap-observe.h" #include "er-coap-separate.h" +#include "er-coap-observe-client.h" #define SERVER_LISTEN_PORT UIP_HTONS(COAP_SERVER_PORT) diff --git a/apps/er-coap/er-coap-observe-client.c b/apps/er-coap/er-coap-observe-client.c new file mode 100644 index 000000000..21863200e --- /dev/null +++ b/apps/er-coap/er-coap-observe-client.c @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2014, Daniele Alessandrelli. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this 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 + * Extension to Erbium for enabling CoAP observe clients + * \author + * Daniele Alessandrelli + */ + +#include +#include + +#include "er-coap.h" +#include "er-coap-observe-client.h" + +/* Compile this code only if client-side support for CoAP Observe is required */ +#if COAP_OBSERVE_CLIENT + +#define DEBUG 1 +#if DEBUG +#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 + +MEMB(obs_subjects_memb, coap_observee_t, COAP_MAX_OBSERVEES); +LIST(obs_subjects_list); + +/*----------------------------------------------------------------------------*/ +static size_t +get_token(void *packet, const uint8_t **token) +{ + coap_packet_t *const coap_pkt = (coap_packet_t *)packet; + + *token = coap_pkt->token; + + return coap_pkt->token_len; +} +/*----------------------------------------------------------------------------*/ +static int +set_token(void *packet, const uint8_t *token, size_t token_len) +{ + coap_packet_t *const coap_pkt = (coap_packet_t *)packet; + + coap_pkt->token_len = MIN(COAP_TOKEN_LEN, token_len); + memcpy(coap_pkt->token, token, coap_pkt->token_len); + + return coap_pkt->token_len; +} +/*----------------------------------------------------------------------------*/ +coap_observee_t * +coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port, + const uint8_t *token, size_t token_len, const char *url, + notification_callback_t notification_callback, + void *data) +{ + coap_observee_t *o; + + /* Remove existing observe relationship, if any. */ + coap_obs_remove_observee_by_url(addr, port, url); + o = memb_alloc(&obs_subjects_memb); + if(o) { + o->url = url; + uip_ipaddr_copy(&o->addr, addr); + o->port = port; + o->token_len = token_len; + memcpy(o->token, token, token_len); + /* o->last_mid = 0; */ + o->notification_callback = notification_callback; + o->data = data; + /* stimer_set(&o->refresh_timer, COAP_OBSERVING_REFRESH_INTERVAL); */ + PRINTF("Adding obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0], + o->token[1]); + list_add(obs_subjects_list, o); + } + + return o; +} +/*----------------------------------------------------------------------------*/ +void +coap_obs_remove_observee(coap_observee_t *o) +{ + PRINTF("Removing obs_subject for /%s [0x%02X%02X]\n", o->url, o->token[0], + o->token[1]); + memb_free(&obs_subjects_memb, o); + list_remove(obs_subjects_list, o); +} +/*----------------------------------------------------------------------------*/ +coap_observee_t * +coap_get_obs_subject_by_token(const uint8_t *token, size_t token_len) +{ + coap_observee_t *obs = NULL; + + for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs; + obs = obs->next) { + PRINTF("Looking for token 0x%02X%02X\n", token[0], token[1]); + if(obs->token_len == token_len + && memcmp(obs->token, token, token_len) == 0) { + return obs; + } + } + + return NULL; +} +/*----------------------------------------------------------------------------*/ +int +coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port, + uint8_t *token, size_t token_len) +{ + int removed = 0; + coap_observee_t *obs = NULL; + + for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs; + obs = obs->next) { + PRINTF("Remove check Token 0x%02X%02X\n", token[0], token[1]); + if(uip_ipaddr_cmp(&obs->addr, addr) + && obs->port == port + && obs->token_len == token_len + && memcmp(obs->token, token, token_len) == 0) { + coap_obs_remove_observee(obs); + removed++; + } + } + return removed; +} +/*----------------------------------------------------------------------------*/ +int +coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port, + const char *url) +{ + int removed = 0; + coap_observee_t *obs = NULL; + + for(obs = (coap_observee_t *)list_head(obs_subjects_list); obs; + obs = obs->next) { + PRINTF("Remove check URL %s\n", url); + if(uip_ipaddr_cmp(&obs->addr, addr) + && obs->port == port + && (obs->url == url || memcmp(obs->url, url, strlen(obs->url)) == 0)) { + coap_obs_remove_observee(obs); + removed++; + } + } + return removed; +} +/*----------------------------------------------------------------------------*/ +static void +simple_reply(coap_message_type_t type, uip_ip6addr_t *addr, uint16_t port, + coap_packet_t *notification) +{ + static coap_packet_t response[1]; + size_t len; + + coap_init_message(response, type, NO_ERROR, notification->mid); + len = coap_serialize_message(response, uip_appdata); + coap_send_message(addr, port, uip_appdata, len); +} +/*----------------------------------------------------------------------------*/ +static coap_notification_flag_t +classify_notification(void *response, int first) +{ + coap_packet_t *pkt; + + pkt = (coap_packet_t *)response; + if(!pkt) { + PRINTF("no response\n"); + return NO_REPLY_FROM_SERVER; + } + PRINTF("server replied\n"); + if(!IS_RESPONSE_CODE_2_XX(pkt)) { + PRINTF("error response code\n"); + return ERROR_RESPONSE_CODE; + } + if(!IS_OPTION(pkt, COAP_OPTION_OBSERVE)) { + PRINTF("server does not support observe\n"); + return OBSERVE_NOT_SUPPORTED; + } + if(first) { + return OBSERVE_OK; + } + return NOTIFICATION_OK; +} +/*----------------------------------------------------------------------------*/ +void +coap_handle_notification(uip_ipaddr_t *addr, uint16_t port, + coap_packet_t *notification) +{ + coap_packet_t *pkt; + const uint8_t *token; + int token_len; + coap_observee_t *obs; + coap_notification_flag_t flag; + uint32_t observe; + + PRINTF("coap_handle_notification()\n"); + pkt = (coap_packet_t *)notification; + token_len = get_token(pkt, &token); + PRINTF("Getting token\n"); + if(0 == token_len) { + PRINTF("Error while handling coap observe notification: " + "no token in message\n"); + return; + } + PRINTF("Getting observee info\n"); + obs = coap_get_obs_subject_by_token(token, token_len); + if(NULL == obs) { + PRINTF("Error while handling coap observe notification: " + "no matching token found\n"); + simple_reply(COAP_TYPE_RST, addr, port, notification); + return; + } + if(notification->type == COAP_TYPE_CON) { + simple_reply(COAP_TYPE_ACK, addr, port, notification); + } + if(obs->notification_callback != NULL) { + flag = classify_notification(notification, 0); + /* TODO: the following mechanism for discarding duplicates is too trivial */ + /* refer to Observe RFC for a better solution */ + if(flag == NOTIFICATION_OK) { + coap_get_header_observe(notification, &observe); + if(observe == obs->last_observe) { + PRINTF("Discarding duplicate\n"); + return; + } + obs->last_observe = observe; + } + obs->notification_callback(obs, notification, flag); + } +} +/*----------------------------------------------------------------------------*/ +static void +handle_obs_registration_response(void *data, void *response) +{ + coap_observee_t *obs; + notification_callback_t notification_callback; + coap_notification_flag_t flag; + + PRINTF("handle_obs_registration_response(): "); + obs = (coap_observee_t *)data; + notification_callback = obs->notification_callback; + flag = classify_notification(response, 1); + if(notification_callback) { + notification_callback(obs, response, flag); + } + if(flag != OBSERVE_OK) { + coap_obs_remove_observee(obs); + } +} +/*----------------------------------------------------------------------------*/ +uint8_t +coap_generate_token(uint8_t **token_ptr) +{ + static uint8_t token = 0; + + token++; + /* FIXME: we should check that this token is not already used */ + *token_ptr = (uint8_t *)&token; + return sizeof(token); +} +/*----------------------------------------------------------------------------*/ +coap_observee_t * +coap_obs_request_registration(uip_ipaddr_t *addr, uint16_t port, char *uri, + notification_callback_t notification_callback, + void *data) +{ + coap_packet_t request[1]; + coap_transaction_t *t; + uint8_t *token; + uint8_t token_len; + coap_observee_t *obs; + + obs = NULL; + coap_init_message(request, COAP_TYPE_CON, COAP_GET, coap_get_mid()); + coap_set_header_uri_path(request, uri); + coap_set_header_observe(request, 0); + token_len = coap_generate_token(&token); + set_token(request, token, token_len); + t = coap_new_transaction(request->mid, addr, port); + if(t) { + obs = coap_obs_add_observee(addr, port, (uint8_t *)token, token_len, uri, + notification_callback, data); + if(obs) { + t->callback = handle_obs_registration_response; + t->callback_data = obs; + t->packet_len = coap_serialize_message(request, t->packet); + coap_send_transaction(t); + } else { + PRINTF("Could not allocate obs_subject resource buffer"); + coap_clear_transaction(t); + } + } else { + PRINTF("Could not allocate transaction buffer"); + } + return obs; +} +#endif /* COAP_OBSERVE_CLIENT */ diff --git a/apps/er-coap/er-coap-observe-client.h b/apps/er-coap/er-coap-observe-client.h new file mode 100644 index 000000000..d0ece32c0 --- /dev/null +++ b/apps/er-coap/er-coap-observe-client.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2014, Daniele Alessandrelli. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this 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 + * Extension to Erbium for enabling CoAP observe clients + * \author + * Daniele Alessandrelli + */ + +#ifndef COAP_OBSERVING_CLIENT_H_ +#define COAP_OBSERVING_CLIENT_H_ + +#include "er-coap.h" +#include "er-coap-transactions.h" + +#ifndef COAP_OBSERVE_CLIENT +#define COAP_OBSERVE_CLIENT 0 +#endif + +#ifdef COAP_CONF_MAX_OBSERVEES +#define COAP_MAX_OBSERVEES COAP_CONF_MAX_OBSERVEES +#else +#define COAP_MAX_OBSERVEES 4 +#endif /* COAP_CONF_MAX_OBSERVEES */ + +#if COAP_MAX_OPEN_TRANSACTIONS < COAP_MAX_OBSERVEES +#warning "COAP_MAX_OPEN_TRANSACTIONS smaller than COAP_MAX_OBSERVEES: " \ + "this may be a problem" +#endif + +#define IS_RESPONSE_CODE_2_XX(message) (64 < message->code \ + && message->code < 128) + +/*----------------------------------------------------------------------------*/ +typedef enum { + OBSERVE_OK, + NOTIFICATION_OK, + OBSERVE_NOT_SUPPORTED, + ERROR_RESPONSE_CODE, + NO_REPLY_FROM_SERVER, +} coap_notification_flag_t; + +/*----------------------------------------------------------------------------*/ +typedef struct coap_observee_s coap_observee_t; + +typedef void (*notification_callback_t)(coap_observee_t *subject, + void *notification, + coap_notification_flag_t); + +struct coap_observee_s { + coap_observee_t *next; /* for LIST */ + uip_ipaddr_t addr; + uint16_t port; + const char *url; + uint8_t token_len; + uint8_t token[COAP_TOKEN_LEN]; + void *data; /* generic pointer for storing user data */ + notification_callback_t notification_callback; + uint32_t last_observe; +}; + +/*----------------------------------------------------------------------------*/ +coap_observee_t *coap_obs_add_observee(uip_ipaddr_t *addr, uint16_t port, + const uint8_t *token, size_t token_len, + const char *url, + notification_callback_t + notification_callback, void *data); + +void coap_obs_remove_observee(coap_observee_t *o); + +coap_observee_t *coap_obs_get_observee_by_token(const uint8_t *token, + size_t token_len); + +int coap_obs_remove_observee_by_token(uip_ipaddr_t *addr, uint16_t port, + uint8_t *token, size_t token_len); + +int coap_obs_remove_observee_by_url(uip_ipaddr_t *addr, uint16_t port, + const char *url); + +void coap_handle_notification(uip_ipaddr_t *, uint16_t port, + coap_packet_t *notification); + +coap_observee_t *coap_obs_request_registration(uip_ipaddr_t *addr, + uint16_t port, char *uri, + notification_callback_t + notification_callback, + void *data); +/* TODO: this function may be moved to er-coap.c */ +uint8_t coap_generate_token(uint8_t **token_ptr); + +#endif /* COAP_OBSERVING_CLIENT_H_ */ diff --git a/apps/mqtt/Makefile.mqtt b/apps/mqtt/Makefile.mqtt new file mode 100644 index 000000000..06d7bd5ab --- /dev/null +++ b/apps/mqtt/Makefile.mqtt @@ -0,0 +1 @@ +mqtt_src = mqtt.c diff --git a/apps/mqtt/mqtt.c b/apps/mqtt/mqtt.c new file mode 100644 index 000000000..112c584cb --- /dev/null +++ b/apps/mqtt/mqtt.c @@ -0,0 +1,1484 @@ +/* + * 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 mqtt-engine + * @{ + */ +/** + * \file + * Implementation of the Contiki MQTT engine + * + * \author + * Texas Instruments + */ +/*---------------------------------------------------------------------------*/ +#include "mqtt.h" +#include "contiki.h" +#include "contiki-net.h" +#include "contiki-lib.h" +#include "lib/random.h" +#include "sys/ctimer.h" +#include "sys/etimer.h" +#include "sys/pt.h" +#include "net/rpl/rpl.h" +#include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" +#include "dev/leds.h" + +#include "tcp-socket.h" + +#include "lib/assert.h" +#include "lib/list.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) PRINTF(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +typedef enum { + MQTT_FHDR_MSG_TYPE_CONNECT = 0x10, + MQTT_FHDR_MSG_TYPE_CONNACK = 0x20, + MQTT_FHDR_MSG_TYPE_PUBLISH = 0x30, + MQTT_FHDR_MSG_TYPE_PUBACK = 0x40, + MQTT_FHDR_MSG_TYPE_PUBREC = 0x50, + MQTT_FHDR_MSG_TYPE_PUBREL = 0x60, + MQTT_FHDR_MSG_TYPE_PUBCOMP = 0x70, + MQTT_FHDR_MSG_TYPE_SUBSCRIBE = 0x80, + MQTT_FHDR_MSG_TYPE_SUBACK = 0x90, + MQTT_FHDR_MSG_TYPE_UNSUBSCRIBE = 0xA0, + MQTT_FHDR_MSG_TYPE_UNSUBACK = 0xB0, + MQTT_FHDR_MSG_TYPE_PINGREQ = 0xC0, + MQTT_FHDR_MSG_TYPE_PINGRESP = 0xD0, + MQTT_FHDR_MSG_TYPE_DISCONNECT = 0xE0, + + MQTT_FHDR_DUP_FLAG = 0x08, + + MQTT_FHDR_QOS_LEVEL_0 = 0x00, + MQTT_FHDR_QOS_LEVEL_1 = 0x02, + MQTT_FHDR_QOS_LEVEL_2 = 0x04, + + MQTT_FHDR_RETAIN_FLAG = 0x01, +} mqtt_fhdr_fields_t; +/*---------------------------------------------------------------------------*/ +typedef enum { + MQTT_VHDR_USERNAME_FLAG = 0x80, + MQTT_VHDR_PASSWORD_FLAG = 0x40, + + MQTT_VHDR_WILL_RETAIN_FLAG = 0x20, + MQTT_VHDR_WILL_QOS_LEVEL_0 = 0x00, + MQTT_VHDR_WILL_QOS_LEVEL_1 = 0x08, + MQTT_VHDR_WILL_QOS_LEVEL_2 = 0x10, + + MQTT_VHDR_WILL_FLAG = 0x04, + MQTT_VHDR_CLEAN_SESSION_FLAG = 0x02, +} mqtt_vhdr_conn_fields_t; +/*---------------------------------------------------------------------------*/ +typedef enum { + MQTT_VHDR_CONN_ACCEPTED, + MQTT_VHDR_CONN_REJECTED_PROTOCOL, + MQTT_VHDR_CONN_REJECTED_IDENTIFIER, + MQTT_VHDR_CONN_REJECTED_UNAVAILABLE, + MQTT_VHDR_CONN_REJECTED_BAD_USER_PASS, + MQTT_VHDR_CONN_REJECTED_UNAUTHORIZED, +} mqtt_vhdr_connack_fields_t; +/*---------------------------------------------------------------------------*/ +#define MQTT_CONNECT_VHDR_FLAGS_SIZE 12 + +#define MQTT_STRING_LEN_SIZE 2 +#define MQTT_MID_SIZE 2 +#define MQTT_QOS_SIZE 1 +/*---------------------------------------------------------------------------*/ +#define RESPONSE_WAIT_TIMEOUT (CLOCK_SECOND * 10) +/*---------------------------------------------------------------------------*/ +#define INCREMENT_MID(conn) (conn)->mid_counter += 2 +#define MQTT_STRING_LENGTH(s) (((s)->length) == 0 ? 0 : (MQTT_STRING_LEN_SIZE + (s)->length)) +/*---------------------------------------------------------------------------*/ +/* Protothread send macros */ +#define PT_MQTT_WRITE_BYTES(conn, data, len) \ + while(write_bytes(conn, data, len)) { \ + PT_WAIT_UNTIL(pt, (conn)->out_buffer_sent); \ + } + +#define PT_MQTT_WRITE_BYTE(conn, data) \ + while(write_byte(conn, data)) { \ + PT_WAIT_UNTIL(pt, (conn)->out_buffer_sent); \ + } +/*---------------------------------------------------------------------------*/ +/* + * Sends the continue send event and wait for that event. + * + * The reason we cannot use PROCESS_PAUSE() is since we would risk loosing any + * events posted during the sending process. + */ +#define PT_MQTT_WAIT_SEND() \ + do { \ + process_post(PROCESS_CURRENT(), mqtt_continue_send_event, NULL); \ + PROCESS_WAIT_EVENT(); \ + if(ev == mqtt_abort_now_event) { \ + conn->state = MQTT_CONN_STATE_ABORT_IMMEDIATE; \ + PT_EXIT(&conn->out_proto_thread); \ + process_post(PROCESS_CURRENT(), ev, data); \ + } else if(ev >= mqtt_event_min && ev <= mqtt_event_max) { \ + process_post(PROCESS_CURRENT(), ev, data); \ + } \ + } while(0) +/*---------------------------------------------------------------------------*/ +static process_event_t mqtt_do_connect_tcp_event; +static process_event_t mqtt_do_connect_mqtt_event; +static process_event_t mqtt_do_disconnect_mqtt_event; +static process_event_t mqtt_do_subscribe_event; +static process_event_t mqtt_do_unsubscribe_event; +static process_event_t mqtt_do_publish_event; +static process_event_t mqtt_do_pingreq_event; +static process_event_t mqtt_continue_send_event; +static process_event_t mqtt_abort_now_event; +process_event_t mqtt_update_event; + +/* + * Min and Max event numbers we want to acknowledge while we're in the process + * of doing something else. continue_send does not count, therefore must be + * allocated last + */ +static process_event_t mqtt_event_min; +static process_event_t mqtt_event_max; +/*---------------------------------------------------------------------------*/ +/* Prototypes */ +static int +tcp_input(struct tcp_socket *s, void *ptr, const uint8_t *input_data_ptr, + int input_data_len); + +static void tcp_event(struct tcp_socket *s, void *ptr, + tcp_socket_event_t event); + +static void reset_packet(struct mqtt_in_packet *packet); +/*---------------------------------------------------------------------------*/ +LIST(mqtt_conn_list); +/*---------------------------------------------------------------------------*/ +PROCESS(mqtt_process, "MQTT process"); +/*---------------------------------------------------------------------------*/ +static void +call_event(struct mqtt_connection *conn, + mqtt_event_t event, + void *data) +{ + conn->event_callback(conn, event, data); + process_post(conn->app_process, mqtt_update_event, NULL); +} +/*---------------------------------------------------------------------------*/ +static void +reset_defaults(struct mqtt_connection *conn) +{ + conn->mid_counter = 1; + PT_INIT(&conn->out_proto_thread); + conn->waiting_for_pingresp = 0; + + reset_packet(&conn->in_packet); + conn->out_buffer_sent = 0; +} +/*---------------------------------------------------------------------------*/ +static void +abort_connection(struct mqtt_connection *conn) +{ + conn->out_buffer_ptr = conn->out_buffer; + conn->out_queue_full = 0; + + /* Reset outgoing packet */ + memset(&conn->out_packet, 0, sizeof(conn->out_packet)); + + tcp_socket_close(&conn->socket); + tcp_socket_unregister(&conn->socket); + + memset(&conn->socket, 0, sizeof(conn->socket)); + + conn->state = MQTT_CONN_STATE_NOT_CONNECTED; +} +/*---------------------------------------------------------------------------*/ +static void +connect_tcp(struct mqtt_connection *conn) +{ + conn->state = MQTT_CONN_STATE_TCP_CONNECTING; + + reset_defaults(conn); + tcp_socket_register(&(conn->socket), + conn, + conn->in_buffer, + MQTT_TCP_INPUT_BUFF_SIZE, + conn->out_buffer, + MQTT_TCP_OUTPUT_BUFF_SIZE, + tcp_input, + tcp_event); + tcp_socket_connect(&(conn->socket), &(conn->server_ip), conn->server_port); +} +/*---------------------------------------------------------------------------*/ +static void +disconnect_tcp(struct mqtt_connection *conn) +{ + conn->state = MQTT_CONN_STATE_DISCONNECTING; + tcp_socket_close(&(conn->socket)); + tcp_socket_unregister(&conn->socket); + + memset(&conn->socket, 0, sizeof(conn->socket)); +} +/*---------------------------------------------------------------------------*/ +static void +send_out_buffer(struct mqtt_connection *conn) +{ + if(conn->out_buffer_ptr - conn->out_buffer == 0) { + conn->out_buffer_sent = 1; + return; + } + conn->out_buffer_sent = 0; + + DBG("MQTT - (send_out_buffer) Space used in buffer: %i\n", + conn->out_buffer_ptr - conn->out_buffer); + + tcp_socket_send(&conn->socket, conn->out_buffer, + conn->out_buffer_ptr - conn->out_buffer); +} +/*---------------------------------------------------------------------------*/ +static void +string_to_mqtt_string(struct mqtt_string *mqtt_string, char *string) +{ + if(mqtt_string == NULL) { + return; + } + mqtt_string->string = string; + + if(string != NULL) { + mqtt_string->length = strlen(string); + } else { + mqtt_string->length = 0; + } +} +/*---------------------------------------------------------------------------*/ +static int +write_byte(struct mqtt_connection *conn, uint8_t data) +{ + DBG("MQTT - (write_byte) buff_size: %i write: '%02X'\n", + &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr, + data); + + if(&conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr == 0) { + send_out_buffer(conn); + return 1; + } + + *conn->out_buffer_ptr = data; + conn->out_buffer_ptr++; + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +write_bytes(struct mqtt_connection *conn, uint8_t *data, uint16_t len) +{ + uint16_t write_bytes; + write_bytes = + MIN(&conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr, + len - conn->out_write_pos); + + memcpy(conn->out_buffer_ptr, &data[conn->out_write_pos], write_bytes); + conn->out_write_pos += write_bytes; + conn->out_buffer_ptr += write_bytes; + + DBG("MQTT - (write_bytes) len: %u write_pos: %lu\n", len, + conn->out_write_pos); + + if(len - conn->out_write_pos == 0) { + conn->out_write_pos = 0; + return 0; + } else { + send_out_buffer(conn); + return len - conn->out_write_pos; + } +} +/*---------------------------------------------------------------------------*/ +static void +encode_remaining_length(uint8_t *remaining_length, + uint8_t *remaining_length_bytes, + uint32_t length) +{ + uint8_t digit; + + DBG("MQTT - Encoding length %lu\n", length); + + *remaining_length_bytes = 0; + do { + digit = length % 128; + length = length / 128; + if(length > 0) { + digit = digit | 0x80; + } + + remaining_length[*remaining_length_bytes] = digit; + (*remaining_length_bytes)++; + DBG("MQTT - Encode len digit '%u' length '%lu'\n", digit, length); + } while(length > 0 && *remaining_length_bytes < 5); + DBG("MQTT - remaining_length_bytes %u\n", *remaining_length_bytes); +} +/*---------------------------------------------------------------------------*/ +static void +keep_alive_callback(void *ptr) +{ + struct mqtt_connection *conn = ptr; + + DBG("MQTT - (keep_alive_callback) Called!\n"); + + /* The flag is set when the PINGREQ has been sent */ + if(conn->waiting_for_pingresp) { + PRINTF("MQTT - Disconnect due to no PINGRESP from broker.\n"); + disconnect_tcp(conn); + return; + } + + process_post(&mqtt_process, mqtt_do_pingreq_event, conn); +} +/*---------------------------------------------------------------------------*/ +static void +reset_packet(struct mqtt_in_packet *packet) +{ + memset(packet, 0, sizeof(struct mqtt_in_packet)); + packet->remaining_multiplier = 1; +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(connect_pt(struct pt *pt, struct mqtt_connection *conn)) +{ + PT_BEGIN(pt); + + DBG("MQTT - Sending CONNECT message...\n"); + + /* Set up FHDR */ + conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_CONNECT; + conn->out_packet.remaining_length = 0; + conn->out_packet.remaining_length += MQTT_CONNECT_VHDR_FLAGS_SIZE; + conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->client_id); + conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.username); + conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.password); + conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.topic); + conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.message); + encode_remaining_length(conn->out_packet.remaining_length_enc, + &conn->out_packet.remaining_length_enc_bytes, + conn->out_packet.remaining_length); + if(conn->out_packet.remaining_length_enc_bytes > 4) { + call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); + PRINTF("MQTT - Error, remaining length > 4 bytes\n"); + PT_EXIT(pt); + } + + /* Write Fixed Header */ + PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); + PT_MQTT_WRITE_BYTES(conn, + conn->out_packet.remaining_length_enc, + conn->out_packet.remaining_length_enc_bytes); + PT_MQTT_WRITE_BYTE(conn, 0); + PT_MQTT_WRITE_BYTE(conn, 6); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)MQTT_PROTOCOL_NAME, 6); + PT_MQTT_WRITE_BYTE(conn, MQTT_PROTOCOL_VERSION); + PT_MQTT_WRITE_BYTE(conn, conn->connect_vhdr_flags); + PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive >> 8)); + PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive & 0x00FF)); + PT_MQTT_WRITE_BYTE(conn, conn->client_id.length << 8); + PT_MQTT_WRITE_BYTE(conn, conn->client_id.length & 0x00FF); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->client_id.string, + conn->client_id.length); + if(conn->connect_vhdr_flags & MQTT_VHDR_WILL_FLAG) { + PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length << 8); + PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length & 0x00FF); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->will.topic.string, + conn->will.topic.length); + PT_MQTT_WRITE_BYTE(conn, conn->will.message.length << 8); + PT_MQTT_WRITE_BYTE(conn, conn->will.message.length & 0x00FF); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->will.message.string, + conn->will.message.length); + DBG("MQTT - Setting will topic to '%s' %u bytes and message to '%s' %u bytes\n", + conn->will.topic.string, + conn->will.topic.length, + conn->will.message.string, + conn->will.message.length); + } + if(conn->connect_vhdr_flags & MQTT_VHDR_USERNAME_FLAG) { + PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length << 8); + PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length & 0x00FF); + PT_MQTT_WRITE_BYTES(conn, + (uint8_t *)conn->credentials.username.string, + conn->credentials.username.length); + } + if(conn->connect_vhdr_flags & MQTT_VHDR_PASSWORD_FLAG) { + PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length << 8); + PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length & 0x00FF); + PT_MQTT_WRITE_BYTES(conn, + (uint8_t *)conn->credentials.password.string, + conn->credentials.password.length); + } + + /* Send out buffer */ + send_out_buffer(conn); + conn->state = MQTT_CONN_STATE_CONNECTING_TO_BROKER; + + timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); + + /* Wait for CONNACK */ + reset_packet(&conn->in_packet); + PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK || + timer_expired(&conn->t)); + if(timer_expired(&conn->t)) { + DBG("Timeout waiting for CONNACK\n"); + /* We stick to the letter of the spec here: Tear the connection down */ + mqtt_disconnect(conn); + } + reset_packet(&conn->in_packet); + + DBG("MQTT - Done sending CONNECT\n"); + +#if DEBUG_MQTT == 1 + DBG("MQTT - CONNECT message sent: \n"); + uint16_t i; + for(i = 0; i < (conn->out_buffer_ptr - conn->out_buffer); i++) { + DBG("%02X ", conn->out_buffer[i]); + } + DBG("\n"); +#endif + + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(disconnect_pt(struct pt *pt, struct mqtt_connection *conn)) +{ + PT_BEGIN(pt); + + PT_MQTT_WRITE_BYTE(conn, MQTT_FHDR_MSG_TYPE_DISCONNECT); + PT_MQTT_WRITE_BYTE(conn, 0); + + send_out_buffer(conn); + + /* + * Wait a couple of seconds for a TCP ACK. We don't really need the ACK, + * we do want the TCP/IP stack to actually send this disconnect before we + * tear down the session. + */ + timer_set(&conn->t, (CLOCK_SECOND * 2)); + PT_WAIT_UNTIL(pt, conn->out_buffer_sent || timer_expired(&conn->t)); + + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(subscribe_pt(struct pt *pt, struct mqtt_connection *conn)) +{ + PT_BEGIN(pt); + + DBG("MQTT - Sending subscribe message! topic %s topic_length %i\n", + conn->out_packet.topic, + conn->out_packet.topic_length); + DBG("MQTT - Buffer space is %i \n", + &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr); + + /* Set up FHDR */ + conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_SUBSCRIBE | MQTT_FHDR_QOS_LEVEL_1; + conn->out_packet.remaining_length = MQTT_MID_SIZE + + MQTT_STRING_LEN_SIZE + + conn->out_packet.topic_length + + MQTT_QOS_SIZE; + encode_remaining_length(conn->out_packet.remaining_length_enc, + &conn->out_packet.remaining_length_enc_bytes, + conn->out_packet.remaining_length); + if(conn->out_packet.remaining_length_enc_bytes > 4) { + call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); + PRINTF("MQTT - Error, remaining length > 4 bytes\n"); + PT_EXIT(pt); + } + + /* Write Fixed Header */ + PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); + PT_MQTT_WRITE_BYTES(conn, + conn->out_packet.remaining_length_enc, + conn->out_packet.remaining_length_enc_bytes); + /* Write Variable Header */ + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8)); + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF)); + /* Write Payload */ + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8)); + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length & 0x00FF)); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.topic, + conn->out_packet.topic_length); + PT_MQTT_WRITE_BYTE(conn, conn->out_packet.qos); + + /* Send out buffer */ + send_out_buffer(conn); + timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); + + /* Wait for SUBACK. */ + reset_packet(&conn->in_packet); + PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK || + timer_expired(&conn->t)); + + if(timer_expired(&conn->t)) { + DBG("Timeout waiting for SUBACK\n"); + } + reset_packet(&conn->in_packet); + + /* This is clear after the entire transaction is complete */ + conn->out_queue_full = 0; + + DBG("MQTT - Done in send_subscribe!\n"); + + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(unsubscribe_pt(struct pt *pt, struct mqtt_connection *conn)) +{ + PT_BEGIN(pt); + + DBG("MQTT - Sending unsubscribe message on topic %s topic_length %i\n", + conn->out_packet.topic, + conn->out_packet.topic_length); + DBG("MQTT - Buffer space is %i \n", + &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr); + + /* Set up FHDR */ + conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_UNSUBSCRIBE | + MQTT_FHDR_QOS_LEVEL_1; + conn->out_packet.remaining_length = MQTT_MID_SIZE + + MQTT_STRING_LEN_SIZE + + conn->out_packet.topic_length; + encode_remaining_length(conn->out_packet.remaining_length_enc, + &conn->out_packet.remaining_length_enc_bytes, + conn->out_packet.remaining_length); + if(conn->out_packet.remaining_length_enc_bytes > 4) { + call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); + PRINTF("MQTT - Error, remaining length > 4 bytes\n"); + PT_EXIT(pt); + } + + /* Write Fixed Header */ + PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.remaining_length_enc, + conn->out_packet.remaining_length_enc_bytes); + /* Write Variable Header */ + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8)); + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF)); + /* Write Payload */ + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8)); + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length & 0x00FF)); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.topic, + conn->out_packet.topic_length); + + /* Send out buffer */ + send_out_buffer(conn); + timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); + + /* Wait for UNSUBACK */ + reset_packet(&conn->in_packet); + PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK || + timer_expired(&conn->t)); + + if(timer_expired(&conn->t)) { + DBG("Timeout waiting for UNSUBACK\n"); + } + + reset_packet(&conn->in_packet); + + /* This is clear after the entire transaction is complete */ + conn->out_queue_full = 0; + + DBG("MQTT - Done writing subscribe message to out buffer!\n"); + + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(publish_pt(struct pt *pt, struct mqtt_connection *conn)) +{ + PT_BEGIN(pt); + + DBG("MQTT - Sending publish message! topic %s topic_length %i\n", + conn->out_packet.topic, + conn->out_packet.topic_length); + DBG("MQTT - Buffer space is %i \n", + &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr); + + /* Set up FHDR */ + conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_PUBLISH | + conn->out_packet.qos << 1; + if(conn->out_packet.retain == MQTT_RETAIN_ON) { + conn->out_packet.fhdr |= MQTT_FHDR_RETAIN_FLAG; + } + conn->out_packet.remaining_length = MQTT_STRING_LEN_SIZE + + conn->out_packet.topic_length + + conn->out_packet.payload_size; + if(conn->out_packet.qos > MQTT_QOS_LEVEL_0) { + conn->out_packet.remaining_length += MQTT_MID_SIZE; + } + encode_remaining_length(conn->out_packet.remaining_length_enc, + &conn->out_packet.remaining_length_enc_bytes, + conn->out_packet.remaining_length); + if(conn->out_packet.remaining_length_enc_bytes > 4) { + call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); + PRINTF("MQTT - Error, remaining length > 4 bytes\n"); + PT_EXIT(pt); + } + + /* Write Fixed Header */ + PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.remaining_length_enc, + conn->out_packet.remaining_length_enc_bytes); + /* Write Variable Header */ + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8)); + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length & 0x00FF)); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.topic, + conn->out_packet.topic_length); + if(conn->out_packet.qos > MQTT_QOS_LEVEL_0) { + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8)); + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF)); + } + /* Write Payload */ + PT_MQTT_WRITE_BYTES(conn, + conn->out_packet.payload, + conn->out_packet.payload_size); + + send_out_buffer(conn); + timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); + + /* + * If QoS is zero then wait until the message has been sent, since there is + * no ACK to wait for. + * + * Also notify the app will not be notified via PUBACK or PUBCOMP + */ + if(conn->out_packet.qos == 0) { + process_post(conn->app_process, mqtt_update_event, NULL); + } else if(conn->out_packet.qos == 1) { + /* Wait for PUBACK */ + reset_packet(&conn->in_packet); + PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK || + timer_expired(&conn->t)); + if(timer_expired(&conn->t)) { + DBG("Timeout waiting for PUBACK\n"); + } + if(conn->in_packet.mid != conn->out_packet.mid) { + DBG("MQTT - Warning, got PUBACK with none matching MID. Currently there " + "is no support for several concurrent PUBLISH messages.\n"); + } + } else if(conn->out_packet.qos == 2) { + DBG("MQTT - QoS not implemented yet.\n"); + /* Should wait for PUBREC, send PUBREL and then wait for PUBCOMP */ + } + + reset_packet(&conn->in_packet); + + /* This is clear after the entire transaction is complete */ + conn->out_queue_full = 0; + + DBG("MQTT - Publish Enqueued\n"); + + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(pingreq_pt(struct pt *pt, struct mqtt_connection *conn)) +{ + PT_BEGIN(pt); + + DBG("MQTT - Sending PINGREQ\n"); + + /* Write Fixed Header */ + PT_MQTT_WRITE_BYTE(conn, MQTT_FHDR_MSG_TYPE_PINGREQ); + PT_MQTT_WRITE_BYTE(conn, 0); + + send_out_buffer(conn); + + /* Start timeout for reply. */ + conn->waiting_for_pingresp = 1; + + /* Wait for PINGRESP or timeout */ + reset_packet(&conn->in_packet); + timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); + + PT_WAIT_UNTIL(pt, conn->in_packet.packet_received || timer_expired(&conn->t)); + + reset_packet(&conn->in_packet); + + conn->waiting_for_pingresp = 0; + + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +static void +handle_connack(struct mqtt_connection *conn) +{ + DBG("MQTT - Got CONNACK\n"); + + if(conn->in_packet.payload[1] != 0) { + PRINTF("MQTT - Connection refused with Return Code %i\n", + conn->in_packet.payload[1]); + call_event(conn, + MQTT_EVENT_CONNECTION_REFUSED_ERROR, + &conn->in_packet.payload[1]); + } + + conn->out_packet.qos_state = MQTT_QOS_STATE_GOT_ACK; + + ctimer_set(&conn->keep_alive_timer, conn->keep_alive * CLOCK_SECOND, + keep_alive_callback, conn); + + /* Always reset packet before callback since it might be used directly */ + conn->state = MQTT_CONN_STATE_CONNECTED_TO_BROKER; + call_event(conn, MQTT_EVENT_CONNECTED, NULL); +} +/*---------------------------------------------------------------------------*/ +static void +handle_pingresp(struct mqtt_connection *conn) +{ + DBG("MQTT - Got RINGRESP\n"); +} +/*---------------------------------------------------------------------------*/ +static void +handle_suback(struct mqtt_connection *conn) +{ + struct mqtt_suback_event suback_event; + + DBG("MQTT - Got SUBACK\n"); + + /* Only accept SUBACKS with X topic QoS response, assume 1 */ + if(conn->in_packet.remaining_length > MQTT_MID_SIZE + + MQTT_MAX_TOPICS_PER_SUBSCRIBE * MQTT_QOS_SIZE) { + DBG("MQTT - Error, SUBACK with > 1 topic, not supported.\n"); + } + + conn->out_packet.qos_state = MQTT_QOS_STATE_GOT_ACK; + + suback_event.mid = (conn->in_packet.payload[0] << 8) | + (conn->in_packet.payload[1]); + suback_event.qos_level = conn->in_packet.payload[2]; + conn->in_packet.mid = suback_event.mid; + + if(conn->in_packet.mid != conn->out_packet.mid) { + DBG("MQTT - Warning, got SUBACK with none matching MID. Currently there is" + "no support for several concurrent SUBSCRIBE messages.\n"); + } + + /* Always reset packet before callback since it might be used directly */ + call_event(conn, MQTT_EVENT_SUBACK, &suback_event); +} +/*---------------------------------------------------------------------------*/ +static void +handle_unsuback(struct mqtt_connection *conn) +{ + DBG("MQTT - Got UNSUBACK\n"); + + conn->out_packet.qos_state = MQTT_QOS_STATE_GOT_ACK; + conn->in_packet.mid = (conn->in_packet.payload[0] << 8) | + (conn->in_packet.payload[1]); + + if(conn->in_packet.mid != conn->out_packet.mid) { + DBG("MQTT - Warning, got UNSUBACK with none matching MID. Currently there is" + "no support for several concurrent UNSUBSCRIBE messages.\n"); + } + + call_event(conn, MQTT_EVENT_UNSUBACK, &conn->in_packet.mid); +} +/*---------------------------------------------------------------------------*/ +static void +handle_puback(struct mqtt_connection *conn) +{ + DBG("MQTT - Got PUBACK\n"); + + conn->out_packet.qos_state = MQTT_QOS_STATE_GOT_ACK; + conn->in_packet.mid = (conn->in_packet.payload[0] << 8) | + (conn->in_packet.payload[1]); + + call_event(conn, MQTT_EVENT_PUBACK, &conn->in_packet.mid); +} +/*---------------------------------------------------------------------------*/ +static void +handle_publish(struct mqtt_connection *conn) +{ + DBG("MQTT - Got PUBLISH, called once per manageable chunk of message.\n"); + DBG("MQTT - Handling publish on topic '%s'\n", conn->in_publish_msg.topic); + + DBG("MQTT - This chunk is %i bytes\n", conn->in_packet.payload_pos); + + if(((conn->in_packet.fhdr & 0x09) >> 1) > 0) { + PRINTF("MQTT - Error, got incoming PUBLISH with QoS > 0, not supported atm!\n"); + } + + call_event(conn, MQTT_EVENT_PUBLISH, &conn->in_publish_msg); + + if(conn->in_publish_msg.first_chunk == 1) { + conn->in_publish_msg.first_chunk = 0; + } + + /* If this is the last time handle_publish will be called, reset packet. */ + if(conn->in_publish_msg.payload_left == 0) { + + /* Check for QoS and initiate the reply, do not rely on the data in the + * in_packet being untouched. */ + + DBG("MQTT - (handle_publish) resetting packet.\n"); + reset_packet(&conn->in_packet); + } +} +/*---------------------------------------------------------------------------*/ +static void +parse_publish_vhdr(struct mqtt_connection *conn, + uint32_t *pos, + const uint8_t *input_data_ptr, + int input_data_len) +{ + uint16_t copy_bytes; + + /* Read out topic length */ + if(conn->in_packet.topic_len_received == 0) { + conn->in_packet.topic_len = (input_data_ptr[(*pos)++] << 8); + conn->in_packet.byte_counter++; + if(*pos >= input_data_len) { + return; + } + conn->in_packet.topic_len |= input_data_ptr[(*pos)++]; + conn->in_packet.byte_counter++; + conn->in_packet.topic_len_received = 1; + + DBG("MQTT - Read PUBLISH topic len %i\n", conn->in_packet.topic_len); + /* WARNING: Check here if TOPIC fits in payload area, otherwise error */ + } + + /* Read out topic */ + if(conn->in_packet.topic_len_received == 1 && + conn->in_packet.topic_received == 0) { + copy_bytes = MIN(conn->in_packet.topic_len - conn->in_packet.topic_pos, + input_data_len - *pos); + DBG("MQTT - topic_pos: %i copy_bytes: %i", conn->in_packet.topic_pos, + copy_bytes); + memcpy(&conn->in_publish_msg.topic[conn->in_packet.topic_pos], + &input_data_ptr[*pos], + copy_bytes); + (*pos) += copy_bytes; + conn->in_packet.byte_counter += copy_bytes; + conn->in_packet.topic_pos += copy_bytes; + + if(conn->in_packet.topic_len - conn->in_packet.topic_pos == 0) { + DBG("MQTT - Got topic '%s'", conn->in_publish_msg.topic); + conn->in_packet.topic_received = 1; + conn->in_publish_msg.topic[conn->in_packet.topic_pos] = '\0'; + conn->in_publish_msg.payload_length = + conn->in_packet.remaining_length - conn->in_packet.topic_len - 2; + conn->in_publish_msg.payload_left = conn->in_publish_msg.payload_length; + } + + /* Set this once per incomming publish message */ + conn->in_publish_msg.first_chunk = 1; + } +} +/*---------------------------------------------------------------------------*/ +static int +tcp_input(struct tcp_socket *s, + void *ptr, + const uint8_t *input_data_ptr, + int input_data_len) +{ + struct mqtt_connection *conn = ptr; + uint32_t pos = 0; + uint32_t copy_bytes = 0; + uint8_t byte; + + if(input_data_len == 0) { + return 0; + } + + if(conn->in_packet.packet_received) { + reset_packet(&conn->in_packet); + } + + DBG("tcp_input with %i bytes of data:\n", input_data_len); + + /* Read the fixed header field, if we do not have it */ + if(!conn->in_packet.fhdr) { + conn->in_packet.fhdr = input_data_ptr[pos++]; + conn->in_packet.byte_counter++; + + DBG("MQTT - Read VHDR '%02X'\n", conn->in_packet.fhdr); + + if(pos >= input_data_len) { + return 0; + } + } + + /* Read the Remaining Length field, if we do not have it */ + if(!conn->in_packet.has_remaining_length) { + do { + if(pos >= input_data_len) { + return 0; + } + + byte = input_data_ptr[pos++]; + conn->in_packet.byte_counter++; + conn->in_packet.remaining_length_bytes++; + DBG("MQTT - Read Remaining Length byte\n"); + + if(conn->in_packet.byte_counter > 5) { + call_event(conn, MQTT_EVENT_ERROR, NULL); + DBG("Received more then 4 byte 'remaining lenght'."); + return 0; + } + + conn->in_packet.remaining_length += + (byte & 127) * conn->in_packet.remaining_multiplier; + conn->in_packet.remaining_multiplier *= 128; + } while((byte & 128) != 0); + + DBG("MQTT - Finished reading remaining length byte\n"); + conn->in_packet.has_remaining_length = 1; + } + + /* + * Check for unsupported payload length. Will read all incoming data from the + * server in any case and then reset the packet. + * + * TODO: Decide if we, for example, want to disconnect instead. + */ + if((conn->in_packet.remaining_length > MQTT_INPUT_BUFF_SIZE) && + (conn->in_packet.fhdr & 0xF0) != MQTT_FHDR_MSG_TYPE_PUBLISH) { + + PRINTF("MQTT - Error, unsupported payload size for non-PUBLISH message\n"); + + conn->in_packet.byte_counter += input_data_len; + if(conn->in_packet.byte_counter >= + (MQTT_FHDR_SIZE + conn->in_packet.remaining_length)) { + conn->in_packet.packet_received = 1; + } + return 0; + } + + /* + * Supported payload, reads out both VHDR and Payload of all packets. + * + * Note: There will always be at least one byte left to read when we enter + * this loop. + */ + while(conn->in_packet.byte_counter < + (MQTT_FHDR_SIZE + conn->in_packet.remaining_length)) { + + if((conn->in_packet.fhdr & 0xF0) == MQTT_FHDR_MSG_TYPE_PUBLISH && + conn->in_packet.topic_received == 0) { + parse_publish_vhdr(conn, &pos, input_data_ptr, input_data_len); + } + + /* Read in as much as we can into the packet payload */ + copy_bytes = MIN(input_data_len - pos, + MQTT_INPUT_BUFF_SIZE - conn->in_packet.payload_pos); + DBG("- Copied %lu payload bytes\n", copy_bytes); + memcpy(&conn->in_packet.payload[conn->in_packet.payload_pos], + &input_data_ptr[pos], + copy_bytes); + conn->in_packet.byte_counter += copy_bytes; + conn->in_packet.payload_pos += copy_bytes; + pos += copy_bytes; + + uint8_t i; + DBG("MQTT - Copied bytes: \n"); + for(i = 0; i < copy_bytes; i++) { + DBG("%02X ", conn->in_packet.payload[i]); + } + DBG("\n"); + + /* Full buffer, shall only happen to PUBLISH messages. */ + if(MQTT_INPUT_BUFF_SIZE - conn->in_packet.payload_pos == 0) { + conn->in_publish_msg.payload_chunk = conn->in_packet.payload; + conn->in_publish_msg.payload_chunk_length = MQTT_INPUT_BUFF_SIZE; + conn->in_publish_msg.payload_left -= MQTT_INPUT_BUFF_SIZE; + + handle_publish(conn); + + conn->in_publish_msg.payload_chunk = conn->in_packet.payload; + conn->in_packet.payload_pos = 0; + } + + if(pos >= input_data_len && + (conn->in_packet.byte_counter < (MQTT_FHDR_SIZE + conn->in_packet.remaining_length))) { + return 0; + } + } + + /* Debug information */ + DBG("\n"); + /* Take care of input */ + DBG("MQTT - Finished reading packet!\n"); + /* What to return? */ + DBG("MQTT - total data was %i bytes of data. \n", + (MQTT_FHDR_SIZE + conn->in_packet.remaining_length)); + + /* Handle packet here. */ + switch(conn->in_packet.fhdr & 0xF0) { + case MQTT_FHDR_MSG_TYPE_CONNACK: + handle_connack(conn); + break; + case MQTT_FHDR_MSG_TYPE_PUBLISH: + /* This is the only or the last chunk of publish payload */ + conn->in_publish_msg.payload_chunk = conn->in_packet.payload; + conn->in_publish_msg.payload_chunk_length = conn->in_packet.payload_pos; + conn->in_publish_msg.payload_left = 0; + handle_publish(conn); + break; + case MQTT_FHDR_MSG_TYPE_PUBACK: + handle_puback(conn); + break; + case MQTT_FHDR_MSG_TYPE_SUBACK: + handle_suback(conn); + break; + case MQTT_FHDR_MSG_TYPE_UNSUBACK: + handle_unsuback(conn); + break; + case MQTT_FHDR_MSG_TYPE_PINGRESP: + handle_pingresp(conn); + break; + + /* QoS 2 not implemented yet */ + case MQTT_FHDR_MSG_TYPE_PUBREC: + case MQTT_FHDR_MSG_TYPE_PUBREL: + case MQTT_FHDR_MSG_TYPE_PUBCOMP: + call_event(conn, MQTT_EVENT_NOT_IMPLEMENTED_ERROR, NULL); + PRINTF("MQTT - Got unhandled MQTT Message Type '%i'", + (conn->in_packet.fhdr & 0xF0)); + break; + + default: + /* All server-only message */ + PRINTF("MQTT - Got MQTT Message Type '%i'", (conn->in_packet.fhdr & 0xF0)); + break; + } + + conn->in_packet.packet_received = 1; + + return 0; +} +/*---------------------------------------------------------------------------*/ +/* + * Handles TCP events from Simple TCP + */ +static void +tcp_event(struct tcp_socket *s, void *ptr, tcp_socket_event_t event) +{ + struct mqtt_connection *conn = ptr; + + /* Take care of event */ + switch(event) { + + /* Fall through to manage different disconnect event the same way. */ + case TCP_SOCKET_CLOSED: + case TCP_SOCKET_TIMEDOUT: + case TCP_SOCKET_ABORTED: { + + DBG("MQTT - Disconnected by tcp event %d\n", event); + process_post(&mqtt_process, mqtt_abort_now_event, conn); + conn->state = MQTT_CONN_STATE_NOT_CONNECTED; + ctimer_stop(&conn->keep_alive_timer); + call_event(conn, MQTT_EVENT_DISCONNECTED, &event); + abort_connection(conn); + + /* If connecting retry */ + if(conn->auto_reconnect == 1) { + connect_tcp(conn); + } + break; + } + case TCP_SOCKET_CONNECTED: { + conn->state = MQTT_CONN_STATE_TCP_CONNECTED; + conn->out_buffer_sent = 1; + + process_post(&mqtt_process, mqtt_do_connect_mqtt_event, conn); + break; + } + case TCP_SOCKET_DATA_SENT: { + DBG("MQTT - Got TCP_DATA_SENT\n"); + + if(conn->socket.output_data_len == 0) { + conn->out_buffer_sent = 1; + conn->out_buffer_ptr = conn->out_buffer; + } + + ctimer_restart(&conn->keep_alive_timer); + break; + } + + default: { + DBG("MQTT - TCP Event %d is currently not managed by the tcp event callback\n", + event); + } + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(mqtt_process, ev, data) +{ + static struct mqtt_connection *conn; + + PROCESS_BEGIN(); + + while(1) { + PROCESS_WAIT_EVENT(); + + if(ev == mqtt_abort_now_event) { + DBG("MQTT - Abort\n"); + conn = data; + conn->state = MQTT_CONN_STATE_ABORT_IMMEDIATE; + + abort_connection(conn); + } + if(ev == mqtt_do_connect_tcp_event) { + conn = data; + DBG("MQTT - Got mqtt_do_connect_tcp_event!\n"); + connect_tcp(conn); + } + if(ev == mqtt_do_connect_mqtt_event) { + conn = data; + conn->socket.output_data_max_seg = conn->max_segment_size; + DBG("MQTT - Got mqtt_do_connect_mqtt_event!\n"); + + if(conn->out_buffer_sent == 1) { + PT_INIT(&conn->out_proto_thread); + while(connect_pt(&conn->out_proto_thread, conn) < PT_EXITED && + conn->state != MQTT_CONN_STATE_ABORT_IMMEDIATE) { + PT_MQTT_WAIT_SEND(); + } + } + } + if(ev == mqtt_do_disconnect_mqtt_event) { + conn = data; + DBG("MQTT - Got mqtt_do_disconnect_mqtt_event!\n"); + + /* Send MQTT Disconnect if we are connected */ + if(conn->state == MQTT_CONN_STATE_SENDING_MQTT_DISCONNECT) { + if(conn->out_buffer_sent == 1) { + PT_INIT(&conn->out_proto_thread); + while(disconnect_pt(&conn->out_proto_thread, conn) < PT_EXITED && + conn->state != MQTT_CONN_STATE_ABORT_IMMEDIATE) { + PT_MQTT_WAIT_SEND(); + } + abort_connection(conn); + call_event(conn, MQTT_EVENT_DISCONNECTED, &ev); + } else { + process_post(&mqtt_process, mqtt_do_disconnect_mqtt_event, conn); + } + } + } + if(ev == mqtt_do_pingreq_event) { + conn = data; + DBG("MQTT - Got mqtt_do_pingreq_event!\n"); + + if(conn->out_buffer_sent == 1 && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_INIT(&conn->out_proto_thread); + while(pingreq_pt(&conn->out_proto_thread, conn) < PT_EXITED && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_MQTT_WAIT_SEND(); + } + } + } + if(ev == mqtt_do_subscribe_event) { + conn = data; + DBG("MQTT - Got mqtt_do_subscribe_mqtt_event!\n"); + + if(conn->out_buffer_sent == 1 && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_INIT(&conn->out_proto_thread); + while(subscribe_pt(&conn->out_proto_thread, conn) < PT_EXITED && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_MQTT_WAIT_SEND(); + } + } + } + if(ev == mqtt_do_unsubscribe_event) { + conn = data; + DBG("MQTT - Got mqtt_do_unsubscribe_mqtt_event!\n"); + + if(conn->out_buffer_sent == 1 && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_INIT(&conn->out_proto_thread); + while(unsubscribe_pt(&conn->out_proto_thread, conn) < PT_EXITED && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_MQTT_WAIT_SEND(); + } + } + } + if(ev == mqtt_do_publish_event) { + conn = data; + DBG("MQTT - Got mqtt_do_publish_mqtt_event!\n"); + + if(conn->out_buffer_sent == 1 && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_INIT(&conn->out_proto_thread); + while(publish_pt(&conn->out_proto_thread, conn) < PT_EXITED && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_MQTT_WAIT_SEND(); + } + } + } + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +void +mqtt_init(void) +{ + static uint8_t inited = 0; + if(!inited) { + mqtt_do_connect_tcp_event = process_alloc_event(); + mqtt_event_min = mqtt_do_connect_tcp_event; + + mqtt_do_connect_mqtt_event = process_alloc_event(); + mqtt_do_disconnect_mqtt_event = process_alloc_event(); + mqtt_do_subscribe_event = process_alloc_event(); + mqtt_do_unsubscribe_event = process_alloc_event(); + mqtt_do_publish_event = process_alloc_event(); + mqtt_do_pingreq_event = process_alloc_event(); + mqtt_update_event = process_alloc_event(); + mqtt_abort_now_event = process_alloc_event(); + mqtt_event_max = mqtt_abort_now_event; + + mqtt_continue_send_event = process_alloc_event(); + + list_init(mqtt_conn_list); + process_start(&mqtt_process, NULL); + inited = 1; + } +} +/*---------------------------------------------------------------------------*/ +mqtt_status_t +mqtt_register(struct mqtt_connection *conn, struct process *app_process, + char *client_id, mqtt_event_callback_t event_callback, + uint16_t max_segment_size) +{ + if(strlen(client_id) < 1) { + return MQTT_STATUS_INVALID_ARGS_ERROR; + } + + /* Set defaults - Set all to zero to begin with */ + memset(conn, 0, sizeof(struct mqtt_connection)); + string_to_mqtt_string(&conn->client_id, client_id); + conn->event_callback = event_callback; + conn->app_process = app_process; + conn->auto_reconnect = 1; + conn->max_segment_size = max_segment_size; + reset_defaults(conn); + + mqtt_init(); + list_add(mqtt_conn_list, conn); + + DBG("MQTT - Registered successfully\n"); + + return MQTT_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +/* + * Connect to MQTT broker. + * + * N.B. Non-blocking call. + */ +mqtt_status_t +mqtt_connect(struct mqtt_connection *conn, char *host, uint16_t port, + uint16_t keep_alive) +{ + uip_ip6addr_t ip6addr; + uip_ipaddr_t *ipaddr; + ipaddr = &ip6addr; + + /* Check if we are already trying to connect */ + if(conn->state > MQTT_CONN_STATE_NOT_CONNECTED) { + return MQTT_STATUS_OK; + } + + conn->server_host = host; + conn->keep_alive = keep_alive; + conn->server_port = port; + conn->out_buffer_ptr = conn->out_buffer; + conn->out_packet.qos_state = MQTT_QOS_STATE_NO_ACK; + conn->connect_vhdr_flags |= MQTT_VHDR_CLEAN_SESSION_FLAG; + + /* convert the string IPv6 address to a numeric IPv6 address */ + uiplib_ip6addrconv(host, &ip6addr); + + uip_ipaddr_copy(&(conn->server_ip), ipaddr); + + /* + * Initiate the connection if the IP could be resolved. Otherwise the + * connection will be initiated when the DNS lookup is finished, in the main + * event loop. + */ + process_post(&mqtt_process, mqtt_do_connect_tcp_event, conn); + + return MQTT_STATUS_OK; +} +/*----------------------------------------------------------------------------*/ +void +mqtt_disconnect(struct mqtt_connection *conn) +{ + if(conn->state != MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + return; + } + + conn->state = MQTT_CONN_STATE_SENDING_MQTT_DISCONNECT; + + process_post(&mqtt_process, mqtt_do_disconnect_mqtt_event, conn); +} +/*----------------------------------------------------------------------------*/ +mqtt_status_t +mqtt_subscribe(struct mqtt_connection *conn, uint16_t *mid, char *topic, + mqtt_qos_level_t qos_level) +{ + if(conn->state != MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + return MQTT_STATUS_NOT_CONNECTED_ERROR; + } + + DBG("MQTT - Call to mqtt_subscribe...\n"); + + /* Currently don't have a queue, so only one item at a time */ + if(conn->out_queue_full) { + DBG("MQTT - Not accepted!\n"); + return MQTT_STATUS_OUT_QUEUE_FULL; + } + conn->out_queue_full = 1; + DBG("MQTT - Accepted!\n"); + + conn->out_packet.mid = INCREMENT_MID(conn); + conn->out_packet.topic = topic; + conn->out_packet.topic_length = strlen(topic); + conn->out_packet.qos = qos_level; + conn->out_packet.qos_state = MQTT_QOS_STATE_NO_ACK; + + process_post(&mqtt_process, mqtt_do_subscribe_event, conn); + return MQTT_STATUS_OK; +} +/*----------------------------------------------------------------------------*/ +mqtt_status_t +mqtt_unsubscribe(struct mqtt_connection *conn, uint16_t *mid, char *topic) +{ + if(conn->state != MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + return MQTT_STATUS_NOT_CONNECTED_ERROR; + } + + DBG("MQTT - Call to mqtt_unsubscribe...\n"); + /* Currently don't have a queue, so only one item at a time */ + if(conn->out_queue_full) { + DBG("MQTT - Not accepted!\n"); + return MQTT_STATUS_OUT_QUEUE_FULL; + } + conn->out_queue_full = 1; + DBG("MQTT - Accepted!\n"); + + conn->out_packet.mid = INCREMENT_MID(conn); + conn->out_packet.topic = topic; + conn->out_packet.topic_length = strlen(topic); + conn->out_packet.qos_state = MQTT_QOS_STATE_NO_ACK; + + process_post(&mqtt_process, mqtt_do_unsubscribe_event, conn); + return MQTT_STATUS_OK; +} +/*----------------------------------------------------------------------------*/ +mqtt_status_t +mqtt_publish(struct mqtt_connection *conn, uint16_t *mid, char *topic, + uint8_t *payload, uint32_t payload_size, + mqtt_qos_level_t qos_level, mqtt_retain_t retain) +{ + if(conn->state != MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + return MQTT_STATUS_NOT_CONNECTED_ERROR; + } + + DBG("MQTT - Call to mqtt_publish...\n"); + + /* Currently don't have a queue, so only one item at a time */ + if(conn->out_queue_full) { + DBG("MQTT - Not accepted!\n"); + return MQTT_STATUS_OUT_QUEUE_FULL; + } + conn->out_queue_full = 1; + DBG("MQTT - Accepted!\n"); + + conn->out_packet.mid = INCREMENT_MID(conn); + conn->out_packet.retain = retain; + conn->out_packet.topic = topic; + conn->out_packet.topic_length = strlen(topic); + conn->out_packet.payload = payload; + conn->out_packet.payload_size = payload_size; + conn->out_packet.qos = qos_level; + conn->out_packet.qos_state = MQTT_QOS_STATE_NO_ACK; + + process_post(&mqtt_process, mqtt_do_publish_event, conn); + return MQTT_STATUS_OK; +} +/*----------------------------------------------------------------------------*/ +void +mqtt_set_username_password(struct mqtt_connection *conn, char *username, + char *password) +{ + /* Set strings, NULL string will simply set length to zero */ + string_to_mqtt_string(&conn->credentials.username, username); + string_to_mqtt_string(&conn->credentials.password, password); + + /* Set CONNECT VHDR flags */ + if(username != NULL) { + conn->connect_vhdr_flags |= MQTT_VHDR_USERNAME_FLAG; + } else { + conn->connect_vhdr_flags &= ~MQTT_VHDR_USERNAME_FLAG; + } + if(password != NULL) { + conn->connect_vhdr_flags |= MQTT_VHDR_PASSWORD_FLAG; + } else { + conn->connect_vhdr_flags &= ~MQTT_VHDR_PASSWORD_FLAG; + } +} +/*----------------------------------------------------------------------------*/ +void +mqtt_set_last_will(struct mqtt_connection *conn, char *topic, char *message, + mqtt_qos_level_t qos) +{ + /* Set strings, NULL string will simply set length to zero */ + string_to_mqtt_string(&conn->will.topic, topic); + string_to_mqtt_string(&conn->will.message, message); + + /* Currently not used! */ + conn->will.qos = qos; + + if(topic != NULL) { + conn->connect_vhdr_flags |= MQTT_VHDR_WILL_FLAG | + MQTT_VHDR_WILL_RETAIN_FLAG; + } +} +/*----------------------------------------------------------------------------*/ +/** @} */ diff --git a/apps/mqtt/mqtt.h b/apps/mqtt/mqtt.h new file mode 100644 index 000000000..4b27fa30c --- /dev/null +++ b/apps/mqtt/mqtt.h @@ -0,0 +1,509 @@ +/* + * 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 apps + * @{ + * + * \defgroup mqtt-engine An implementation of MQTT v3.1 + * @{ + * + * This application is an engine for MQTT v3.1. It supports QoS Levels 0 and 1. + * + * MQTT is a Client Server publish/subscribe messaging transport protocol. + * It is light weight, open, simple, and designed so as to be easy to implement. + * These characteristics make it ideal for use in many situations, including + * constrained environments such as for communication in Machine to Machine + * (M2M) and Internet of Things (IoT) contexts where a small code footprint is + * required and/or network bandwidth is at a premium. + * + * The protocol runs over TCP/IP, more specifically tcp_socket. + * Its features include: + * + * - Use of the publish/subscribe message pattern which provides + * one-to-many message distribution and decoupling of applications. + * - A messaging transport that is agnostic to the content of the payload. + * Three qualities of service for message delivery: + * -- "At most once" (0), where messages are delivered according to the best + * efforts of the operating environment. Message loss can occur. + * This level could be used, for example, with ambient sensor data where it + * does not matter if an individual reading is lost as the next one will be + * published soon after. + * --"At least once" (1), where messages are assured to arrive but duplicates + * can occur. + * -- "Exactly once" (2), where message are assured to arrive exactly once. + * This level could be used, for example, with billing systems where duplicate + * or lost messages could lead to incorrect charges being applied. This QoS + * level is currently not supported in this implementation. + * + * - A small transport overhead and protocol exchanges minimized to reduce + * network traffic. + * - A mechanism, Last Will, to notify interested parties when an abnormal + * disconnection occurs. + * + * The protocol specification and other useful information can be found + * here: http://mqtt.org + * + */ +/** + * \file + * Header file for the Contiki MQTT engine + * + * \author + * Texas Instruments + */ +/*---------------------------------------------------------------------------*/ +#ifndef MQTT_H_ +#define MQTT_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "contiki-net.h" +#include "contiki-lib.h" +#include "lib/random.h" +#include "sys/ctimer.h" +#include "sys/etimer.h" +#include "net/rpl/rpl.h" +#include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" +#include "dev/leds.h" + +#include "tcp-socket.h" +#include "udp-socket.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +/* Protocol constants */ +#define MQTT_CLIENT_ID_MAX_LEN 23 + +/* Size of the underlying TCP buffers */ +#define MQTT_TCP_INPUT_BUFF_SIZE 512 +#define MQTT_TCP_OUTPUT_BUFF_SIZE 512 + +#define MQTT_INPUT_BUFF_SIZE 512 +#define MQTT_MAX_TOPIC_LENGTH 64 +#define MQTT_MAX_TOPICS_PER_SUBSCRIBE 1 + +#define MQTT_FHDR_SIZE 1 +#define MQTT_MAX_REMAINING_LENGTH_BYTES 4 +#define MQTT_PROTOCOL_VERSION 3 +#define MQTT_PROTOCOL_NAME "MQIsdp" +#define MQTT_TOPIC_MAX_LENGTH 128 +/*---------------------------------------------------------------------------*/ +/* + * Debug configuration, this is similar but not exactly like the Debugging + * System discussion at https://github.com/contiki-os/contiki/wiki. + */ +#define DEBUG_MQTT 0 + +#if DEBUG_MQTT == 1 +#define DBG(...) printf(__VA_ARGS__) +#else +#define DBG(...) +#endif /* DEBUG */ +/*---------------------------------------------------------------------------*/ +extern process_event_t mqtt_update_event; + +/* Forward declaration */ +struct mqtt_connection; + +typedef enum { + MQTT_RETAIN_OFF, + MQTT_RETAIN_ON, +} mqtt_retain_t; + +/** + * \brief MQTT engine events + */ +typedef enum { + MQTT_EVENT_CONNECTED, + MQTT_EVENT_DISCONNECTED, + + MQTT_EVENT_SUBACK, + MQTT_EVENT_UNSUBACK, + MQTT_EVENT_PUBLISH, + MQTT_EVENT_PUBACK, + + /* Errors */ + MQTT_EVENT_ERROR = 0x80, + MQTT_EVENT_PROTOCOL_ERROR, + MQTT_EVENT_CONNECTION_REFUSED_ERROR, + MQTT_EVENT_DNS_ERROR, + MQTT_EVENT_NOT_IMPLEMENTED_ERROR, + /* Add more */ +} mqtt_event_t; + +typedef enum { + MQTT_STATUS_OK, + + MQTT_STATUS_OUT_QUEUE_FULL, + + /* Errors */ + MQTT_STATUS_ERROR = 0x80, + MQTT_STATUS_NOT_CONNECTED_ERROR, + MQTT_STATUS_INVALID_ARGS_ERROR, + MQTT_STATUS_DNS_ERROR, +} mqtt_status_t; + +typedef enum { + MQTT_QOS_LEVEL_0, + MQTT_QOS_LEVEL_1, + MQTT_QOS_LEVEL_2, +} mqtt_qos_level_t; + +typedef enum { + MQTT_QOS_STATE_NO_ACK, + MQTT_QOS_STATE_GOT_ACK, + + /* Expand for QoS 2 */ +} mqtt_qos_state_t; +/*---------------------------------------------------------------------------*/ +/* + * This is the state of the connection itself. + * + * N.B. The order is important because of runtime checks on how far the + * connection has proceeded. + */ +typedef enum { + MQTT_CONN_STATE_ERROR, + MQTT_CONN_STATE_DNS_ERROR, + MQTT_CONN_STATE_DISCONNECTING, + + MQTT_CONN_STATE_NOT_CONNECTED, + MQTT_CONN_STATE_DNS_LOOKUP, + MQTT_CONN_STATE_TCP_CONNECTING, + MQTT_CONN_STATE_TCP_CONNECTED, + MQTT_CONN_STATE_CONNECTING_TO_BROKER, + MQTT_CONN_STATE_CONNECTED_TO_BROKER, + MQTT_CONN_STATE_SENDING_MQTT_DISCONNECT, + MQTT_CONN_STATE_ABORT_IMMEDIATE, +} mqtt_conn_state_t; +/*---------------------------------------------------------------------------*/ +struct mqtt_string { + char *string; + uint16_t length; +}; + +/* + * Note that the pairing mid <-> QoS level only applies one-to-one if we only + * allow the subscription of one topic at a time. Otherwise we will have an + * ordered list of QoS levels corresponding to the order of topics. + * + * This could be part of a union of event data structures. + */ +struct mqtt_suback_event { + uint16_t mid; + mqtt_qos_level_t qos_level; +}; + +/* This is the MQTT message that is exposed to the end user. */ +struct mqtt_message { + uint32_t mid; + char topic[MQTT_MAX_TOPIC_LENGTH + 1]; /* +1 for string termination */ + + uint8_t *payload_chunk; + uint16_t payload_chunk_length; + + uint8_t first_chunk; + uint16_t payload_length; + uint16_t payload_left; +}; + +/* This struct represents a packet received from the MQTT server. */ +struct mqtt_in_packet { + /* Used by the list interface, must be first in the struct. */ + struct mqtt_connection *next; + + /* Total bytes read so far. Compared to the remaining length to to decide when + * we've read the payload. */ + uint32_t byte_counter; + uint8_t packet_received; + + uint8_t fhdr; + uint16_t remaining_length; + uint16_t mid; + + /* Helper variables needed to decode the remaining_length */ + uint8_t remaining_multiplier; + uint8_t has_remaining_length; + uint8_t remaining_length_bytes; + + /* Not the same as payload in the MQTT sense, it also contains the variable + * header. + */ + uint8_t payload_pos; + uint8_t payload[MQTT_INPUT_BUFF_SIZE]; + + /* Message specific data */ + uint16_t topic_len; + uint16_t topic_pos; + uint8_t topic_len_received; + uint8_t topic_received; +}; + +/* This struct represents a packet sent to the MQTT server. */ +struct mqtt_out_packet { + uint8_t fhdr; + uint32_t remaining_length; + uint8_t remaining_length_enc[MQTT_MAX_REMAINING_LENGTH_BYTES]; + uint8_t remaining_length_enc_bytes; + uint16_t mid; + char *topic; + uint16_t topic_length; + uint8_t *payload; + uint32_t payload_size; + mqtt_qos_level_t qos; + mqtt_qos_state_t qos_state; + mqtt_retain_t retain; +}; +/*---------------------------------------------------------------------------*/ +/** + * \brief MQTT event callback function + * \param m A pointer to a MQTT connection + * \param event The event number + * \param data A user-defined pointer + * + * The MQTT socket event callback function gets called whenever there is an + * event on a MQTT connection, such as the connection getting connected + * or closed. + */ +typedef void (*mqtt_event_callback_t)(struct mqtt_connection *m, + mqtt_event_t event, + void *data); + +typedef void (*mqtt_topic_callback_t)(struct mqtt_connection *m, + struct mqtt_message *msg); +/*---------------------------------------------------------------------------*/ +struct mqtt_will { + struct mqtt_string topic; + struct mqtt_string message; + mqtt_qos_level_t qos; +}; + +struct mqtt_credentials { + struct mqtt_string username; + struct mqtt_string password; +}; + +struct mqtt_connection { + /* Used by the list interface, must be first in the struct */ + struct mqtt_connection *next; + struct timer t; + + struct mqtt_string client_id; + + uint8_t connect_vhdr_flags; + uint8_t auto_reconnect; + + uint16_t keep_alive; + struct ctimer keep_alive_timer; + uint8_t waiting_for_pingresp; + + struct mqtt_will will; + struct mqtt_credentials credentials; + + mqtt_conn_state_t state; + mqtt_event_callback_t event_callback; + + /* Internal data */ + uint16_t mid_counter; + + /* Used for communication between MQTT API and APP */ + uint8_t out_queue_full; + struct process *app_process; + + /* Outgoing data related */ + uint8_t *out_buffer_ptr; + uint8_t out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE]; + uint8_t out_buffer_sent; + struct mqtt_out_packet out_packet; + struct pt out_proto_thread; + uint32_t out_write_pos; + uint16_t max_segment_size; + + /* Incoming data related */ + uint8_t in_buffer[MQTT_TCP_INPUT_BUFF_SIZE]; + struct mqtt_in_packet in_packet; + struct mqtt_message in_publish_msg; + + /* TCP related information */ + char *server_host; + uip_ipaddr_t server_ip; + uint16_t server_port; + struct tcp_socket socket; +}; +/* This is the API exposed to the user. */ +/*---------------------------------------------------------------------------*/ +/** + * \brief Initializes the MQTT engine. + * \param conn A pointer to the MQTT connection. + * \param app_process A pointer to the application process handling the MQTT + * connection. + * \param client_id A pointer to the MQTT client ID. + * \param event_callback Callback function responsible for handling the + * callback from MQTT engine. + * \param max_segment_size The TCP segment size to use for this MQTT/TCP + * connection. + * \return MQTT_STATUS_OK or MQTT_STATUS_INVALID_ARGS_ERROR + * + * This function initializes the MQTT engine and shall be called before any + * other MQTT function. + */ +mqtt_status_t mqtt_register(struct mqtt_connection *conn, + struct process *app_process, + char *client_id, + mqtt_event_callback_t event_callback, + uint16_t max_segment_size); +/*---------------------------------------------------------------------------*/ +/** + * \brief Connects to a MQTT broker. + * \param conn A pointer to the MQTT connection. + * \param host IP address of the broker to connect to. + * \param port Port of the broker to connect to, default is MQTT port is 1883. + * \param keep_alive Keep alive timer in seconds. Used by broker to handle + * client disc. Defines the maximum time interval between two messages + * from the client. Shall be min 1.5 x report interval. + * \return MQTT_STATUS_OK or an error status + * + * This function connects to a MQTT broker. + */ +mqtt_status_t mqtt_connect(struct mqtt_connection *conn, + char *host, + uint16_t port, + uint16_t keep_alive); +/*---------------------------------------------------------------------------*/ +/** + * \brief Disconnects from a MQTT broker. + * \param conn A pointer to the MQTT connection. + * + * This function disconnects from a MQTT broker. + */ +void mqtt_disconnect(struct mqtt_connection *conn); +/*---------------------------------------------------------------------------*/ +/** + * \brief Subscribes to a MQTT topic. + * \param conn A pointer to the MQTT connection. + * \param mid A pointer to message ID. + * \param topic A pointer to the topic to subscribe to. + * \param qos_level Quality Of Service level to use. Currently supports 0, 1. + * \return MQTT_STATUS_OK or some error status + * + * This function subscribes to a topic on a MQTT broker. + */ +mqtt_status_t mqtt_subscribe(struct mqtt_connection *conn, + uint16_t *mid, + char *topic, + mqtt_qos_level_t qos_level); +/*---------------------------------------------------------------------------*/ +/** + * \brief Unsubscribes from a MQTT topic. + * \param conn A pointer to the MQTT connection. + * \param mid A pointer to message ID. + * \param topic A pointer to the topic to unsubscribe from. + * \return MQTT_STATUS_OK or some error status + * + * This function unsubscribes from a topic on a MQTT broker. + */ +mqtt_status_t mqtt_unsubscribe(struct mqtt_connection *conn, + uint16_t *mid, + char *topic); +/*---------------------------------------------------------------------------*/ +/** + * \brief Publish to a MQTT topic. + * \param conn A pointer to the MQTT connection. + * \param mid A pointer to message ID. + * \param topic A pointer to the topic to subscribe to. + * \param payload A pointer to the topic payload. + * \param payload_size Payload size. + * \param qos_level Quality Of Service level to use. Currently supports 0, 1. + * \param retain If the RETAIN flag is set to 1, in a PUBLISH Packet sent by a + * Client to a Server, the Server MUST store the Application Message + * and its QoS, so that it can be delivered to future subscribers whose + * subscriptions match its topic name + * \return MQTT_STATUS_OK or some error status + * + * This function publishes to a topic on a MQTT broker. + */ +mqtt_status_t mqtt_publish(struct mqtt_connection *conn, + uint16_t *mid, + char *topic, + uint8_t *payload, + uint32_t payload_size, + mqtt_qos_level_t qos_level, + mqtt_retain_t retain); +/*---------------------------------------------------------------------------*/ +/** + * \brief Set the user name and password for a MQTT client. + * \param conn A pointer to the MQTT connection. + * \param username A pointer to the user name. + * \param password A pointer to the password. + * + * This function sets clients user name and password to use when connecting to + * a MQTT broker. + */ +void mqtt_set_username_password(struct mqtt_connection *conn, + char *username, + char *password); +/*---------------------------------------------------------------------------*/ +/** + * \brief Set the last will topic and message for a MQTT client. + * \param conn A pointer to the MQTT connection. + * \param topic A pointer to the Last Will topic. + * \param message A pointer to the Last Will message (payload). + * \param qos The desired QoS level. + * + * This function sets clients Last Will topic and message (payload). + * If the Will Flag is set to 1 (using the function) this indicates that, + * if the Connect request is accepted, a Will Message MUST be stored on the + * Server and associated with the Network Connection. The Will Message MUST + * be published when the Network Connection is subsequently closed. + * + * This functionality can be used to get notified that a device has + * disconnected from the broker. + * + */ +void mqtt_set_last_will(struct mqtt_connection *conn, + char *topic, + char *message, + mqtt_qos_level_t qos); + +#define mqtt_connected(conn) \ + ((conn)->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER ? 1 : 0) + +#define mqtt_ready(conn) \ + (!(conn)->out_queue_full && mqtt_connected((conn))) +/*---------------------------------------------------------------------------*/ +#endif /* MQTT_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/apps/netconf/netconf.c b/apps/netconf/netconf.c index 8249d35ec..b7a81fb99 100644 --- a/apps/netconf/netconf.c +++ b/apps/netconf/netconf.c @@ -113,7 +113,7 @@ makestrings(void) makeaddr(&addr, gateway); #if UIP_UDP - addrptr = resolv_getserver(); + addrptr = uip_nameserver_get(0); if(addrptr != NULL) { makeaddr(addrptr, dnsserver); } @@ -152,7 +152,7 @@ apply_tcpipconfig(void) #if UIP_UDP nullterminate(dnsserver); if(uiplib_ipaddrconv(dnsserver, &addr)) { - resolv_conf(&addr); + uip_nameserver_update(&addr, UIP_NAMESERVER_INFINITE_LIFETIME); } #endif /* UIP_UDP */ } diff --git a/apps/shell/shell-download.c b/apps/shell/shell-download.c index 86ad20207..7c2d419e8 100644 --- a/apps/shell/shell-download.c +++ b/apps/shell/shell-download.c @@ -31,9 +31,11 @@ */ /** - * \file Shell command for downloading files from a remote node. + * \file + * + * Shell command for downloading files from a remote node. * Example usage: - * 'download | write \ | write \'. * * \author Luca Mottola , Fredrik Osterlind */ diff --git a/core/cfs/cfs-coffee.c b/core/cfs/cfs-coffee.c index f4e7a26c1..d7f55a7c2 100644 --- a/core/cfs/cfs-coffee.c +++ b/core/cfs/cfs-coffee.c @@ -35,12 +35,12 @@ * Coffee: A file system for a variety of storage types in * memory-constrained devices. * - * For further information, see "Enabling Large-Scale Storage in - * Sensor Networks with the Coffee File System" in the proceedings + * For further information, see "Enabling Large-Scale Storage in + * Sensor Networks with the Coffee File System" in the proceedings * of ACM/IEEE IPSN 2009. * * \author - * Nicolas Tsiftes + * Nicolas Tsiftes */ #include @@ -62,23 +62,23 @@ /* Micro logs enable modifications on storage types that do not support in-place updates. This applies primarily to flash memories. */ #ifndef COFFEE_MICRO_LOGS -#define COFFEE_MICRO_LOGS 1 +#define COFFEE_MICRO_LOGS 1 #endif -/* If the files are expected to be appended to only, this parameter +/* If the files are expected to be appended to only, this parameter can be set to save some code space. */ #ifndef COFFEE_APPEND_ONLY -#define COFFEE_APPEND_ONLY 0 +#define COFFEE_APPEND_ONLY 0 #endif #if COFFEE_MICRO_LOGS && COFFEE_APPEND_ONLY #error "Cannot have COFFEE_APPEND_ONLY set when COFFEE_MICRO_LOGS is set." #endif -/* I/O semantics can be set on file descriptors in order to optimize +/* I/O semantics can be set on file descriptors in order to optimize file access on certain storage types. */ #ifndef COFFEE_IO_SEMANTICS -#define COFFEE_IO_SEMANTICS 0 +#define COFFEE_IO_SEMANTICS 0 #endif /* @@ -87,72 +87,72 @@ * to longer garbage collection procedures. */ #ifndef COFFEE_EXTENDED_WEAR_LEVELLING -#define COFFEE_EXTENDED_WEAR_LEVELLING 1 +#define COFFEE_EXTENDED_WEAR_LEVELLING 1 #endif #if COFFEE_START & (COFFEE_SECTOR_SIZE - 1) #error COFFEE_START must point to the first byte in a sector. #endif -#define COFFEE_FD_FREE 0x0 -#define COFFEE_FD_READ 0x1 -#define COFFEE_FD_WRITE 0x2 -#define COFFEE_FD_APPEND 0x4 +#define COFFEE_FD_FREE 0x0 +#define COFFEE_FD_READ 0x1 +#define COFFEE_FD_WRITE 0x2 +#define COFFEE_FD_APPEND 0x4 -#define COFFEE_FILE_MODIFIED 0x1 +#define COFFEE_FILE_MODIFIED 0x1 -#define INVALID_PAGE ((coffee_page_t)-1) -#define UNKNOWN_OFFSET ((cfs_offset_t)-1) +#define INVALID_PAGE ((coffee_page_t)-1) +#define UNKNOWN_OFFSET ((cfs_offset_t)-1) -#define REMOVE_LOG 1 -#define CLOSE_FDS 1 -#define ALLOW_GC 1 +#define REMOVE_LOG 1 +#define CLOSE_FDS 1 +#define ALLOW_GC 1 /* "Greedy" garbage collection erases as many sectors as possible. */ -#define GC_GREEDY 0 +#define GC_GREEDY 0 /* "Reluctant" garbage collection stops after erasing one sector. */ -#define GC_RELUCTANT 1 +#define GC_RELUCTANT 1 /* File descriptor macros. */ -#define FD_VALID(fd) \ - ((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \ - coffee_fd_set[(fd)].flags != COFFEE_FD_FREE) -#define FD_READABLE(fd) (coffee_fd_set[(fd)].flags & CFS_READ) -#define FD_WRITABLE(fd) (coffee_fd_set[(fd)].flags & CFS_WRITE) -#define FD_APPENDABLE(fd) (coffee_fd_set[(fd)].flags & CFS_APPEND) +#define FD_VALID(fd) \ + ((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \ + coffee_fd_set[(fd)].flags != COFFEE_FD_FREE) +#define FD_READABLE(fd) (coffee_fd_set[(fd)].flags & CFS_READ) +#define FD_WRITABLE(fd) (coffee_fd_set[(fd)].flags & CFS_WRITE) +#define FD_APPENDABLE(fd) (coffee_fd_set[(fd)].flags & CFS_APPEND) /* File object macros. */ -#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED) -#define FILE_FREE(file) ((file)->max_pages == 0) -#define FILE_UNREFERENCED(file) ((file)->references == 0) +#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED) +#define FILE_FREE(file) ((file)->max_pages == 0) +#define FILE_UNREFERENCED(file) ((file)->references == 0) /* File header flags. */ -#define HDR_FLAG_VALID 0x1 /* Completely written header. */ -#define HDR_FLAG_ALLOCATED 0x2 /* Allocated file. */ -#define HDR_FLAG_OBSOLETE 0x4 /* File marked for GC. */ -#define HDR_FLAG_MODIFIED 0x8 /* Modified file, log exists. */ -#define HDR_FLAG_LOG 0x10 /* Log file. */ -#define HDR_FLAG_ISOLATED 0x20 /* Isolated page. */ +#define HDR_FLAG_VALID 0x1 /* Completely written header. */ +#define HDR_FLAG_ALLOCATED 0x2 /* Allocated file. */ +#define HDR_FLAG_OBSOLETE 0x4 /* File marked for GC. */ +#define HDR_FLAG_MODIFIED 0x8 /* Modified file, log exists. */ +#define HDR_FLAG_LOG 0x10 /* Log file. */ +#define HDR_FLAG_ISOLATED 0x20 /* Isolated page. */ /* File header macros. */ -#define CHECK_FLAG(hdr, flag) ((hdr).flags & (flag)) -#define HDR_VALID(hdr) CHECK_FLAG(hdr, HDR_FLAG_VALID) -#define HDR_ALLOCATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ALLOCATED) -#define HDR_FREE(hdr) !HDR_ALLOCATED(hdr) -#define HDR_LOG(hdr) CHECK_FLAG(hdr, HDR_FLAG_LOG) -#define HDR_MODIFIED(hdr) CHECK_FLAG(hdr, HDR_FLAG_MODIFIED) -#define HDR_ISOLATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ISOLATED) -#define HDR_OBSOLETE(hdr) CHECK_FLAG(hdr, HDR_FLAG_OBSOLETE) -#define HDR_ACTIVE(hdr) (HDR_ALLOCATED(hdr) && \ - !HDR_OBSOLETE(hdr) && \ - !HDR_ISOLATED(hdr)) +#define CHECK_FLAG(hdr, flag) ((hdr).flags & (flag)) +#define HDR_VALID(hdr) CHECK_FLAG(hdr, HDR_FLAG_VALID) +#define HDR_ALLOCATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ALLOCATED) +#define HDR_FREE(hdr) !HDR_ALLOCATED(hdr) +#define HDR_LOG(hdr) CHECK_FLAG(hdr, HDR_FLAG_LOG) +#define HDR_MODIFIED(hdr) CHECK_FLAG(hdr, HDR_FLAG_MODIFIED) +#define HDR_ISOLATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ISOLATED) +#define HDR_OBSOLETE(hdr) CHECK_FLAG(hdr, HDR_FLAG_OBSOLETE) +#define HDR_ACTIVE(hdr) (HDR_ALLOCATED(hdr) && \ + !HDR_OBSOLETE(hdr) && \ + !HDR_ISOLATED(hdr)) /* Shortcuts derived from the hardware-dependent configuration of Coffee. */ -#define COFFEE_SECTOR_COUNT (unsigned)(COFFEE_SIZE / COFFEE_SECTOR_SIZE) -#define COFFEE_PAGE_COUNT \ - ((coffee_page_t)(COFFEE_SIZE / COFFEE_PAGE_SIZE)) -#define COFFEE_PAGES_PER_SECTOR \ - ((coffee_page_t)(COFFEE_SECTOR_SIZE / COFFEE_PAGE_SIZE)) +#define COFFEE_SECTOR_COUNT (unsigned)(COFFEE_SIZE / COFFEE_SECTOR_SIZE) +#define COFFEE_PAGE_COUNT \ + ((coffee_page_t)(COFFEE_SIZE / COFFEE_PAGE_SIZE)) +#define COFFEE_PAGES_PER_SECTOR \ + ((coffee_page_t)(COFFEE_SECTOR_SIZE / COFFEE_PAGE_SIZE)) /* This structure is used for garbage collection statistics. */ struct sector_status { @@ -181,7 +181,7 @@ struct file_desc { #endif }; -/* The file header structure mimics the representation of file headers +/* The file header structure mimics the representation of file headers in the physical storage medium. */ struct file_header { coffee_page_t log_page; @@ -201,9 +201,9 @@ struct log_param { }; /* - * The protected memory consists of structures that should not be - * overwritten during system checkpointing because they may be used by - * the checkpointing implementation. These structures need not be + * The protected memory consists of structures that should not be + * overwritten during system checkpointing because they may be used by + * the checkpointing implementation. These structures need not be * protected if checkpointing is not used. */ static struct protected_mem_t { @@ -212,10 +212,10 @@ static struct protected_mem_t { coffee_page_t next_free; char gc_wait; } protected_mem; -static struct file * const coffee_files = protected_mem.coffee_files; -static struct file_desc * const coffee_fd_set = protected_mem.coffee_fd_set; -static coffee_page_t * const next_free = &protected_mem.next_free; -static char * const gc_wait = &protected_mem.gc_wait; +static struct file *const coffee_files = protected_mem.coffee_files; +static struct file_desc *const coffee_fd_set = protected_mem.coffee_fd_set; +static coffee_page_t *const next_free = &protected_mem.next_free; +static char *const gc_wait = &protected_mem.gc_wait; /*---------------------------------------------------------------------------*/ static void @@ -256,8 +256,8 @@ get_sector_status(uint16_t sector, struct sector_status *stats) active = obsolete = free = 0; /* - * get_sector_status() is an iterative function using local static - * state. It therefore requires that the caller starts iterating from + * get_sector_status() is an iterative function using local static + * state. It therefore requires that the caller starts iterating from * sector 0 in order to reset the internal state. */ if(sector == 0) { @@ -269,8 +269,8 @@ get_sector_status(uint16_t sector, struct sector_status *stats) sector_end = sector_start + COFFEE_PAGES_PER_SECTOR; /* - * Account for pages belonging to a file starting in a previous - * segment that extends into this segment. If the whole segment is + * Account for pages belonging to a file starting in a previous + * segment that extends into this segment. If the whole segment is * covered, we do not need to continue counting pages in this iteration. */ if(last_pages_are_active) { @@ -289,7 +289,7 @@ get_sector_status(uint16_t sector, struct sector_status *stats) obsolete = skip_pages; } - /* Determine the amount of pages of each type that have not been + /* Determine the amount of pages of each type that have not been accounted for yet in the current sector. */ for(page = sector_start + skip_pages; page < sector_end;) { read_header(&hdr, page); @@ -312,10 +312,10 @@ get_sector_status(uint16_t sector, struct sector_status *stats) /* * Determine the amount of pages in the following sectors that - * should be remembered for the next iteration. This is necessary - * because no page except the first of a file contains information + * should be remembered for the next iteration. This is necessary + * because no page except the first of a file contains information * about what type of page it is. A side effect of remembering this - * amount is that there is no need to read in the headers of each + * amount is that there is no need to read in the headers of each * of these pages from the storage. */ skip_pages = active + obsolete + free - COFFEE_PAGES_PER_SECTOR; @@ -332,14 +332,14 @@ get_sector_status(uint16_t sector, struct sector_status *stats) stats->free = free; /* - * To avoid unnecessary page isolation, we notify the caller that - * "skip_pages" pages should be isolated only if the current file extent - * ends in the next sector. If the file extent ends in a more distant - * sector, however, the garbage collection can free the next sector - * immediately without requiring page isolation. + * To avoid unnecessary page isolation, we notify the caller that + * "skip_pages" pages should be isolated only if the current file extent + * ends in the next sector. If the file extent ends in a more distant + * sector, however, the garbage collection can free the next sector + * immediately without requiring page isolation. */ return (last_pages_are_active || (skip_pages >= COFFEE_PAGES_PER_SECTOR)) ? - 0 : skip_pages; + 0 : skip_pages; } /*---------------------------------------------------------------------------*/ static void @@ -359,7 +359,6 @@ isolate_pages(coffee_page_t start, coffee_page_t skip_pages) } PRINTF("Coffee: Isolated %u pages starting in sector %d\n", (unsigned)skip_pages, (int)start / COFFEE_PAGES_PER_SECTOR); - } /*---------------------------------------------------------------------------*/ static void @@ -370,7 +369,7 @@ collect_garbage(int mode) coffee_page_t first_page, isolation_count; PRINTF("Coffee: Running the file system garbage collector in %s mode\n", - mode == GC_RELUCTANT ? "reluctant" : "greedy"); + mode == GC_RELUCTANT ? "reluctant" : "greedy"); /* * The garbage collector erases as many sectors as possible. A sector is * erasable if there are only free or obsolete pages in it. @@ -378,8 +377,8 @@ collect_garbage(int mode) for(sector = 0; sector < COFFEE_SECTOR_COUNT; sector++) { isolation_count = get_sector_status(sector, &stats); PRINTF("Coffee: Sector %u has %u active, %u obsolete, and %u free pages.\n", - sector, (unsigned)stats.active, - (unsigned)stats.obsolete, (unsigned)stats.free); + sector, (unsigned)stats.active, + (unsigned)stats.obsolete, (unsigned)stats.free); if(stats.active > 0) { continue; @@ -410,13 +409,13 @@ static coffee_page_t next_file(coffee_page_t page, struct file_header *hdr) { /* - * The quick-skip algorithm for finding file extents is the most - * essential part of Coffee. The file allocation rules enables this - * algorithm to quickly jump over free areas and allocated extents + * The quick-skip algorithm for finding file extents is the most + * essential part of Coffee. The file allocation rules enables this + * algorithm to quickly jump over free areas and allocated extents * after reading single headers and determining their status. * - * The worst-case performance occurs when we encounter multiple long - * sequences of isolated pages, but such sequences are uncommon and + * The worst-case performance occurs when we encounter multiple long + * sequences of isolated pages, but such sequences are uncommon and * always shorter than a sector. */ if(HDR_FREE(*hdr)) { @@ -424,7 +423,7 @@ next_file(coffee_page_t page, struct file_header *hdr) } else if(HDR_ISOLATED(*hdr)) { return page + 1; } - return page + hdr->max_pages; + return page + hdr->max_pages; } /*---------------------------------------------------------------------------*/ static struct file * @@ -475,7 +474,7 @@ find_file(const char *name) int i; struct file_header hdr; coffee_page_t page; - + /* First check if the file metadata is cached. */ for(i = 0; i < COFFEE_MAX_OPEN_FILES; i++) { if(FILE_FREE(&coffee_files[i])) { @@ -487,7 +486,7 @@ find_file(const char *name) return &coffee_files[i]; } } - + /* Scan the flash memory sequentially otherwise. */ for(page = 0; page < COFFEE_PAGE_COUNT; page = next_file(page, &hdr)) { read_header(&hdr, page); @@ -521,10 +520,10 @@ file_end(coffee_page_t start) COFFEE_READ(buf, sizeof(buf), (start + page) * COFFEE_PAGE_SIZE); for(i = COFFEE_PAGE_SIZE - 1; i >= 0; i--) { if(buf[i] != 0) { - if(page == 0 && i < sizeof(hdr)) { - return 0; - } - return 1 + i + (page * COFFEE_PAGE_SIZE) - sizeof(hdr); + if(page == 0 && i < sizeof(hdr)) { + return 0; + } + return 1 + i + (page * COFFEE_PAGE_SIZE) - sizeof(hdr); } } } @@ -544,7 +543,7 @@ find_contiguous_pages(coffee_page_t amount) read_header(&hdr, page); if(HDR_FREE(hdr)) { if(start == INVALID_PAGE) { - start = page; + start = page; if(start + amount >= COFFEE_PAGE_COUNT) { /* We can stop immediately if the remaining pages are not enough. */ break; @@ -557,9 +556,9 @@ find_contiguous_pages(coffee_page_t amount) if(start + amount <= page) { if(start == *next_free) { - *next_free = start + amount; - } - return start; + *next_free = start + amount; + } + return start; } } else { start = INVALID_PAGE; @@ -596,7 +595,7 @@ remove_by_page(coffee_page_t page, int remove_log, int close_fds, if(close_fds) { for(i = 0; i < COFFEE_FD_SET_SIZE; i++) { if(coffee_fd_set[i].file != NULL && coffee_fd_set[i].file->page == page) { - coffee_fd_set[i].flags = COFFEE_FD_FREE; + coffee_fd_set[i].flags = COFFEE_FD_FREE; } } } @@ -622,12 +621,12 @@ static coffee_page_t page_count(cfs_offset_t size) { return (size + sizeof(struct file_header) + COFFEE_PAGE_SIZE - 1) / - COFFEE_PAGE_SIZE; + COFFEE_PAGE_SIZE; } /*---------------------------------------------------------------------------*/ static struct file * reserve(const char *name, coffee_page_t pages, - int allow_duplicates, unsigned flags) + int allow_duplicates, unsigned flags) { struct file_header hdr; coffee_page_t page; @@ -657,7 +656,7 @@ reserve(const char *name, coffee_page_t pages, write_header(&hdr, page); PRINTF("Coffee: Reserved %u pages starting from %u for file %s\n", - pages, page, name); + pages, page, name); file = load_file(page, &hdr); if(file != NULL) { @@ -670,19 +669,19 @@ reserve(const char *name, coffee_page_t pages, #if COFFEE_MICRO_LOGS static void adjust_log_config(struct file_header *hdr, - uint16_t *log_record_size, uint16_t *log_records) + uint16_t *log_record_size, uint16_t *log_records) { *log_record_size = hdr->log_record_size == 0 ? - COFFEE_PAGE_SIZE : hdr->log_record_size; + COFFEE_PAGE_SIZE : hdr->log_record_size; *log_records = hdr->log_records == 0 ? - COFFEE_LOG_SIZE / *log_record_size : hdr->log_records; + COFFEE_LOG_SIZE / *log_record_size : hdr->log_records; } #endif /* COFFEE_MICRO_LOGS */ /*---------------------------------------------------------------------------*/ #if COFFEE_MICRO_LOGS static uint16_t modify_log_buffer(uint16_t log_record_size, - cfs_offset_t *offset, uint16_t *size) + cfs_offset_t *offset, uint16_t *size) { uint16_t region; @@ -700,7 +699,7 @@ modify_log_buffer(uint16_t log_record_size, #if COFFEE_MICRO_LOGS static int get_record_index(coffee_page_t log_page, uint16_t search_records, - uint16_t region) + uint16_t region) { cfs_offset_t base; uint16_t processed; @@ -709,30 +708,30 @@ get_record_index(coffee_page_t log_page, uint16_t search_records, base = absolute_offset(log_page, sizeof(uint16_t) * search_records); batch_size = search_records > COFFEE_LOG_TABLE_LIMIT ? - COFFEE_LOG_TABLE_LIMIT : search_records; + COFFEE_LOG_TABLE_LIMIT : search_records; processed = 0; match_index = -1; { - uint16_t indices[batch_size]; + uint16_t indices[batch_size]; - while(processed < search_records && match_index < 0) { - if(batch_size + processed > search_records) { - batch_size = search_records - processed; - } - - base -= batch_size * sizeof(indices[0]); - COFFEE_READ(&indices, sizeof(indices[0]) * batch_size, base); - - for(i = batch_size - 1; i >= 0; i--) { - if(indices[i] - 1 == region) { - match_index = search_records - processed - (batch_size - i); - break; + while(processed < search_records && match_index < 0) { + if(batch_size + processed > search_records) { + batch_size = search_records - processed; } - } - processed += batch_size; - } + base -= batch_size * sizeof(indices[0]); + COFFEE_READ(&indices, sizeof(indices[0]) * batch_size, base); + + for(i = batch_size - 1; i >= 0; i--) { + if(indices[i] - 1 == region) { + match_index = search_records - processed - (batch_size - i); + break; + } + } + + processed += batch_size; + } } return match_index; @@ -839,7 +838,7 @@ merge_log(coffee_page_t file_page, int extend) } while(n != 0); for(i = 0; i < COFFEE_FD_SET_SIZE; i++) { - if(coffee_fd_set[i].flags != COFFEE_FD_FREE && + if(coffee_fd_set[i].flags != COFFEE_FD_FREE && coffee_fd_set[i].file->page == file_page) { coffee_fd_set[i].file = new_file; new_file->references++; @@ -869,7 +868,7 @@ merge_log(coffee_page_t file_page, int extend) #if COFFEE_MICRO_LOGS static int find_next_record(struct file *file, coffee_page_t log_page, - int log_records) + int log_records) { int log_record, preferred_batch_size; @@ -878,7 +877,7 @@ find_next_record(struct file *file, coffee_page_t log_page, } preferred_batch_size = log_records > COFFEE_LOG_TABLE_LIMIT ? - COFFEE_LOG_TABLE_LIMIT : log_records; + COFFEE_LOG_TABLE_LIMIT : log_records; { /* The next log record is unknown at this point; search for it. */ uint16_t indices[preferred_batch_size]; @@ -888,15 +887,15 @@ find_next_record(struct file *file, coffee_page_t log_page, log_record = log_records; for(processed = 0; processed < log_records; processed += batch_size) { batch_size = log_records - processed >= preferred_batch_size ? - preferred_batch_size : log_records - processed; + preferred_batch_size : log_records - processed; COFFEE_READ(&indices, batch_size * sizeof(indices[0]), - absolute_offset(log_page, processed * sizeof(indices[0]))); + absolute_offset(log_page, processed * sizeof(indices[0]))); for(log_record = 0; log_record < batch_size; log_record++) { - if(indices[log_record] == 0) { - log_record += processed; - break; - } + if(indices[log_record] == 0) { + log_record += processed; + break; + } } } } @@ -940,7 +939,7 @@ write_log_page(struct file *file, struct log_param *lp) return -1; } PRINTF("Coffee: Created a log structure for file %s at page %u\n", - hdr.name, (unsigned)log_page); + hdr.name, (unsigned)log_page); hdr.log_page = log_page; log_record = 0; } @@ -953,9 +952,9 @@ write_log_page(struct file *file, struct log_param *lp) lp_out.size = log_record_size; if((lp->offset > 0 || lp->size != log_record_size) && - read_log_page(&hdr, log_record, &lp_out) < 0) { + read_log_page(&hdr, log_record, &lp_out) < 0) { COFFEE_READ(copy_buf, sizeof(copy_buf), - absolute_offset(file->page, offset)); + absolute_offset(file->page, offset)); } memcpy(©_buf[lp->offset], lp->buf, lp->size); @@ -967,11 +966,11 @@ write_log_page(struct file *file, struct log_param *lp) offset = absolute_offset(log_page, 0); ++region; COFFEE_WRITE(®ion, sizeof(region), - offset + log_record * sizeof(region)); + offset + log_record * sizeof(region)); offset += log_records * sizeof(region); COFFEE_WRITE(copy_buf, sizeof(copy_buf), - offset + log_record * log_record_size); + offset + log_record * log_record_size); file->record_count = log_record + 1; } @@ -1171,7 +1170,7 @@ cfs_write(int fd, const void *buf, unsigned size) if(!(fdp->io_flags & CFS_COFFEE_IO_FIRM_SIZE)) { #endif while(size + fdp->offset + sizeof(struct file_header) > - (file->max_pages * COFFEE_PAGE_SIZE)) { + (file->max_pages * COFFEE_PAGE_SIZE)) { if(merge_log(file->page, 1) < 0) { return -1; } @@ -1179,7 +1178,7 @@ cfs_write(int fd, const void *buf, unsigned size) PRINTF("Extended the file at page %u\n", (unsigned)file->page); } #if COFFEE_IO_SEMANTICS - } +} #endif #if COFFEE_MICRO_LOGS @@ -1196,19 +1195,19 @@ cfs_write(int fd, const void *buf, unsigned size) lp.size = bytes_left; i = write_log_page(file, &lp); if(i < 0) { - /* Return -1 if we wrote nothing because the log write failed. */ - if(size == bytes_left) { - return -1; - } - break; + /* Return -1 if we wrote nothing because the log write failed. */ + if(size == bytes_left) { + return -1; + } + break; } else if(i == 0) { /* The file was merged with the log. */ - file = fdp->file; + file = fdp->file; } else { - /* A log record was written. */ - bytes_left -= i; - fdp->offset += i; - buf = (char *)buf + i; + /* A log record was written. */ + bytes_left -= i; + fdp->offset += i; + buf = (char *)buf + i; /* Update the file end for a potential log merge that might occur while writing log records. */ @@ -1231,15 +1230,15 @@ cfs_write(int fd, const void *buf, unsigned size) } else { #endif /* COFFEE_MICRO_LOGS */ #if COFFEE_APPEND_ONLY - if(fdp->offset < file->end) { - return -1; - } + if(fdp->offset < file->end) { + return -1; + } #endif /* COFFEE_APPEND_ONLY */ - COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset)); - fdp->offset += size; + COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset)); + fdp->offset += size; #if COFFEE_MICRO_LOGS - } +} #endif /* COFFEE_MICRO_LOGS */ if(fdp->offset > file->end) { @@ -1253,7 +1252,7 @@ int cfs_opendir(struct cfs_dir *dir, const char *name) { /* - * Coffee is only guaranteed to support "/" and ".", but it does not + * Coffee is only guaranteed to support "/" and ".", but it does not * currently enforce this. */ memset(dir->dummy_space, 0, sizeof(coffee_page_t)); @@ -1300,7 +1299,7 @@ cfs_coffee_reserve(const char *name, cfs_offset_t size) /*---------------------------------------------------------------------------*/ int cfs_coffee_configure_log(const char *filename, unsigned log_size, - unsigned log_record_size) + unsigned log_record_size) { struct file *file; struct file_header hdr; diff --git a/core/contiki-net.h b/core/contiki-net.h index d38d89344..087be23cb 100644 --- a/core/contiki-net.h +++ b/core/contiki-net.h @@ -44,6 +44,7 @@ #include "net/ip/uiplib.h" #include "net/ip/uip-udp-packet.h" #include "net/ip/simple-udp.h" +#include "net/ip/uip-nameserver.h" #if NETSTACK_CONF_WITH_IPV6 #include "net/ipv6/uip-icmp6.h" diff --git a/core/ctk/ctk-draw.h b/core/ctk/ctk-draw.h index 388596cea..2f5cb8816 100644 --- a/core/ctk/ctk-draw.h +++ b/core/ctk/ctk-draw.h @@ -201,6 +201,7 @@ void ctk_draw_clear_window(struct ctk_window *window, * drawn, in screen coordinates (line 1 is the first line below the * menus) * + * \param draw_borders The border style */ void ctk_draw_window(struct ctk_window *window, unsigned char focus, @@ -318,7 +319,7 @@ extern unsigned char ctk_draw_windowborder_width, /** * The character used for the Return/Enter key. * - * \define #define CH_ENTER '\n' + * \#define CH_ENTER '\n' */ /** diff --git a/core/lib/crc16.h b/core/lib/crc16.h index 03aa94ea7..e243f546e 100644 --- a/core/lib/crc16.h +++ b/core/lib/crc16.h @@ -77,7 +77,7 @@ unsigned short crc16_add(unsigned char b, unsigned short crc); * \brief Calculate the CRC16 over a data area * \param data Pointer to the data * \param datalen The length of the data - * \param crc The accumulated CRC that is to be updated (or zero). + * \param acc The accumulated CRC that is to be updated (or zero). * \return The CRC16 checksum. * * This function calculates the CRC16 checksum of a data area. diff --git a/core/net/ip/resolv.c b/core/net/ip/resolv.c index 5df53ecac..4a9999cca 100644 --- a/core/net/ip/resolv.c +++ b/core/net/ip/resolv.c @@ -65,6 +65,7 @@ #include "net/ip/tcpip.h" #include "net/ip/resolv.h" #include "net/ip/uip-udp-packet.h" +#include "net/ip/uip-nameserver.h" #include "lib/random.h" #ifndef DEBUG @@ -227,17 +228,6 @@ struct dns_hdr { uint16_t numextrarr; }; -/** These default values for the DNS server are Google's public DNS: - * - */ -static uip_ipaddr_t resolv_default_dns_server = -#if NETSTACK_CONF_WITH_IPV6 - { { 0x20, 0x01, 0x48, 0x60, 0x48, 0x60, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x88 } }; -#else /* NETSTACK_CONF_WITH_IPV6 */ - { { 8, 8, 8, 8 } }; -#endif /* NETSTACK_CONF_WITH_IPV6 */ - /** \internal The DNS answer message structure. */ struct dns_answer { /* DNS answer record starts with either a domain name or a pointer @@ -269,6 +259,7 @@ struct namemap { #endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */ uip_ipaddr_t ipaddr; uint8_t err; + uint8_t server; #if RESOLV_CONF_SUPPORTS_MDNS int is_mdns:1, is_probe:1; #endif @@ -637,6 +628,21 @@ mdns_prep_host_announce_packet(void) } #endif /* RESOLV_CONF_SUPPORTS_MDNS */ /*---------------------------------------------------------------------------*/ +static char +try_next_server(struct namemap *namemapptr) +{ +#if VERBOSE_DEBUG + printf("server %d\n", namemapptr->server); +#endif + namemapptr->server++; + if(uip_nameserver_get(namemapptr->server) != NULL) { + namemapptr->retries = 0; + return 1; + } + namemapptr->server = 0; + return 0; +} +/*---------------------------------------------------------------------------*/ /** \internal * Runs through the list of names to see if there are any that have * not yet been queried and, if so, sends out a query. @@ -666,16 +672,20 @@ check_entries(void) if(++namemapptr->retries == RESOLV_CONF_MAX_RETRIES) #endif /* RESOLV_CONF_SUPPORTS_MDNS */ { - /* STATE_ERROR basically means "not found". */ - namemapptr->state = STATE_ERROR; + /* Try the next server (if possible) before failing. Otherwise + simply mark the entry as failed. */ + if(try_next_server(namemapptr) == 0) { + /* STATE_ERROR basically means "not found". */ + namemapptr->state = STATE_ERROR; #if RESOLV_SUPPORTS_RECORD_EXPIRATION - /* Keep the "not found" error valid for 30 seconds */ - namemapptr->expiration = clock_seconds() + 30; + /* Keep the "not found" error valid for 30 seconds */ + namemapptr->expiration = clock_seconds() + 30; #endif /* RESOLV_SUPPORTS_RECORD_EXPIRATION */ - resolv_found(namemapptr->name, NULL); - continue; + resolv_found(namemapptr->name, NULL); + continue; + } } namemapptr->tmr = namemapptr->retries * namemapptr->retries * 3; @@ -747,7 +757,9 @@ check_entries(void) } else { uip_udp_packet_sendto(resolv_conn, uip_appdata, (query - (uint8_t *) uip_appdata), - &resolv_default_dns_server, UIP_HTONS(DNS_PORT)); + (const uip_ipaddr_t *) + uip_nameserver_get(namemapptr->server), + UIP_HTONS(DNS_PORT)); PRINTF("resolver: (i=%d) Sent DNS request for \"%s\".\n", i, namemapptr->name); @@ -755,7 +767,8 @@ check_entries(void) #else /* RESOLV_CONF_SUPPORTS_MDNS */ uip_udp_packet_sendto(resolv_conn, uip_appdata, (query - (uint8_t *) uip_appdata), - &resolv_default_dns_server, UIP_HTONS(DNS_PORT)); + uip_nameserver_get(namemapptr->server), + UIP_HTONS(DNS_PORT)); PRINTF("resolver: (i=%d) Sent DNS request for \"%s\".\n", i, namemapptr->name); #endif /* RESOLV_CONF_SUPPORTS_MDNS */ @@ -1041,11 +1054,28 @@ newdata(void) uip_ipaddr_copy(&namemapptr->ipaddr, (uip_ipaddr_t *) ans->ipaddr); resolv_found(namemapptr->name, &namemapptr->ipaddr); + break; skip_to_next_answer: queryptr = (unsigned char *)skip_name(queryptr) + 10 + uip_htons(ans->len); --nanswers; } + + /* Got to this point there's no answer, try next nameserver if available + since this one doesn't know the answer */ +#if RESOLV_CONF_SUPPORTS_MDNS + if(nanswers == 0 && UIP_UDP_BUF->srcport != UIP_HTONS(MDNS_PORT) + && hdr->id != 0) +#else + if(nanswers == 0) +#endif + { + if(try_next_server(namemapptr)) { + namemapptr->state = STATE_ASKING; + process_post(&resolv_process, PROCESS_EVENT_TIMER, NULL); + } + } + } /*---------------------------------------------------------------------------*/ #if RESOLV_CONF_SUPPORTS_MDNS @@ -1405,31 +1435,6 @@ resolv_lookup(const char *name, uip_ipaddr_t ** ipaddr) return ret; } /*---------------------------------------------------------------------------*/ -/** - * Obtain the currently configured DNS server. - * - * \return A pointer to a 4-byte representation of the IP address of - * the currently configured DNS server or NULL if no DNS server has - * been configured. - */ -uip_ipaddr_t * -resolv_getserver(void) -{ - return &resolv_default_dns_server; -} -/*---------------------------------------------------------------------------*/ -/** - * Configure a DNS server. - * - * \param dnsserver A pointer to a 4-byte representation of the IP - * address of the DNS server to be configured. - */ -void -resolv_conf(const uip_ipaddr_t * dnsserver) -{ - uip_ipaddr_copy(&resolv_default_dns_server, dnsserver); -} -/*---------------------------------------------------------------------------*/ /** \internal * Callback function which is called when a hostname is found. * diff --git a/core/net/ip/resolv.h b/core/net/ip/resolv.h index cf1fef7e0..ed24d5bce 100644 --- a/core/net/ip/resolv.h +++ b/core/net/ip/resolv.h @@ -57,11 +57,6 @@ */ CCIF extern process_event_t resolv_event_found; -/* Functions. */ -CCIF void resolv_conf(const uip_ipaddr_t * dnsserver); - -CCIF uip_ipaddr_t *resolv_getserver(void); - enum { /** Hostname is fresh and usable. This response is cached and will eventually * expire to RESOLV_STATUS_EXPIRED.*/ @@ -95,6 +90,7 @@ enum { typedef uint8_t resolv_status_t; +/* Functions. */ CCIF resolv_status_t resolv_lookup(const char *name, uip_ipaddr_t ** ipaddr); CCIF void resolv_query(const char *name); diff --git a/core/net/ip/simple-udp.h b/core/net/ip/simple-udp.h index ad4ac53ac..c28ce3e2c 100644 --- a/core/net/ip/simple-udp.h +++ b/core/net/ip/simple-udp.h @@ -142,7 +142,7 @@ int simple_udp_sendto(struct simple_udp_connection *c, * \param data A pointer to the data to be sent * \param datalen The length of the data * \param to The IP address of the receiver - * \param port The UDP port of the receiver, in host byte order + * \param to_port The UDP port of the receiver, in host byte order * * This function sends a UDP packet to a specified IP * address and UDP port. The packet will be sent with the diff --git a/core/net/ip/uip-nameserver.c b/core/net/ip/uip-nameserver.c new file mode 100644 index 000000000..6ced6b91e --- /dev/null +++ b/core/net/ip/uip-nameserver.c @@ -0,0 +1,234 @@ +/** + * \addtogroup uip6 + * @{ + */ + +/** + * \file + * uIP Name Server interface + * \author Víctor Ariño + */ + +/* + * Copyright (c) 2014, tado° GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +#include "contiki.h" +#include "contiki-net.h" + +#include "lib/list.h" +#include "lib/memb.h" + +#include +/** \brief Nameserver record */ +typedef struct uip_nameserver_record { + struct uip_nameserver_record *next; + uip_ipaddr_t ip; + uint32_t added; + uint32_t lifetime; +} uip_nameserver_record; + +/** \brief Initialization flag */ +static uint8_t initialized = 0; + +/** \name List and memory block + * @{ + */ +#if UIP_NAMESERVER_POOL_SIZE > 1 +LIST(dns); +MEMB(dnsmemb, uip_nameserver_record, UIP_NAMESERVER_POOL_SIZE); +#else /* UIP_NAMESERVER_POOL_SIZE > 1 */ +static uip_ipaddr_t serveraddr; +static uint32_t serverlifetime; +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +/** @} */ + +/** \brief Expiration time in seconds */ +#define DNS_EXPIRATION(r) \ + (((UIP_NAMESERVER_INFINITE_LIFETIME - r->added) <= r->lifetime) ? \ + UIP_NAMESERVER_INFINITE_LIFETIME : r->added + r->lifetime) +/*----------------------------------------------------------------------------*/ +/** + * Initialize the module variables + */ +#if UIP_NAMESERVER_POOL_SIZE > 1 +static CC_INLINE void +init(void) +{ + list_init(dns); + memb_init(&dnsmemb); + initialized = 1; +} +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +/*----------------------------------------------------------------------------*/ +void +uip_nameserver_update(uip_ipaddr_t *nameserver, uint32_t lifetime) +{ +#if UIP_NAMESERVER_POOL_SIZE > 1 + register uip_nameserver_record *e; + + if(initialized == 0) { + init(); + } + + for(e = list_head(dns); e != NULL; e = list_item_next(e)) { + if(uip_ipaddr_cmp(&e->ip, nameserver)) { + break; + /* RFC6106: In case there's no more space, the new servers should replace + * the the eldest ones */ + } + } + + if(e == NULL) { + if((e = memb_alloc(&dnsmemb)) != NULL) { + list_add(dns, e); + } else { + uip_nameserver_record *p; + for(e = list_head(dns), p = list_head(dns); p != NULL; + p = list_item_next(p)) { + if(DNS_EXPIRATION(p) < DNS_EXPIRATION(e)) { + e = p; + } + } + } + } + + /* RFC6106: In case the entry is existing the expiration time must be + * updated. Otherwise, new entries are added. */ + if(e != NULL) { + if(lifetime == 0) { + memb_free(&dnsmemb, e); + list_remove(dns, e); + } else { + e->added = clock_seconds(); + e->lifetime = lifetime; + uip_ipaddr_copy(&e->ip, nameserver); + } + } +#else /* UIP_NAMESERVER_POOL_SIZE > 1 */ + uip_ipaddr_copy(&serveraddr, nameserver); + serverlifetime = lifetime; +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +} +/*----------------------------------------------------------------------------*/ +#if UIP_NAMESERVER_POOL_SIZE > 1 +/** + * Purge expired records + */ +static void +purge(void) +{ + register uip_nameserver_record *e = NULL; + uint32_t time = clock_seconds(); + for(e = list_head(dns); e != NULL; e = list_item_next(e)) { + if(DNS_EXPIRATION(e) < time) { + list_remove(dns, e); + memb_free(&dnsmemb, e); + e = list_head(dns); + } + } +} +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +/*----------------------------------------------------------------------------*/ +uip_ipaddr_t * +uip_nameserver_get(uint8_t num) +{ +#if UIP_NAMESERVER_POOL_SIZE > 1 + uint8_t i; + uip_nameserver_record *e = NULL; + + if(initialized == 0) { + return NULL; + } + purge(); + for(i = 1, e = list_head(dns); e != NULL && i <= num; + i++, e = list_item_next(e)) { + } + + if(e != NULL) { + return &e->ip; + } + return NULL; +#else /* UIP_NAMESERVER_POOL_SIZE > 1 */ + if(num > 0) { + return NULL; + } + return &serveraddr; +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +} +/*----------------------------------------------------------------------------*/ +uint32_t +uip_nameserver_next_expiration(void) +{ +#if UIP_NAMESERVER_POOL_SIZE > 1 + register uip_nameserver_record *e = NULL; + uint32_t exp = UIP_NAMESERVER_INFINITE_LIFETIME; + uint32_t t; + + if(initialized == 0 || list_length(dns) == 0) { + return 0; + } + purge(); + for(e = list_head(dns); e != NULL; e = list_item_next(e)) { + t = DNS_EXPIRATION(e); + if(t < exp) { + exp = t; + } + } + + return exp; +#else /* UIP_NAMESERVER_POOL_SIZE > 1 */ + return serverlifetime; +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +} +/*----------------------------------------------------------------------------*/ +uint16_t +uip_nameserver_count(void) +{ +#if UIP_NAMESERVER_POOL_SIZE > 1 + if(initialized == 0) { + return 0; + } + return list_length(dns); +#else /* UIP_NAMESERVER_POOL_SIZE > 1 */ +#if NETSTACK_CONF_WITH_IPV6 + if(uip_is_addr_unspecified(&serveraddr)) { +#else /* NETSTACK_CONF_WITH_IPV6 */ + if(uip_ipaddr_cmp(&serveraddr, &uip_all_zeroes_addr)) { +#endif /* NETSTACK_CONF_WITH_IPV6 */ + return 0; + } else { + return 1; + } +#endif /* UIP_NAMESERVER_POOL_SIZE > 1 */ +} +/*----------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ip/uip-nameserver.h b/core/net/ip/uip-nameserver.h new file mode 100644 index 000000000..41dcf58c8 --- /dev/null +++ b/core/net/ip/uip-nameserver.h @@ -0,0 +1,101 @@ +/** + * \addtogroup uip6 + * @{ + */ + +/** + * \file + * uIP Name Server interface + * \author Víctor Ariño + */ + +/* + * Copyright (c) 2014, tado° GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this 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. + * + */ + +#ifndef UIP_NAMESERVER_H_ +#define UIP_NAMESERVER_H_ + +/** + * \name General + * @{ + */ +/** \brief Number of Nameservers to keep */ +#ifndef UIP_CONF_NAMESERVER_POOL_SIZE +#define UIP_NAMESERVER_POOL_SIZE 1 +#else /* UIP_CONF_NAMESERVER_POOL_SIZE */ +#define UIP_NAMESERVER_POOL_SIZE UIP_CONF_NAMESERVER_POOL_SIZE +#endif /* UIP_CONF_NAMESERVER_POOL_SIZE */ +/** \brief Infinite Lifetime indicator */ +#define UIP_NAMESERVER_INFINITE_LIFETIME 0xFFFFFFFF +/** @} */ + +/** + * \name Nameserver maintenance + * @{ + */ +/** + * \brief Insert or update a nameserver into/from the pool + * + * The list is kept according to the RFC6106, which indicates that new entries + * will replace old ones (with lower lifetime) and existing entries will update + * their lifetimes. + * + * \param nameserver Pointer to the nameserver ip address + * \param lifetime Life time of the given address. Minimum is 0, which is + * considered to remove an entry. Maximum is 0xFFFFFFFF which + * is considered infinite. + */ +void uip_nameserver_update(uip_ipaddr_t *nameserver, uint32_t lifetime); + +/** + * \brief Get a Nameserver ip address given in RA + * + * \param num The number of the nameserver to obtain, starting at 0 and going + * up to the pool size. + */ +uip_ipaddr_t *uip_nameserver_get(uint8_t num); + +/** + * \brief Get next expiration time + * + * The least expiration time is returned + */ +uint32_t uip_nameserver_next_expiration(void); + +/** + * \brief Get the number of recorded name servers + */ +uint16_t uip_nameserver_count(void); +/** @} */ + +#endif /* UIP_NAMESERVER_H_ */ +/** @} */ diff --git a/core/net/ip/uip.h b/core/net/ip/uip.h index cfd095de2..78ebfef59 100644 --- a/core/net/ip/uip.h +++ b/core/net/ip/uip.h @@ -350,7 +350,7 @@ void uip_setipid(uint16_t id); * Periodic processing for a connection identified by its number. * * This function does the necessary periodic processing (timers, - * polling) for a uIP TCP conneciton, and should be called when the + * polling) for a uIP TCP connection, and should be called when the * periodic uIP timer goes off. It should be called for every * connection, regardless of whether they are open of closed. * @@ -393,8 +393,10 @@ void uip_setipid(uint16_t id); uip_process(UIP_TIMER); } while (0) /** + * Macro to determine whether a specific uIP connection is active * - * + * \param conn The connection's number + * \retval 0 Connection closed */ #define uip_conn_active(conn) (uip_conns[conn].tcpstateflags != UIP_CLOSED) @@ -489,7 +491,7 @@ void uip_reass_over(void); /** * The uIP packet buffer. * - * The uip_buf array is used to hold incoming and outgoing + * The uip_aligned_buf array is used to hold incoming and outgoing * packets. The device driver should place incoming data into this * buffer. When sending data, the device driver should read the link * level headers and the TCP/IP headers from this buffer. The size of @@ -519,6 +521,8 @@ typedef union { } uip_buf_t; CCIF extern uip_buf_t uip_aligned_buf; + +/** Macro to access uip_aligned_buf as an array of bytes */ #define uip_buf (uip_aligned_buf.u8) @@ -1097,7 +1101,7 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport); -/** +/* * Check if an address is a broadcast address for a network. * * Checks if an address is the broadcast address for a network. The @@ -2172,7 +2176,7 @@ CCIF extern uip_lladdr_t uip_lladdr; * * See RFC1071. * - * \param buf A pointer to the buffer over which the checksum is to be + * \param data A pointer to the buffer over which the checksum is to be * computed. * * \param len The length of the buffer over which the checksum is to @@ -2180,7 +2184,7 @@ CCIF extern uip_lladdr_t uip_lladdr; * * \return The Internet checksum of the buffer. */ -uint16_t uip_chksum(uint16_t *buf, uint16_t len); +uint16_t uip_chksum(uint16_t *data, uint16_t len); /** * Calculate the IP header checksum of the packet header in uip_buf. diff --git a/core/net/ip/uip_arch.h b/core/net/ip/uip_arch.h index a27548519..352a39711 100644 --- a/core/net/ip/uip_arch.h +++ b/core/net/ip/uip_arch.h @@ -93,7 +93,7 @@ void uip_add32(uint8_t *op32, uint16_t op16); * \note This function is not called in the current version of uIP, * but future versions might make use of it. * - * \param buf A pointer to the buffer over which the checksum is to be + * \param data A pointer to the buffer over which the checksum is to be * computed. * * \param len The length of the buffer over which the checksum is to @@ -101,7 +101,7 @@ void uip_add32(uint8_t *op32, uint16_t op16); * * \return The Internet checksum of the buffer. */ -uint16_t uip_chksum(uint16_t *buf, uint16_t len); +uint16_t uip_chksum(uint16_t *data, uint16_t len); /** * Calculate the IP header checksum of the packet header in uip_buf. diff --git a/core/net/ipv4/uip.c b/core/net/ipv4/uip.c index f1bb7257a..1c767e170 100644 --- a/core/net/ipv4/uip.c +++ b/core/net/ipv4/uip.c @@ -75,18 +75,9 @@ #include "net/ipv4/uip_arp.h" #include "net/ip/uip_arch.h" -#if !NETSTACK_CONF_WITH_IPV6 /* If NETSTACK_CONF_WITH_IPV6 is defined, we compile the - uip6.c file instead of this one. Therefore - this #ifndef removes the entire compilation - output of the uip.c file */ - - -#if NETSTACK_CONF_WITH_IPV6 #include "net/ipv4/uip-neighbor.h" -#endif /* NETSTACK_CONF_WITH_IPV6 */ #include - /*---------------------------------------------------------------------------*/ /* Variable definitions. */ @@ -699,7 +690,7 @@ uip_process(uint8_t flag) } goto drop; - /* Check if we were invoked because of the perodic timer fireing. */ + /* Check if we were invoked because of the periodic timer firing. */ } else if(flag == UIP_TIMER) { #if UIP_REASSEMBLY if(uip_reasstmr != 0) { @@ -851,7 +842,7 @@ uip_process(uint8_t flag) that the packet has been corrupted in transit. If the size of uip_len is larger than the size reported in the IP packet header, the packet has been padded and we set uip_len to the correct - value.. */ + value. */ if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) { uip_len = (BUF->len[0] << 8) + BUF->len[1]; @@ -891,7 +882,7 @@ uip_process(uint8_t flag) if(uip_ipaddr_cmp(&uip_hostaddr, &uip_all_zeroes_addr)) { /* If we are configured to use ping IP address configuration and - hasn't been assigned an IP address yet, we accept all ICMP + haven't been assigned an IP address yet, we accept all ICMP packets. */ #if UIP_PINGADDRCONF && !NETSTACK_CONF_WITH_IPV6 if(BUF->proto == UIP_PROTO_ICMP) { @@ -1252,7 +1243,7 @@ uip_process(uint8_t flag) } } - /* If we didn't find and active connection that expected the packet, + /* If we didn't find an active connection that expected the packet, either this packet is an old duplicate, or this is a SYN packet destined for a connection in LISTEN. If the SYN flag isn't set, it is an old packet and we send a RST. */ @@ -1441,7 +1432,7 @@ uip_process(uint8_t flag) uip_flags = 0; /* We do a very naive form of TCP reset processing; we just accept any RST and kill our connection. We should in fact check if the - sequence number of this reset is wihtin our advertised window + sequence number of this reset is within our advertised window before we accept the reset. */ if(BUF->flags & TCP_RST) { uip_connr->tcpstateflags = UIP_CLOSED; @@ -1973,6 +1964,4 @@ uip_send(const void *data, int len) } } /*---------------------------------------------------------------------------*/ -#endif /* NETSTACK_CONF_WITH_IPV6 */ - /** @}*/ diff --git a/core/net/ipv6/multicast/roll-tm.c b/core/net/ipv6/multicast/roll-tm.c index cfb4e66d5..20a562084 100644 --- a/core/net/ipv6/multicast/roll-tm.c +++ b/core/net/ipv6/multicast/roll-tm.c @@ -29,20 +29,15 @@ * This file is part of the Contiki operating system. */ +/** + * \addtogroup roll-tm + * @{ + */ /** * \file - * This file implements IPv6 MCAST forwarding according to the - * algorithm described in the "MCAST Forwarding Using Trickle" - * internet draft. - * - * The current version of the draft can always be found in - * http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast - * - * This implementation is based on the draft version stored in - * ROLL_TM_VER - * + * Implementation of the ROLL TM multicast engine * \author - * George Oikonomou - + * George Oikonomou - */ #include "contiki.h" @@ -1440,6 +1435,9 @@ init() return; } /*---------------------------------------------------------------------------*/ +/** + * \brief The ROLL TM engine driver + */ const struct uip_mcast6_driver roll_tm_driver = { "ROLL TM", init, @@ -1447,3 +1445,4 @@ const struct uip_mcast6_driver roll_tm_driver = { in, }; /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ipv6/multicast/roll-tm.h b/core/net/ipv6/multicast/roll-tm.h index 97dabb552..3ab22cc20 100644 --- a/core/net/ipv6/multicast/roll-tm.h +++ b/core/net/ipv6/multicast/roll-tm.h @@ -29,25 +29,34 @@ * This file is part of the Contiki operating system. */ +/** + * \addtogroup uip6-multicast + * @{ + */ +/** + * \defgroup roll-tm ROLL Trickle Multicast + * + * IPv6 multicast according to the algorithm in the + * "MCAST Forwarding Using Trickle" internet draft. + * + * The current version of the draft can always be found in + * http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast + * + * This implementation is based on the draft version stored in + * ROLL_TM_VER. + * + * In draft v2, the document was renamed to + * "Multicast Protocol for Low power and Lossy Networks (MPL)" + * Due to very significant changes between draft versions 1 and 2, + * MPL will be implemented as a separate engine and this file here + * will provide legacy support for Draft v1. + * @{ + */ /** * \file - * Header file for IPv6 multicast according to the algorithm in the - * "MCAST Forwarding Using Trickle" internet draft. - * - * The current version of the draft can always be found in - * http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast - * - * This implementation is based on the draft version stored in - * ROLL_TM_VER. - * - * In draft v2, the document was renamed to - * "Multicast Protocol for Low power and Lossy Networks (MPL)" - * Due to very significant changes between draft versions 1 and 2, - * MPL will be implemented as a separate engine and this file here - * will provide legacy support for Draft v1. - * + * Header file for the implementation of the ROLL-TM multicast engine * \author - * George Oikonomou - + * George Oikonomou - */ #ifndef ROLL_TM_H_ @@ -60,9 +69,9 @@ /*---------------------------------------------------------------------------*/ /* Protocol Constants */ /*---------------------------------------------------------------------------*/ -#define ROLL_TM_VER 1 /* Supported Draft Version */ -#define ROLL_TM_ICMP_CODE 0 /* ICMPv6 code field */ -#define ROLL_TM_IP_HOP_LIMIT 0xFF /* Hop limit for ICMP messages */ +#define ROLL_TM_VER 1 /**< Supported Draft Version */ +#define ROLL_TM_ICMP_CODE 0 /**< ROLL TM ICMPv6 code field */ +#define ROLL_TM_IP_HOP_LIMIT 0xFF /**< Hop limit for ICMP messages */ #define ROLL_TM_INFINITE_REDUNDANCY 0xFF #define ROLL_TM_DGRAM_OUT 0 #define ROLL_TM_DGRAM_IN 1 @@ -153,7 +162,7 @@ /*---------------------------------------------------------------------------*/ /* Configuration */ /*---------------------------------------------------------------------------*/ -/* +/** * Number of Sliding Windows * In essence: How many unique sources of simultaneous multicast traffic do we * want to support for our lowpan @@ -166,7 +175,7 @@ #define ROLL_TM_WINS 2 #endif /*---------------------------------------------------------------------------*/ -/* +/** * Maximum Number of Buffered Multicast Messages * This buffer is shared across all Seed IDs, therefore a new very active Seed * may eventually occupy all slots. It would make little sense (if any) to @@ -178,7 +187,7 @@ #define ROLL_TM_BUFF_NUM 6 #endif /*---------------------------------------------------------------------------*/ -/* +/** * Use Short Seed IDs [short: 2, long: 16 (default)] * It can be argued that we should (and it would be easy to) support both at * the same time but the draft doesn't list this as a MUST so we opt for @@ -190,7 +199,7 @@ #define ROLL_TM_SHORT_SEEDS 0 #endif /*---------------------------------------------------------------------------*/ -/* +/** * Destination address for our ICMPv6 advertisements. The draft gives us a * choice between LL all-nodes or LL all-routers * @@ -202,7 +211,7 @@ #define ROLL_TM_DEST_ALL_NODES 0 #endif /*---------------------------------------------------------------------------*/ -/* +/** * M param for our outgoing messages * By default, we set the M bit (conservative). Define this as 0 to clear the * M bit in our outgoing messages (aggressive) @@ -215,10 +224,21 @@ /*---------------------------------------------------------------------------*/ /* Stats datatype */ /*---------------------------------------------------------------------------*/ +/** + * \brief Multicast stats extension for the ROLL TM engine + */ struct roll_tm_stats { + /** Number of received ICMP datagrams */ UIP_MCAST6_STATS_DATATYPE icmp_in; + + /** Number of ICMP datagrams sent */ UIP_MCAST6_STATS_DATATYPE icmp_out; + + /** Number of malformed ICMP datagrams seen by us */ UIP_MCAST6_STATS_DATATYPE icmp_bad; }; - +/*---------------------------------------------------------------------------*/ #endif /* ROLL_TM_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ +/** @} */ diff --git a/core/net/ipv6/multicast/smrf.c b/core/net/ipv6/multicast/smrf.c index 9e49fdc40..b1dccbd19 100644 --- a/core/net/ipv6/multicast/smrf.c +++ b/core/net/ipv6/multicast/smrf.c @@ -29,14 +29,16 @@ * This file is part of the Contiki operating system. */ +/** + * \addtogroup smrf-multicast + * @{ + */ /** * \file - * This file implements 'Stateless Multicast RPL Forwarding' (SMRF) - * - * It will only work in RPL networks in MOP 3 "Storing with Multicast" + * This file implements 'Stateless Multicast RPL Forwarding' (SMRF) * * \author - * George Oikonomou - + * George Oikonomou - */ #include "contiki.h" @@ -199,6 +201,9 @@ out() return; } /*---------------------------------------------------------------------------*/ +/** + * \brief The SMRF engine driver + */ const struct uip_mcast6_driver smrf_driver = { "SMRF", init, @@ -206,3 +211,4 @@ const struct uip_mcast6_driver smrf_driver = { in, }; /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ipv6/multicast/smrf.h b/core/net/ipv6/multicast/smrf.h index d19fd6de8..51dcf216e 100644 --- a/core/net/ipv6/multicast/smrf.h +++ b/core/net/ipv6/multicast/smrf.h @@ -29,12 +29,22 @@ * This file is part of the Contiki operating system. */ +/** + * \addtogroup uip6-multicast + * @{ + */ +/** + * \defgroup smrf-multicast 'Stateless Multicast RPL Forwarding' (SMRF) + * + * SMRF will only work in RPL networks in MOP 3 "Storing with Multicast" + * @{ + */ /** * \file - * Header file for 'Stateless Multicast RPL Forwarding' (SMRF) + * Header file for the SMRF forwarding engine * * \author - * George Oikonomou - + * George Oikonomou - */ #ifndef SMRF_H_ @@ -71,5 +81,8 @@ struct smrf_stats { uint16_t mcast_bad; uint16_t mcast_dropped; }; - +/*---------------------------------------------------------------------------*/ #endif /* SMRF_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ +/** @} */ diff --git a/core/net/ipv6/multicast/uip-mcast6-engines.h b/core/net/ipv6/multicast/uip-mcast6-engines.h index cea3c9ecc..f4bff657a 100644 --- a/core/net/ipv6/multicast/uip-mcast6-engines.h +++ b/core/net/ipv6/multicast/uip-mcast6-engines.h @@ -29,22 +29,27 @@ * This file is part of the Contiki operating system. */ +/** + * \addtogroup uip6-multicast + * @{ + */ /** * \file - * Header file with definition of multicast engine constants + * Header file with definition of multicast engine constants * - * When writing a new engine, add it here with a unique number and - * then modify uip-mcast6.h accordingly + * When writing a new engine, add it here with a unique number and + * then modify uip-mcast6.h accordingly * * \author - * George Oikonomou - + * George Oikonomou - */ #ifndef UIP_MCAST6_ENGINES_H_ #define UIP_MCAST6_ENGINES_H_ -#define UIP_MCAST6_ENGINE_NONE 0 /* Selecting this disables mcast */ -#define UIP_MCAST6_ENGINE_SMRF 1 -#define UIP_MCAST6_ENGINE_ROLL_TM 2 +#define UIP_MCAST6_ENGINE_NONE 0 /**< Selecting this disables mcast */ +#define UIP_MCAST6_ENGINE_SMRF 1 /**< The SMRF engine */ +#define UIP_MCAST6_ENGINE_ROLL_TM 2 /**< The ROLL TM engine */ #endif /* UIP_MCAST6_ENGINES_H_ */ +/** @} */ diff --git a/core/net/ipv6/multicast/uip-mcast6-route.c b/core/net/ipv6/multicast/uip-mcast6-route.c index e414fbf17..f6b9737fc 100644 --- a/core/net/ipv6/multicast/uip-mcast6-route.c +++ b/core/net/ipv6/multicast/uip-mcast6-route.c @@ -28,12 +28,16 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \addtogroup uip6-multicast + * @{ + */ /** * \file - * Multicast routing table manipulation + * Multicast routing table manipulation * * \author - * George Oikonomou - + * George Oikonomou - */ #include "contiki.h" @@ -128,3 +132,4 @@ uip_mcast6_route_init() list_init(mcast_route_list); } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ipv6/multicast/uip-mcast6-route.h b/core/net/ipv6/multicast/uip-mcast6-route.h index ef5d43f77..95e808676 100644 --- a/core/net/ipv6/multicast/uip-mcast6-route.h +++ b/core/net/ipv6/multicast/uip-mcast6-route.h @@ -28,12 +28,16 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \addtogroup uip6-multicast + * @{ + */ /** * \file - * Multicast routing table manipulation + * Header file for multicast routing table manipulation * * \author - * George Oikonomou - + * George Oikonomou - */ #ifndef UIP_MCAST6_ROUTE_H_ #define UIP_MCAST6_ROUTE_H_ @@ -45,18 +49,48 @@ /*---------------------------------------------------------------------------*/ /** \brief An entry in the multicast routing table */ typedef struct uip_mcast6_route { - struct uip_mcast6_route *next; - uip_ipaddr_t group; - uint32_t lifetime; /* seconds */ - void *dag; /* Pointer to an rpl_dag_t struct */ + struct uip_mcast6_route *next; /**< Routes are arranged in a linked list */ + uip_ipaddr_t group; /**< The multicast group */ + uint32_t lifetime; /**< Entry lifetime seconds */ + void *dag; /**< Pointer to an rpl_dag_t struct */ } uip_mcast6_route_t; /*---------------------------------------------------------------------------*/ /** \name Multicast Routing Table Manipulation */ /** @{ */ + +/** + * \brief Lookup a multicast route + * \param group A pointer to the multicast group to be searched for + * \return A pointer to the new routing entry, or NULL if the route could not + * be found + */ uip_mcast6_route_t *uip_mcast6_route_lookup(uip_ipaddr_t *group); + +/** + * \brief Add a multicast route + * \param group A pointer to the multicast group to be added + * \return A pointer to the new route, or NULL if the route could not be added + */ uip_mcast6_route_t *uip_mcast6_route_add(uip_ipaddr_t *group); -void uip_mcast6_route_rm(uip_mcast6_route_t *defrt); + +/** + * \brief Remove a multicast route + * \param route A pointer to the route to be removed + */ +void uip_mcast6_route_rm(uip_mcast6_route_t *route); + +/** + * \brief Retrieve the count of multicast routes + * \return The number of multicast routes + */ int uip_mcast6_route_count(void); + +/** + * \brief Retrieve a pointer to the start of the multicast routes list + * \return A pointer to the start of the multicast routes + * + * If the multicast routes list is empty, this function will return NULL + */ uip_mcast6_route_t *uip_mcast6_route_list_head(void); /*---------------------------------------------------------------------------*/ /** @@ -73,3 +107,4 @@ void uip_mcast6_route_init(void); /** @} */ #endif /* UIP_MCAST6_ROUTE_H_ */ +/** @} */ diff --git a/core/net/ipv6/multicast/uip-mcast6-stats.c b/core/net/ipv6/multicast/uip-mcast6-stats.c index ed23747f1..d617358ba 100644 --- a/core/net/ipv6/multicast/uip-mcast6-stats.c +++ b/core/net/ipv6/multicast/uip-mcast6-stats.c @@ -27,12 +27,16 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \addtogroup uip6-multicast + * @{ + */ /** * \file - * IPv6 multicast forwarding stats maintenance + * IPv6 multicast forwarding stats maintenance * * \author - * George Oikonomou - + * George Oikonomou - */ #include "net/ipv6/multicast/uip-mcast6-stats.h" @@ -47,3 +51,4 @@ uip_mcast6_stats_init(void *stats) uip_mcast6_stats.engine_stats = stats; } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ipv6/multicast/uip-mcast6-stats.h b/core/net/ipv6/multicast/uip-mcast6-stats.h index 1e3775934..263758b66 100644 --- a/core/net/ipv6/multicast/uip-mcast6-stats.h +++ b/core/net/ipv6/multicast/uip-mcast6-stats.h @@ -27,12 +27,16 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \addtogroup uip6-multicast + * @{ + */ /** * \file - * Header file for IPv6 multicast forwarding stats maintenance + * Header file for IPv6 multicast forwarding stats maintenance * * \author - * George Oikonomou - + * George Oikonomou - */ #ifndef UIP_MCAST6_STATS_H_ #define UIP_MCAST6_STATS_H_ @@ -56,15 +60,35 @@ /*---------------------------------------------------------------------------*/ /* Stats datatype */ /*---------------------------------------------------------------------------*/ +/** + * \brief A data structure used to maintain multicast stats + * + * Each engine can extend this structure via the engine_stats field + */ typedef struct uip_mcast6_stats { + /** Count of unique datagrams received */ UIP_MCAST6_STATS_DATATYPE mcast_in_unique; - UIP_MCAST6_STATS_DATATYPE mcast_in_all; /* At layer 3 */ - UIP_MCAST6_STATS_DATATYPE mcast_in_ours; /* Unique and we are a group member */ - UIP_MCAST6_STATS_DATATYPE mcast_fwd; /* Forwarded by us but we are not the seed */ - UIP_MCAST6_STATS_DATATYPE mcast_out; /* We are the seed */ + + /** Count of all datagrams received */ + UIP_MCAST6_STATS_DATATYPE mcast_in_all; + + /** Count of datagrams received for a group that we have joined */ + UIP_MCAST6_STATS_DATATYPE mcast_in_ours; + + /** Count of datagrams forwarded by us but we are not the seed */ + UIP_MCAST6_STATS_DATATYPE mcast_fwd; + + /** Count of multicast datagrams originated by us */ + UIP_MCAST6_STATS_DATATYPE mcast_out; + + /** Count of malformed multicast datagrams seen by us */ UIP_MCAST6_STATS_DATATYPE mcast_bad; + + /** Count of multicast datagrams correclty formed but dropped by us */ UIP_MCAST6_STATS_DATATYPE mcast_dropped; - void *engine_stats; /* Opaque pointer to an engine's additional stats */ + + /** Opaque pointer to an engine's additional stats */ + void *engine_stats; } uip_mcast6_stats_t; /*---------------------------------------------------------------------------*/ /* Access macros */ @@ -89,3 +113,5 @@ extern uip_mcast6_stats_t uip_mcast6_stats; void uip_mcast6_stats_init(void *stats); /*---------------------------------------------------------------------------*/ #endif /* UIP_MCAST6_STATS_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ipv6/multicast/uip-mcast6.h b/core/net/ipv6/multicast/uip-mcast6.h index 9bd2b2b2d..de2003839 100644 --- a/core/net/ipv6/multicast/uip-mcast6.h +++ b/core/net/ipv6/multicast/uip-mcast6.h @@ -30,9 +30,11 @@ */ /** - * \file - * This header file contains configuration directives for uIPv6 - * multicast support. + * \addtogroup uip6 + * @{ + */ +/** + * \defgroup uip6-multicast IPv6 Multicast Forwarding * * We currently support 2 engines: * - 'Stateless Multicast RPL Forwarding' (SMRF) @@ -42,6 +44,14 @@ * in the internet draft: * http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast * + * @{ + */ + +/** + * \file + * This header file contains configuration directives for uIPv6 + * multicast support. + * * \author * George Oikonomou - */ @@ -83,7 +93,11 @@ * Multicast API. Similar to NETSTACK, each engine must define a driver and * populate the fields with suitable function pointers */ +/** + * \brief The data structure used to represent a multicast engine + */ struct uip_mcast6_driver { + /** The driver's name */ char *name; /** Initialize the multicast engine */ @@ -110,6 +124,7 @@ struct uip_mcast6_driver { * * \return 0: Drop, 1: Deliver * + * * When a datagram with a multicast destination address is received, * the forwarding logic in core is bypassed. Instead, we let the * multicast engine handle forwarding internally if and as necessary. @@ -158,5 +173,7 @@ extern const struct uip_mcast6_driver UIP_MCAST6; #error "Check the value of UIP_CONF_IPV6_RPL in conf files." #endif /*---------------------------------------------------------------------------*/ - #endif /* UIP_MCAST6_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ +/** @} */ diff --git a/core/net/ipv6/sicslowpan.h b/core/net/ipv6/sicslowpan.h index a46229b02..4dcb2ae11 100644 --- a/core/net/ipv6/sicslowpan.h +++ b/core/net/ipv6/sicslowpan.h @@ -234,7 +234,7 @@ struct sicslowpan_addr_context { * \brief check whether we can compress the IID in * address 'a' to 16 bits. * This is used for unicast addresses only, and is true - * if the address is on the format ::0000:00ff:fe00:XXXX + * if the address is on the format \::0000:00ff:fe00:XXXX * NOTE: we currently assume 64-bits prefixes */ #define sicslowpan_is_iid_16_bit_compressable(a) \ diff --git a/core/net/ipv6/uip-ds6-nbr.c b/core/net/ipv6/uip-ds6-nbr.c index 86f915d10..db14f8647 100644 --- a/core/net/ipv6/uip-ds6-nbr.c +++ b/core/net/ipv6/uip-ds6-nbr.c @@ -29,20 +29,20 @@ * */ +/** + * \addtogroup uip6 + * @{ + */ + /** * \file - * IPv6 Neighbor cache (link-layer/IPv6 address mapping) + * IPv6 Neighbor cache (link-layer/IPv6 address mapping) * \author Mathilde Durvy * \author Julien Abeille * \author Simon Duquennoy * */ -/** - * \addtogroup uip6 - * @{ - */ - #include #include #include diff --git a/core/net/ipv6/uip-ds6-nbr.h b/core/net/ipv6/uip-ds6-nbr.h index 5627f03aa..36a202e86 100644 --- a/core/net/ipv6/uip-ds6-nbr.h +++ b/core/net/ipv6/uip-ds6-nbr.h @@ -29,20 +29,20 @@ * */ +/** + * \addtogroup uip6 + * @{ + */ + /** * \file - * IPv6 Neighbor cache (link-layer/IPv6 address mapping) + * IPv6 Neighbor cache (link-layer/IPv6 address mapping) * \author Mathilde Durvy * \author Julien Abeille * \author Simon Duquennoy * */ -/** - * \addtogroup uip6 - * @{ - */ - #ifndef UIP_DS6_NEIGHBOR_H_ #define UIP_DS6_NEIGHBOR_H_ @@ -74,6 +74,7 @@ typedef struct uip_ds6_nbr { uint8_t nscount; uint8_t isrouter; uint8_t state; + uint16_t link_metric; #if UIP_CONF_IPV6_QUEUE_PKT struct uip_packetqueue_handle packethandle; #define UIP_DS6_NBR_PACKET_LIFETIME CLOCK_SECOND * 4 @@ -98,12 +99,12 @@ int uip_ds6_nbr_num(void); /** * \brief - * This searches inside the neighbor table for the neighbor that is about to - * expire the next. + * This searches inside the neighbor table for the neighbor that is about to + * expire the next. * * \return - * A reference to the neighbor about to expire the next or NULL if - * table is empty. + * A reference to the neighbor about to expire the next or NULL if + * table is empty. */ uip_ds6_nbr_t *uip_ds6_get_least_lifetime_neighbor(void); diff --git a/core/net/ipv6/uip-ds6-route.c b/core/net/ipv6/uip-ds6-route.c index ecb7d354b..3931319a0 100644 --- a/core/net/ipv6/uip-ds6-route.c +++ b/core/net/ipv6/uip-ds6-route.c @@ -29,6 +29,15 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. * */ +/** + * \addtogroup uip6 + * @{ + */ + +/** + * \file + * Routing table manipulation + */ #include "net/ipv6/uip-ds6.h" #include "net/ip/uip.h" @@ -269,9 +278,16 @@ uip_ds6_route_add(uip_ipaddr_t *ipaddr, uint8_t length, one first. */ r = uip_ds6_route_lookup(ipaddr); if(r != NULL) { + uip_ipaddr_t *current_nexthop; + current_nexthop = uip_ds6_route_nexthop(r); + if(uip_ipaddr_cmp(nexthop, current_nexthop)) { + /* no need to update route - already correct! */ + return r; + } PRINTF("uip_ds6_route_add: old route for "); PRINT6ADDR(ipaddr); PRINTF(" found, deleting it\n"); + uip_ds6_route_rm(r); } { @@ -629,3 +645,4 @@ uip_ds6_defrt_periodic(void) } } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ipv6/uip-ds6-route.h b/core/net/ipv6/uip-ds6-route.h index 9603d6cde..27cbee79b 100644 --- a/core/net/ipv6/uip-ds6-route.h +++ b/core/net/ipv6/uip-ds6-route.h @@ -29,6 +29,14 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. * */ +/** + * \addtogroup uip6 + * @{ + */ +/** + * \file + * Header file for routing table manipulation + */ #ifndef UIP_DS6_ROUTE_H #define UIP_DS6_ROUTE_H @@ -158,3 +166,4 @@ uip_ds6_route_t *uip_ds6_route_next(uip_ds6_route_t *); /** @} */ #endif /* UIP_DS6_ROUTE_H */ +/** @} */ diff --git a/core/net/ipv6/uip-ds6.c b/core/net/ipv6/uip-ds6.c index d5b848b9a..ce75ca485 100644 --- a/core/net/ipv6/uip-ds6.c +++ b/core/net/ipv6/uip-ds6.c @@ -29,17 +29,17 @@ */ /** - * \file - * IPv6 data structures handling functions. - * Comprises part of the Neighbor discovery (RFC 4861) - * and auto configuration (RFC 4862) state machines. - * \author Mathilde Durvy - * \author Julien Abeille + * \addtogroup uip6 + * @{ */ /** - * \addtogroup uip6 - * @{ + * \file + * IPv6 data structure manipulation. + * Comprises part of the Neighbor discovery (RFC 4861) + * and auto configuration (RFC 4862) state machines. + * \author Mathilde Durvy + * \author Julien Abeille */ #include diff --git a/core/net/ipv6/uip-ds6.h b/core/net/ipv6/uip-ds6.h index b6238e609..9c470a1db 100644 --- a/core/net/ipv6/uip-ds6.h +++ b/core/net/ipv6/uip-ds6.h @@ -5,7 +5,7 @@ /** * \file - * Network interface and stateless autoconfiguration (RFC 4862) + * Header file for IPv6-related data structures * \author Mathilde Durvy * \author Julien Abeille * diff --git a/core/net/ipv6/uip-icmp6.c b/core/net/ipv6/uip-icmp6.c index b14ac2d64..ee8d94c77 100644 --- a/core/net/ipv6/uip-icmp6.c +++ b/core/net/ipv6/uip-icmp6.c @@ -31,15 +31,15 @@ */ /** - * \file - * ICMPv6 echo request and error messages (RFC 4443) - * \author Julien Abeille - * \author Mathilde Durvy + * \addtogroup uip6 + * @{ */ /** - * \addtogroup uip6 - * @{ + * \file + * ICMPv6 (RFC 4443) implementation, with message and error handling + * \author Julien Abeille + * \author Mathilde Durvy */ #include diff --git a/core/net/ipv6/uip-icmp6.h b/core/net/ipv6/uip-icmp6.h index aa44bff5a..5633791fd 100644 --- a/core/net/ipv6/uip-icmp6.h +++ b/core/net/ipv6/uip-icmp6.h @@ -31,15 +31,15 @@ */ /** - * \file - * ICMPv6 echo request and error messages (RFC 4443) - * \author Julien Abeille - * \author Mathilde Durvy + * \addtogroup uip6 + * @{ */ /** - * \addtogroup uip6 - * @{ + * \file + * Header file for ICMPv6 message and error handing (RFC 4443) + * \author Julien Abeille + * \author Mathilde Durvy */ #ifndef ICMP6_H_ diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index 273b45134..701f458fa 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -57,21 +57,22 @@ */ /** - * \file - * Neighbor discovery (RFC 4861) - * \author Mathilde Durvy - * \author Julien Abeille + * \addtogroup uip6 + * @{ */ /** - * \addtogroup uip6 - * @{ + * \file + * Neighbor discovery (RFC 4861) + * \author Mathilde Durvy + * \author Julien Abeille */ #include #include "net/ipv6/uip-icmp6.h" #include "net/ipv6/uip-nd6.h" #include "net/ipv6/uip-ds6.h" +#include "net/ip/uip-nameserver.h" #include "lib/random.h" /*------------------------------------------------------------------*/ @@ -112,6 +113,7 @@ void uip_log(char *msg); #define UIP_ND6_OPT_HDR_BUF ((uip_nd6_opt_hdr *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) #define UIP_ND6_OPT_PREFIX_BUF ((uip_nd6_opt_prefix_info *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) #define UIP_ND6_OPT_MTU_BUF ((uip_nd6_opt_mtu *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) +#define UIP_ND6_OPT_RDNSS_BUF ((uip_nd6_opt_dns *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset]) /** @} */ static uint8_t nd6_opt_offset; /** Offset from the end of the icmpv6 header to the option in uip_buf*/ @@ -715,6 +717,29 @@ uip_nd6_ra_output(uip_ipaddr_t * dest) uip_len += UIP_ND6_OPT_MTU_LEN; nd6_opt_offset += UIP_ND6_OPT_MTU_LEN; + +#if UIP_ND6_RA_RDNSS + if(uip_nameserver_count() > 0) { + uint8_t i = 0; + uip_ipaddr_t *ip = &UIP_ND6_OPT_RDNSS_BUF->ip; + uip_ipaddr_t *dns = NULL; + UIP_ND6_OPT_RDNSS_BUF->type = UIP_ND6_OPT_RDNSS; + UIP_ND6_OPT_RDNSS_BUF->reserved = 0; + UIP_ND6_OPT_RDNSS_BUF->lifetime = uip_nameserver_next_expiration(); + if(UIP_ND6_OPT_RDNSS_BUF->lifetime != UIP_NAMESERVER_INFINITE_LIFETIME) { + UIP_ND6_OPT_RDNSS_BUF->lifetime -= clock_seconds(); + } + while((dns = uip_nameserver_get(i)) != NULL) { + uip_ipaddr_copy(ip++, dns); + i++; + } + UIP_ND6_OPT_RDNSS_BUF->len = UIP_ND6_OPT_RDNSS_LEN + (i << 1); + PRINTF("%d nameservers reported\n", i); + uip_len += UIP_ND6_OPT_RDNSS_BUF->len << 3; + nd6_opt_offset += UIP_ND6_OPT_RDNSS_BUF->len << 3; + } +#endif /* UIP_ND6_RA_RDNSS */ + UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); @@ -938,6 +963,23 @@ ra_input(void) /* End of autonomous flag related processing */ } break; +#if UIP_ND6_RA_RDNSS + case UIP_ND6_OPT_RDNSS: + if(UIP_ND6_RA_BUF->flags_reserved & (UIP_ND6_O_FLAG << 6)) { + PRINTF("Processing RDNSS option\n"); + uint8_t naddr = (UIP_ND6_OPT_RDNSS_BUF->len - 1) / 2; + uip_ipaddr_t *ip = (uip_ipaddr_t *)(&UIP_ND6_OPT_RDNSS_BUF->ip); + PRINTF("got %d nameservers\n", naddr); + while(naddr-- > 0) { + PRINTF(" nameserver: "); + PRINT6ADDR(ip); + PRINTF(" lifetime: %lx\n", uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime)); + uip_nameserver_update(ip, uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime)); + ip++; + } + } + break; +#endif /* UIP_ND6_RA_RDNSS */ default: PRINTF("ND option not supported in RA"); break; diff --git a/core/net/ipv6/uip-nd6.h b/core/net/ipv6/uip-nd6.h index 0ece86522..8b5893328 100644 --- a/core/net/ipv6/uip-nd6.h +++ b/core/net/ipv6/uip-nd6.h @@ -31,15 +31,15 @@ */ /** - * \file - * Neighbor discovery (RFC 4861) - * \author Julien Abeille - * \author Mathilde Durvy + * \addtogroup uip6 + * @{ */ /** - * \addtogroup uip6 - * @{ + * \file + * Header file for IPv6 Neighbor discovery (RFC 4861) + * \author Julien Abeille + * \author Mathilde Durvy */ #ifndef UIP_ND6_H_ @@ -87,7 +87,7 @@ #define UIP_ND6_MIN_RA_INTERVAL UIP_CONF_ND6_MIN_RA_INTERVAL #endif #define UIP_ND6_M_FLAG 0 -#define UIP_ND6_O_FLAG 0 +#define UIP_ND6_O_FLAG (UIP_ND6_RA_RDNSS || UIP_ND6_RA_DNSSL) #define UIP_ND6_ROUTER_LIFETIME 3 * UIP_ND6_MAX_RA_INTERVAL #define UIP_ND6_MAX_INITIAL_RA_INTERVAL 16 /*seconds*/ @@ -139,6 +139,23 @@ /** @} */ +/** \name RFC 6106 RA DNS Options Constants */ +/** @{ */ +#ifndef UIP_CONF_ND6_RA_RDNSS +#define UIP_ND6_RA_RDNSS 0 +#else +#define UIP_ND6_RA_RDNSS UIP_CONF_ND6_RA_RDNSS +#endif + +#ifndef UIP_CONF_ND6_RA_DNSSL +#define UIP_ND6_RA_DNSSL 0 +#else +#error Not implemented +#define UIP_ND6_RA_DNSSL UIP_CONF_ND6_RA_DNSSL +#endif +/** @} */ + + /** \name ND6 option types */ /** @{ */ #define UIP_ND6_OPT_SLLAO 1 @@ -146,6 +163,8 @@ #define UIP_ND6_OPT_PREFIX_INFO 3 #define UIP_ND6_OPT_REDIRECTED_HDR 4 #define UIP_ND6_OPT_MTU 5 +#define UIP_ND6_OPT_RDNSS 25 +#define UIP_ND6_OPT_DNSSL 31 /** @} */ /** \name ND6 option types */ @@ -168,6 +187,8 @@ #define UIP_ND6_OPT_HDR_LEN 2 #define UIP_ND6_OPT_PREFIX_INFO_LEN 32 #define UIP_ND6_OPT_MTU_LEN 8 +#define UIP_ND6_OPT_RDNSS_LEN 1 +#define UIP_ND6_OPT_DNSSL_LEN 1 /* Length of TLLAO and SLLAO options, it is L2 dependant */ @@ -290,6 +311,15 @@ typedef struct uip_nd6_opt_mtu { uint32_t mtu; } uip_nd6_opt_mtu; +/** \brief ND option RDNSS */ +typedef struct uip_nd6_opt_dns { + uint8_t type; + uint8_t len; + uint16_t reserved; + uint32_t lifetime; + uip_ipaddr_t ip; +} uip_nd6_opt_dns; + /** \struct Redirected header option */ typedef struct uip_nd6_opt_redirected_hdr { uint8_t type; diff --git a/core/net/ipv6/uip6.c b/core/net/ipv6/uip6.c index 2debd54d7..a5d1db13c 100644 --- a/core/net/ipv6/uip6.c +++ b/core/net/ipv6/uip6.c @@ -31,20 +31,20 @@ * */ +/** + * \addtogroup uip6 + * @{ + */ + /** * \file - * The uIP TCP/IPv6 stack code. + * The uIP TCP/IPv6 stack code. * * \author Adam Dunkels * \author Julien Abeille (IPv6 related code) * \author Mathilde Durvy (IPv6 related code) */ -/** - * \addtogroup uip6 - * @{ - */ - /* * uIP is a small implementation of the IP, UDP and TCP protocols (as * well as some basic ICMP stuff). The implementation couples the IP, @@ -105,7 +105,10 @@ struct uip_stats uip_stat; /*---------------------------------------------------------------------------*/ -/** @{ \name Layer 2 variables */ +/** + * \name Layer 2 variables + * @{ + */ /*---------------------------------------------------------------------------*/ /** Host L2 address */ #if UIP_CONF_LL_802154 @@ -116,7 +119,10 @@ uip_lladdr_t uip_lladdr = {{0x00,0x06,0x98,0x00,0x02,0x32}}; /** @} */ /*---------------------------------------------------------------------------*/ -/** @{ \name Layer 3 variables */ +/** + * \name Layer 3 variables + * @{ + */ /*---------------------------------------------------------------------------*/ /** * \brief Type of the next header in IPv6 header or extension headers @@ -141,8 +147,9 @@ uint8_t uip_ext_opt_offset = 0; /*---------------------------------------------------------------------------*/ /* Buffers */ /*---------------------------------------------------------------------------*/ -/** \name Buffer defines - * @{ +/** + * \name Buffer defines + * @{ */ #define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0]) #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) @@ -161,8 +168,9 @@ uint8_t uip_ext_opt_offset = 0; #endif /* UIP_CONF_IPV6_RPL */ #define UIP_ICMP6_ERROR_BUF ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len]) /** @} */ -/** \name Buffer variables - * @{ +/** + * \name Buffer variables + * @{ */ /** Packet buffer for incoming and outgoing packets */ #ifndef UIP_CONF_EXTERNAL_BUFFER @@ -185,7 +193,10 @@ uint16_t uip_len, uip_slen; /** @} */ /*---------------------------------------------------------------------------*/ -/** @{ \name General variables */ +/** + * \name General variables + * @{ + */ /*---------------------------------------------------------------------------*/ /* The uip_flags variable is used for communication between the TCP/IP stack @@ -209,7 +220,8 @@ static uint16_t lastport; /*---------------------------------------------------------------------------*/ /* TCP */ /*---------------------------------------------------------------------------*/ -/** \name TCP defines +/** + * \name TCP defines *@{ */ /* Structures and definitions. */ @@ -227,7 +239,8 @@ static uint16_t lastport; #define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */ /** @} */ -/** \name TCP variables +/** + * \name TCP variables *@{ */ #if UIP_TCP @@ -248,7 +261,10 @@ static uint16_t tmp16; /** @} */ /*---------------------------------------------------------------------------*/ -/** @{ \name UDP variables */ +/** + * \name UDP variables + * @{ + */ /*---------------------------------------------------------------------------*/ #if UIP_UDP struct uip_udp_conn *uip_udp_conn; @@ -257,7 +273,10 @@ struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; /** @} */ /*---------------------------------------------------------------------------*/ -/** @{ \name ICMPv6 variables */ +/** + * \name ICMPv6 variables + * @{ + */ /*---------------------------------------------------------------------------*/ #if UIP_CONF_ICMP6 /** single possible icmpv6 "connection" */ diff --git a/core/net/llsec/anti-replay.h b/core/net/llsec/anti-replay.h index 2f8e7b2d8..9211a6e7a 100644 --- a/core/net/llsec/anti-replay.h +++ b/core/net/llsec/anti-replay.h @@ -64,12 +64,13 @@ uint32_t anti_replay_get_counter(void); /** * \brief Initializes the anti-replay information about the sender + * \param info Anti-replay information about the sender */ void anti_replay_init_info(struct anti_replay_info *info); /** * \brief Checks if received frame was replayed - * \param last_counters Anti-replay information about the sender + * \param info Anti-replay information about the sender * \retval 0 <-> received frame was not replayed */ int anti_replay_was_replayed(struct anti_replay_info *info); diff --git a/core/net/llsec/llsec802154.h b/core/net/llsec/llsec802154.h index 5d81d9cb4..6ab6a9793 100644 --- a/core/net/llsec/llsec802154.h +++ b/core/net/llsec/llsec802154.h @@ -43,7 +43,7 @@ */ /** - * \defgroup llsec802154 + * \defgroup llsec802154 Link Layer Security Common Functionality * * Common functionality of 802.15.4-compliant llsec_drivers. * diff --git a/core/net/llsec/noncoresec/noncoresec.h b/core/net/llsec/noncoresec/noncoresec.h index 493ff5ce5..1e2172590 100644 --- a/core/net/llsec/noncoresec/noncoresec.h +++ b/core/net/llsec/noncoresec/noncoresec.h @@ -43,7 +43,7 @@ */ /** - * \defgroup noncoresec + * \defgroup noncoresec LLSEC driver using a network-wide key (NONCORESEC) * * Noncompromise-resilient 802.15.4 security * diff --git a/core/net/llsec/nullsec.h b/core/net/llsec/nullsec.h index 2682bd343..30488e5d4 100644 --- a/core/net/llsec/nullsec.h +++ b/core/net/llsec/nullsec.h @@ -43,7 +43,7 @@ */ /** - * \defgroup nullsec + * \defgroup nullsec LLSEC driver with zero security (NULLSEC) * * Insecure link layer security driver. * diff --git a/core/net/mac/frame802154.h b/core/net/mac/frame802154.h index 4b3a81049..64a367120 100644 --- a/core/net/mac/frame802154.h +++ b/core/net/mac/frame802154.h @@ -44,7 +44,7 @@ */ /** - * \addtogroup net 802.15.4 frame creation and parsing + * \addtogroup net * @{ */ diff --git a/core/net/packetbuf.c b/core/net/packetbuf.c index 43994f61e..6e4c3e720 100644 --- a/core/net/packetbuf.c +++ b/core/net/packetbuf.c @@ -56,10 +56,10 @@ static uint16_t buflen, bufptr; static uint8_t hdrptr; /* The declarations below ensure that the packet buffer is aligned on - an even 16-bit boundary. On some platforms (most notably the - msp430), having apotentially misaligned packet buffer may lead to - problems when accessing 16-bit values. */ -static uint16_t packetbuf_aligned[(PACKETBUF_SIZE + PACKETBUF_HDR_SIZE) / 2 + 1]; + an even 32-bit boundary. On some platforms (most notably the + msp430 or OpenRISC), having a potentially misaligned packet buffer may lead to + problems when accessing words. */ +static uint32_t packetbuf_aligned[(PACKETBUF_SIZE + PACKETBUF_HDR_SIZE + 3) / 4]; static uint8_t *packetbuf = (uint8_t *)packetbuf_aligned; static uint8_t *packetbufptr; diff --git a/core/net/rime/abc.h b/core/net/rime/abc.h index 8e2b1d86b..b1f7f8f29 100644 --- a/core/net/rime/abc.h +++ b/core/net/rime/abc.h @@ -49,7 +49,7 @@ * The abc module sends packets to all local area neighbors. The abc * module adds no headers to outgoing packets. * - * \section channels Channels + * \section abc-channels Channels * * The abc module uses 1 channel. * diff --git a/core/net/rime/announcement.h b/core/net/rime/announcement.h index 759ab8b08..802d1da84 100644 --- a/core/net/rime/announcement.h +++ b/core/net/rime/announcement.h @@ -131,6 +131,7 @@ void announcement_remove(struct announcement *a); * \brief Set the value of an announcement * \param a A pointer to a struct announcement that has * previously been registered + * \param value The new value * * This function sets the value of an announcement that * has previously been registered with diff --git a/core/net/rime/broadcast-announcement.h b/core/net/rime/broadcast-announcement.h index 371c84fc9..0cca9d85c 100644 --- a/core/net/rime/broadcast-announcement.h +++ b/core/net/rime/broadcast-announcement.h @@ -50,7 +50,7 @@ * announcement. THe module announces the announcements that have been * registered with the \ref rimeannouncement "announcement module". * - * \section channels Channels + * \section bcast-announce-channels Channels * * The broadcast announcement module uses 1 channel. * diff --git a/core/net/rime/broadcast.h b/core/net/rime/broadcast.h index c4e427405..4a4c885d7 100644 --- a/core/net/rime/broadcast.h +++ b/core/net/rime/broadcast.h @@ -56,7 +56,7 @@ * either directly or indirectly through any of the other * communication primitives that are based on the broadcast primitive. * - * \section channels Channels + * \section broadcast-channels Channels * * The broadcast module uses 1 channel. * diff --git a/core/net/rime/collect.h b/core/net/rime/collect.h index 333d71628..d731a531b 100644 --- a/core/net/rime/collect.h +++ b/core/net/rime/collect.h @@ -49,7 +49,7 @@ * The collect module implements a hop-by-hop reliable data collection * mechanism. * - * \section channels Channels + * \section collect-channels Channels * * The collect module uses 2 channels; one for neighbor discovery and one * for data packets. diff --git a/core/net/rime/ipolite.h b/core/net/rime/ipolite.h index c76505913..e1fa683b3 100644 --- a/core/net/rime/ipolite.h +++ b/core/net/rime/ipolite.h @@ -84,7 +84,7 @@ * The polite broadcast module does not add any packet attributes to * outgoing packets apart from those added by the upper layer. * - * \section channels Channels + * \section ipolite-channels Channels * * The ipolite module uses 1 channel. * diff --git a/core/net/rime/mesh.h b/core/net/rime/mesh.h index 35a009366..40aaf5bd1 100644 --- a/core/net/rime/mesh.h +++ b/core/net/rime/mesh.h @@ -50,7 +50,7 @@ * receiver somewhere in the network. * * - * \section channels Channels + * \section mesh-channels Channels * * The mesh module uses 3 channel; one for the multi-hop forwarding * (\ref rimemultihop "multihop") and two for the route disovery (\ref diff --git a/core/net/rime/multihop.h b/core/net/rime/multihop.h index bf1bf8c44..a577a3339 100644 --- a/core/net/rime/multihop.h +++ b/core/net/rime/multihop.h @@ -61,7 +61,7 @@ * process. * * - * \section channels Channels + * \section multihop-channels Channels * * The multihop module uses 1 channel. * diff --git a/core/net/rime/neighbor-discovery.h b/core/net/rime/neighbor-discovery.h index 113ec1418..337a9c15a 100644 --- a/core/net/rime/neighbor-discovery.h +++ b/core/net/rime/neighbor-discovery.h @@ -50,7 +50,7 @@ * discovery mechanism. A callback is invoked for every incoming * neighbor discovery message. * - * \section channels Channels + * \section neighbor-discovery-channels Channels * * The neighbor-discovery module uses 1 channel. * diff --git a/core/net/rime/netflood.h b/core/net/rime/netflood.h index 5c791f086..d21593cf2 100644 --- a/core/net/rime/netflood.h +++ b/core/net/rime/netflood.h @@ -65,7 +65,7 @@ * If the time to live reaches zero, the primitive does not forward * the packet. * - * \section channels Channels + * \section netflood-channels Channels * * The netflood module uses 1 channel. * diff --git a/core/net/rime/packetqueue.h b/core/net/rime/packetqueue.h index 5ec581a6c..5956d67e8 100644 --- a/core/net/rime/packetqueue.h +++ b/core/net/rime/packetqueue.h @@ -78,7 +78,7 @@ struct packetqueue { * This structure holds the state of a packet queue. It is * an opaque structure with no user-visible elements. The * function packetqueue_queuebuf() is used to extract a - * \ref queuebuf "queubuf" from the item. The function + * "queubuf" from the item. The function * packetqueue_ptr() is used to extract the opaque pointer * that was registered with the * packetqueue_enqueue_packetbuf() function. diff --git a/core/net/rime/polite-announcement.h b/core/net/rime/polite-announcement.h index c3af5d814..76b4a12ec 100644 --- a/core/net/rime/polite-announcement.h +++ b/core/net/rime/polite-announcement.h @@ -50,7 +50,7 @@ * announcement. THe module announces the announcements that have been * registered with the \ref rimeannouncement "announcement module". * - * \section channels Channels + * \section polite-announcement-channels Channels * * The polite announcement module uses 1 channel. * diff --git a/core/net/rime/polite.h b/core/net/rime/polite.h index 82e6e911b..59c424608 100644 --- a/core/net/rime/polite.h +++ b/core/net/rime/polite.h @@ -84,7 +84,7 @@ * The polite broadcast module does not add any packet attributes to * outgoing packets apart from those added by the upper layer. * - * \section channels Channels + * \section polite-channels Channels * * The polite module uses 1 channel. * diff --git a/core/net/rime/rmh.h b/core/net/rime/rmh.h index f7d7786a6..14faac14d 100644 --- a/core/net/rime/rmh.h +++ b/core/net/rime/rmh.h @@ -56,7 +56,7 @@ * reliable single-hop primitive for the communication between two * single-hop neighbors. * - * \section channels Channels + * \section rmh-channels Channels * * The rmh module uses 1 channel. * diff --git a/core/net/rime/route-discovery.h b/core/net/rime/route-discovery.h index f1ac6fd3a..81d454d5f 100644 --- a/core/net/rime/route-discovery.h +++ b/core/net/rime/route-discovery.h @@ -48,7 +48,7 @@ * * The route-discovery module does route discovery for Rime. * - * \section channels Channels + * \section route-discovery-channels Channels * * The ibc module uses 2 channels; one for the flooded route request * packets and one for the unicast route replies. diff --git a/core/net/rime/rudolph0.h b/core/net/rime/rudolph0.h index 21ac1c086..695d97950 100644 --- a/core/net/rime/rudolph0.h +++ b/core/net/rime/rudolph0.h @@ -49,7 +49,7 @@ * The rudolph0 module implements a single-hop reliable bulk data * transfer mechanism. * - * \section channels Channels + * \section rudolph0-channels Channels * * The rudolph0 module uses 2 channels; one for data packets and one * for NACK and repair packets. diff --git a/core/net/rime/rudolph1.h b/core/net/rime/rudolph1.h index 6b487bbe9..399a0a84e 100644 --- a/core/net/rime/rudolph1.h +++ b/core/net/rime/rudolph1.h @@ -49,7 +49,7 @@ * The rudolph1 module implements a multi-hop reliable bulk data * transfer mechanism. * - * \section channels Channels + * \section rudolph1-channels Channels * * The rudolph1 module uses 2 channels; one for data transmissions and * one for NACKs and repair packets. diff --git a/core/net/rime/rudolph2.h b/core/net/rime/rudolph2.h index 6afe5506e..e1d43e8fa 100644 --- a/core/net/rime/rudolph2.h +++ b/core/net/rime/rudolph2.h @@ -49,7 +49,7 @@ * The rudolph2 module implements a single-hop reliable bulk data * transfer mechanism. * - * \section channels Channels + * \section rudolph2-channels Channels * * The rudolph2 module uses 2 channels; one for data packets and one * for NACK and repair packets. diff --git a/core/net/rime/runicast.h b/core/net/rime/runicast.h index a3b55a5e6..a7e199435 100644 --- a/core/net/rime/runicast.h +++ b/core/net/rime/runicast.h @@ -69,7 +69,7 @@ * callback. * * - * \section channels Channels + * \section runicast-channels Channels * * The runicast module uses 1 channel. * diff --git a/core/net/rime/stbroadcast.h b/core/net/rime/stbroadcast.h index 2c04dc273..0b656827e 100644 --- a/core/net/rime/stbroadcast.h +++ b/core/net/rime/stbroadcast.h @@ -51,7 +51,7 @@ * either the message is canceled or a new message is sent. Messages * sent with the stbroadcast module are not identified with a sender ID. * - * \section channels Channels + * \section stbroadcast-channels Channels * * The stbroadcast module uses 1 channel. * diff --git a/core/net/rime/stunicast.h b/core/net/rime/stunicast.h index cac93cc84..6e02d88ff 100644 --- a/core/net/rime/stunicast.h +++ b/core/net/rime/stunicast.h @@ -63,7 +63,7 @@ * number of retransmissions for a packet as a packet attribute on * outgoing packets. * - * \section channels Channels + * \section stunicast-channels Channels * * The stunicast module uses 1 channel. * diff --git a/core/net/rime/trickle.h b/core/net/rime/trickle.h index 5a33bec32..1521024b7 100644 --- a/core/net/rime/trickle.h +++ b/core/net/rime/trickle.h @@ -48,7 +48,7 @@ * * The trickle module sends a single packet to all nodes on the network. * - * \section channels Channels + * \section trickle-channels Channels * * The trickle module uses 1 channel. * diff --git a/core/net/rime/unicast.h b/core/net/rime/unicast.h index 9b0e06db7..3cb5bb148 100644 --- a/core/net/rime/unicast.h +++ b/core/net/rime/unicast.h @@ -53,7 +53,7 @@ * single-hop receiver address attribute and discards the packet if * the address does not match the address of the node. * - * \section channels Channels + * \section unicast-channels Channels * * The unicast module uses 1 channel. * diff --git a/core/net/rpl/rpl-conf.h b/core/net/rpl/rpl-conf.h index 3d6aa8b36..95a05a499 100644 --- a/core/net/rpl/rpl-conf.h +++ b/core/net/rpl/rpl-conf.h @@ -195,4 +195,16 @@ #define RPL_PREFERENCE 0 #endif +/* + * Hop-by-hop option + * This option control the insertion of the RPL Hop-by-Hop extension header + * into packets originating from this node. Incoming Hop-by-hop extension + * header are still processed and forwarded. + */ +#ifdef RPL_CONF_INSERT_HBH_OPTION +#define RPL_INSERT_HBH_OPTION RPL_CONF_INSERT_HBH_OPTION +#else +#define RPL_INSERT_HBH_OPTION 1 +#endif + #endif /* RPL_CONF_H */ diff --git a/core/net/rpl/rpl-dag.c b/core/net/rpl/rpl-dag.c index eb92e2f10..7b1908cfe 100644 --- a/core/net/rpl/rpl-dag.c +++ b/core/net/rpl/rpl-dag.c @@ -47,6 +47,7 @@ #include "net/rpl/rpl-private.h" #include "net/ip/uip.h" #include "net/ipv6/uip-nd6.h" +#include "net/ipv6/uip-ds6-nbr.h" #include "net/nbr-table.h" #include "net/ipv6/multicast/uip-mcast6.h" #include "lib/list.h" @@ -79,6 +80,19 @@ NBR_TABLE(rpl_parent_t, rpl_parents); /* Allocate instance table. */ rpl_instance_t instance_table[RPL_MAX_INSTANCES]; rpl_instance_t *default_instance; + +/*---------------------------------------------------------------------------*/ +uip_ds6_nbr_t * +rpl_get_nbr(rpl_parent_t *parent) +{ + linkaddr_t *lladdr = NULL; + lladdr = nbr_table_get_lladdr(rpl_parents, parent); + if(lladdr != NULL) { + return nbr_table_get_from_lladdr(ds6_neighbors, lladdr); + } else { + return NULL; + } +} /*---------------------------------------------------------------------------*/ static void nbr_callback(void *ptr) @@ -113,9 +127,11 @@ rpl_get_parent_rank(uip_lladdr_t *addr) uint16_t rpl_get_parent_link_metric(const uip_lladdr_t *addr) { - rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (const linkaddr_t *)addr); - if(p != NULL) { - return p->link_metric; + uip_ds6_nbr_t *nbr; + nbr = nbr_table_get_from_lladdr(ds6_neighbors, (const linkaddr_t *)addr); + + if(nbr != NULL) { + return nbr->link_metric; } else { return 0; } @@ -568,10 +584,17 @@ rpl_add_parent(rpl_dag_t *dag, rpl_dio_t *dio, uip_ipaddr_t *addr) if(p == NULL) { PRINTF("RPL: rpl_add_parent p NULL\n"); } else { + uip_ds6_nbr_t *nbr; + nbr = rpl_get_nbr(p); + p->dag = dag; p->rank = dio->rank; p->dtsn = dio->dtsn; - p->link_metric = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR; + + /* Check whether we have a neighbor that has not gotten a link metric yet */ + if(nbr != NULL && nbr->link_metric == 0) { + nbr->link_metric = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR; + } #if RPL_DAG_MC != RPL_DAG_MC_NONE memcpy(&p->mc, &dio->mc, sizeof(p->mc)); #endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */ @@ -766,7 +789,6 @@ rpl_nullify_parent(rpl_parent_t *parent) /* This function can be called when the preferred parent is NULL, so we need to handle this condition in order to trigger uip_ds6_defrt_rm. */ if(parent == dag->preferred_parent || dag->preferred_parent == NULL) { - rpl_set_preferred_parent(dag, NULL); dag->rank = INFINITE_RANK; if(dag->joined) { if(dag->instance->def_route != NULL) { @@ -776,7 +798,11 @@ rpl_nullify_parent(rpl_parent_t *parent) uip_ds6_defrt_rm(dag->instance->def_route); dag->instance->def_route = NULL; } - dao_output(parent, RPL_ZERO_LIFETIME); + /* Send no-path DAO only to preferred parent, if any */ + if(parent == dag->preferred_parent) { + dao_output(parent, RPL_ZERO_LIFETIME); + rpl_set_preferred_parent(dag, NULL); + } } } @@ -949,6 +975,7 @@ rpl_join_instance(uip_ipaddr_t *from, rpl_dio_t *dio) } } +#if RPL_MAX_DAG_PER_INSTANCE > 1 /*---------------------------------------------------------------------------*/ void rpl_add_dag(uip_ipaddr_t *from, rpl_dio_t *dio) @@ -1028,6 +1055,7 @@ rpl_add_dag(uip_ipaddr_t *from, rpl_dio_t *dio) rpl_process_parent_event(instance, p); p->dtsn = dio->dtsn; } +#endif /* RPL_MAX_DAG_PER_INSTANCE > 1 */ /*---------------------------------------------------------------------------*/ static void @@ -1037,6 +1065,14 @@ global_repair(uip_ipaddr_t *from, rpl_dag_t *dag, rpl_dio_t *dio) remove_parents(dag, 0); dag->version = dio->version; + + /* copy parts of the configuration so that it propagates in the network */ + dag->instance->dio_intdoubl = dio->dag_intdoubl; + dag->instance->dio_intmin = dio->dag_intmin; + dag->instance->dio_redundancy = dio->dag_redund; + dag->instance->default_lifetime = dio->default_lifetime; + dag->instance->lifetime_unit = dio->lifetime_unit; + dag->instance->of->reset(dag); dag->min_rank = INFINITE_RANK; RPL_LOLLIPOP_INCREMENT(dag->instance->dtsn_out); @@ -1215,9 +1251,14 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio) } if(dag == NULL) { +#if RPL_MAX_DAG_PER_INSTANCE > 1 PRINTF("RPL: Adding new DAG to known instance.\n"); rpl_add_dag(from, dio); return; +#else /* RPL_MAX_DAG_PER_INSTANCE > 1 */ + PRINTF("RPL: Only one instance supported.\n"); + return; +#endif /* RPL_MAX_DAG_PER_INSTANCE > 1 */ } diff --git a/core/net/rpl/rpl-ext-header.c b/core/net/rpl/rpl-ext-header.c index 1b41d05e1..1e3250e20 100644 --- a/core/net/rpl/rpl-ext-header.c +++ b/core/net/rpl/rpl-ext-header.c @@ -215,6 +215,7 @@ rpl_update_header_empty(void) } break; default: +#if RPL_INSERT_HBH_OPTION PRINTF("RPL: No hop-by-hop option found, creating it\n"); if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_BUFSIZE) { PRINTF("RPL: Packet too long: impossible to add hop-by-hop option\n"); @@ -223,6 +224,7 @@ rpl_update_header_empty(void) } set_rpl_opt(uip_ext_opt_offset); uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN; +#endif return 0; } @@ -374,9 +376,11 @@ rpl_invert_header(void) void rpl_insert_header(void) { +#if RPL_INSERT_HBH_OPTION if(default_instance != NULL && !uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { rpl_update_header_empty(); } +#endif } /*---------------------------------------------------------------------------*/ diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 80896ddc3..c9890b706 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -64,7 +64,7 @@ /*---------------------------------------------------------------------------*/ #define RPL_DIO_GROUNDED 0x80 #define RPL_DIO_MOP_SHIFT 3 -#define RPL_DIO_MOP_MASK 0x3c +#define RPL_DIO_MOP_MASK 0x38 #define RPL_DIO_PREFERENCE_MASK 0x07 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) @@ -778,6 +778,7 @@ dao_input(void) rep->state.lifetime = RPL_LIFETIME(instance, lifetime); rep->state.learned_from = learned_from; + rep->state.nopath_received = 0; #if RPL_CONF_MULTICAST fwd_dao: diff --git a/core/net/rpl/rpl-mrhof.c b/core/net/rpl/rpl-mrhof.c index 2d4c2109e..47314917f 100644 --- a/core/net/rpl/rpl-mrhof.c +++ b/core/net/rpl/rpl-mrhof.c @@ -90,16 +90,22 @@ typedef uint16_t rpl_path_metric_t; static rpl_path_metric_t calculate_path_metric(rpl_parent_t *p) { + uip_ds6_nbr_t *nbr; if(p == NULL) { return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR; } - + nbr = rpl_get_nbr(p); + if(nbr == NULL) { + return MAX_PATH_COST * RPL_DAG_MC_ETX_DIVISOR; + } #if RPL_DAG_MC == RPL_DAG_MC_NONE - return p->rank + (uint16_t)p->link_metric; + { + return p->rank + (uint16_t)nbr->link_metric; + } #elif RPL_DAG_MC == RPL_DAG_MC_ETX - return p->mc.obj.etx + (uint16_t)p->link_metric; + return p->mc.obj.etx + (uint16_t)nbr->link_metric; #elif RPL_DAG_MC == RPL_DAG_MC_ENERGY - return p->mc.obj.energy.energy_est + (uint16_t)p->link_metric; + return p->mc.obj.energy.energy_est + (uint16_t)nbr->link_metric; #else #error "Unsupported RPL_DAG_MC configured. See rpl.h." #endif /* RPL_DAG_MC */ @@ -114,9 +120,18 @@ reset(rpl_dag_t *dag) static void neighbor_link_callback(rpl_parent_t *p, int status, int numtx) { - uint16_t recorded_etx = p->link_metric; + uint16_t recorded_etx = 0; uint16_t packet_etx = numtx * RPL_DAG_MC_ETX_DIVISOR; uint16_t new_etx; + uip_ds6_nbr_t *nbr = NULL; + + nbr = rpl_get_nbr(p); + if(nbr == NULL) { + /* No neighbor for this parent - something bad has occurred */ + return; + } + + recorded_etx = nbr->link_metric; /* Do not penalize the ETX when collisions or transmission errors occur. */ if(status == MAC_TX_OK || status == MAC_TX_NOACK) { @@ -139,7 +154,8 @@ neighbor_link_callback(rpl_parent_t *p, int status, int numtx) (unsigned)(recorded_etx / RPL_DAG_MC_ETX_DIVISOR), (unsigned)(new_etx / RPL_DAG_MC_ETX_DIVISOR), (unsigned)(packet_etx / RPL_DAG_MC_ETX_DIVISOR)); - p->link_metric = new_etx; + /* update the link metric for this nbr */ + nbr->link_metric = new_etx; } } @@ -148,14 +164,15 @@ calculate_rank(rpl_parent_t *p, rpl_rank_t base_rank) { rpl_rank_t new_rank; rpl_rank_t rank_increase; + uip_ds6_nbr_t *nbr; - if(p == NULL) { + if(p == NULL || (nbr = rpl_get_nbr(p)) == NULL) { if(base_rank == 0) { return INFINITE_RANK; } rank_increase = RPL_INIT_LINK_METRIC * RPL_DAG_MC_ETX_DIVISOR; } else { - rank_increase = p->link_metric; + rank_increase = nbr->link_metric; if(base_rank == 0) { base_rank = p->rank; } diff --git a/core/net/rpl/rpl-of0.c b/core/net/rpl/rpl-of0.c index 0ad1d710e..ca73169fc 100644 --- a/core/net/rpl/rpl-of0.c +++ b/core/net/rpl/rpl-of0.c @@ -126,26 +126,34 @@ static rpl_parent_t * best_parent(rpl_parent_t *p1, rpl_parent_t *p2) { rpl_rank_t r1, r2; - rpl_dag_t *dag; + rpl_dag_t *dag; + uip_ds6_nbr_t *nbr1, *nbr2; + nbr1 = rpl_get_nbr(p1); + nbr2 = rpl_get_nbr(p2); + + dag = (rpl_dag_t *)p1->dag; /* Both parents must be in the same DAG. */ + + if(nbr1 == NULL || nbr2 == NULL) { + return dag->preferred_parent; + } PRINTF("RPL: Comparing parent "); PRINT6ADDR(rpl_get_parent_ipaddr(p1)); PRINTF(" (confidence %d, rank %d) with parent ", - p1->link_metric, p1->rank); + nbr1->link_metric, p1->rank); PRINT6ADDR(rpl_get_parent_ipaddr(p2)); PRINTF(" (confidence %d, rank %d)\n", - p2->link_metric, p2->rank); + nbr2->link_metric, p2->rank); r1 = DAG_RANK(p1->rank, p1->dag->instance) * RPL_MIN_HOPRANKINC + - p1->link_metric; + nbr1->link_metric; r2 = DAG_RANK(p2->rank, p1->dag->instance) * RPL_MIN_HOPRANKINC + - p2->link_metric; + nbr2->link_metric; /* Compare two parents by looking both and their rank and at the ETX for that parent. We choose the parent that has the most favourable combination. */ - dag = (rpl_dag_t *)p1->dag; /* Both parents must be in the same DAG. */ if(r1 < r2 + MIN_DIFFERENCE && r1 > r2 - MIN_DIFFERENCE) { return dag->preferred_parent; diff --git a/core/net/rpl/rpl-timers.c b/core/net/rpl/rpl-timers.c index 4d4e8ca43..ea7bfe7f2 100644 --- a/core/net/rpl/rpl-timers.c +++ b/core/net/rpl/rpl-timers.c @@ -145,7 +145,7 @@ handle_dio_timer(void *ptr) if(instance->dio_send) { /* send DIO if counter is less than desired redundancy */ - if(instance->dio_counter < instance->dio_redundancy) { + if(instance->dio_redundancy != 0 && instance->dio_counter < instance->dio_redundancy) { #if RPL_CONF_STATS instance->dio_totsend++; #endif /* RPL_CONF_STATS */ diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index f71c5fb4c..f92d5f5f8 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -76,9 +76,9 @@ rpl_set_mode(enum rpl_mode m) switching to. */ if(m == RPL_MODE_MESH) { - /* If we switcht to mesh mode, we should send out a DAO message to + /* If we switch to mesh mode, we should send out a DAO message to inform our parent that we now are reachable. Before we do this, - we must set the mode variable, since DAOs will not be send if + we must set the mode variable, since DAOs will not be sent if we are in feather mode. */ PRINTF("RPL: switching to mesh mode\n"); mode = m; diff --git a/core/net/rpl/rpl.h b/core/net/rpl/rpl.h index 512c2f5f1..512c1a8f0 100644 --- a/core/net/rpl/rpl.h +++ b/core/net/rpl/rpl.h @@ -114,7 +114,6 @@ struct rpl_parent { rpl_metric_container_t mc; #endif /* RPL_DAG_MC != RPL_DAG_MC_NONE */ rpl_rank_t rank; - uint16_t link_metric; uint8_t dtsn; uint8_t flags; }; @@ -251,7 +250,7 @@ rpl_parent_t *rpl_get_parent(uip_lladdr_t *addr); rpl_rank_t rpl_get_parent_rank(uip_lladdr_t *addr); uint16_t rpl_get_parent_link_metric(const uip_lladdr_t *addr); void rpl_dag_init(void); - +uip_ds6_nbr_t *rpl_get_nbr(rpl_parent_t *parent); /** * RPL modes diff --git a/core/sys/cc.h b/core/sys/cc.h index 53a5af4db..90ef3e710 100644 --- a/core/sys/cc.h +++ b/core/sys/cc.h @@ -133,7 +133,7 @@ * strings. * * We need use two macros (CC_CONCAT and CC_CONCAT2) in order to allow - * concatenation of two #defined macros. + * concatenation of two \#defined macros. */ #define CC_CONCAT(s1, s2) CC_CONCAT2(s1, s2) diff --git a/core/sys/clock.h b/core/sys/clock.h index 46232273e..4cbfdb223 100644 --- a/core/sys/clock.h +++ b/core/sys/clock.h @@ -57,7 +57,7 @@ * * \note The clock library need in many cases not be used * directly. Rather, the \ref timer "timer library", \ref etimer - * "event timers", or \ref trimer "rtimer library" should be used. + * "event timers", or \ref rtimer "rtimer library" should be used. * * \sa \ref timer "Timer library" * \sa \ref etimer "Event timers" diff --git a/core/sys/dsc.h b/core/sys/dsc.h index ad7632390..b8b70433e 100644 --- a/core/sys/dsc.h +++ b/core/sys/dsc.h @@ -105,7 +105,7 @@ struct dsc { * * \param prgname The name of the program on disk. * - * \param initfunc A pointer to the initialization function of the + * \param process A pointer to the initialization function of the * program. * * \param icon A pointer to the CTK icon. diff --git a/core/sys/process.c b/core/sys/process.c index ef28f80f4..b2ed5701c 100644 --- a/core/sys/process.c +++ b/core/sys/process.c @@ -267,7 +267,7 @@ do_event(void) receiver = events[fevent].p; /* Since we have seen the new event, we move pointer upwards - and decrese the number of events. */ + and decrease the number of events. */ fevent = (fevent + 1) % PROCESS_CONF_NUMEVENTS; --nevents; @@ -337,7 +337,7 @@ process_post(struct process *p, process_event_t ev, process_data_t data) if(p == PROCESS_BROADCAST) { printf("soft panic: event queue is full when broadcast event %d was posted from %s\n", ev, PROCESS_NAME_STRING(process_current)); } else { - printf("soft panic: event queue is full when event %d was posted to %s frpm %s\n", ev, PROCESS_NAME_STRING(p), PROCESS_NAME_STRING(process_current)); + printf("soft panic: event queue is full when event %d was posted to %s from %s\n", ev, PROCESS_NAME_STRING(p), PROCESS_NAME_STRING(process_current)); } #endif /* DEBUG */ return PROCESS_ERR_FULL; diff --git a/core/sys/process.h b/core/sys/process.h index 43547f3bd..2d15ca89c 100644 --- a/core/sys/process.h +++ b/core/sys/process.h @@ -335,7 +335,7 @@ struct process { * * \param p A pointer to a process structure. * - * \param arg An argument pointer that can be passed to the new + * \param data An argument pointer that can be passed to the new * process * */ diff --git a/core/sys/timer.c b/core/sys/timer.c index ea0710911..6fe64119b 100644 --- a/core/sys/timer.c +++ b/core/sys/timer.c @@ -76,8 +76,9 @@ timer_set(struct timer *t, clock_time_t interval) * function will cause the timer to be stable over time, unlike the * timer_restart() function. * - * \param t A pointer to the timer. + * \note Must not be executed before timer expired * + * \param t A pointer to the timer. * \sa timer_restart() */ void diff --git a/cpu/6502/ipconfig/ipconfig.c b/cpu/6502/ipconfig/ipconfig.c index d21994032..5452b735a 100644 --- a/cpu/6502/ipconfig/ipconfig.c +++ b/cpu/6502/ipconfig/ipconfig.c @@ -117,7 +117,7 @@ makestrings(void) makeaddr(&addr, gateway); #if WITH_DNS - addrptr = resolv_getserver(); + addrptr = uip_nameserver_get(0); if(addrptr != NULL) { makeaddr(addrptr, dnsserver); } @@ -245,7 +245,7 @@ dhcpc_configured(const struct dhcpc_state *s) uip_setnetmask(&s->netmask); uip_setdraddr(&s->default_router); #if WITH_DNS - resolv_conf(&s->dnsaddr); + uip_nameserver_update(&s->dnsaddr, UIP_NAMESERVER_INFINITE_LIFETIME); #endif /* WITH_DNS */ set_statustext("Configured."); @@ -261,7 +261,7 @@ dhcpc_unconfigured(const struct dhcpc_state *s) uip_setnetmask(&nulladdr); uip_setdraddr(&nulladdr); #if WITH_DNS - resolv_conf(&nulladdr); + uip_nameserver_update(&nulladdr, UIP_NAMESERVER_INFINITE_LIFETIME); #endif /* WITH_DNS */ set_statustext("Unconfigured."); diff --git a/cpu/6502/lib/config.c b/cpu/6502/lib/config.c index 08677a682..545c47116 100644 --- a/cpu/6502/lib/config.c +++ b/cpu/6502/lib/config.c @@ -105,7 +105,7 @@ config_read(char *filename) uip_setnetmask(&config.netmask); uip_setdraddr(&config.draddr); #if WITH_DNS - resolv_conf(&config.resolvaddr); + uip_nameserver_update(&config.resolvaddr, UIP_NAMESERVER_INFINITE_LIFETIME); #endif /* WITH_DNS */ return &config.ethernetcfg; diff --git a/cpu/arm/aducrf101/Makefile.aducrf101.gnu b/cpu/arm/aducrf101/Makefile.aducrf101.gnu index 93de277a2..bafb06aa9 100644 --- a/cpu/arm/aducrf101/Makefile.aducrf101.gnu +++ b/cpu/arm/aducrf101/Makefile.aducrf101.gnu @@ -39,8 +39,8 @@ CROSS_COMPILE = arm-none-eabi- CC = $(CROSS_COMPILE)gcc LD = $(CROSS_COMPILE)gcc AS = $(CROSS_COMPILE)gcc -AR = $(CROSS_COMPILE)ar -NM = $(CROSS_COMPILE)nm +AR = $(CROSS_COMPILE)gcc-ar +NM = $(CROSS_COMPILE)gcc-nm OBJCOPY = $(CROSS_COMPILE)objcopy OBJDUMP = $(CROSS_COMPILE)objdump STRIP = $(CROSS_COMPILE)strip diff --git a/cpu/avr/dev/clock.c b/cpu/avr/dev/clock.c index 7fcc72063..fdb2acce4 100644 --- a/cpu/avr/dev/clock.c +++ b/cpu/avr/dev/clock.c @@ -159,7 +159,7 @@ clock_set_seconds(unsigned long sec) seconds = sec; } /*---------------------------------------------------------------------------*/ -/** +/* * Wait for a number of clock ticks. */ void @@ -175,7 +175,7 @@ clock_wait(clock_time_t t) } } /*---------------------------------------------------------------------------*/ -/** +/* * Delay the CPU for up to 65535*(4000000/F_CPU) microseconds. * Copied from _delay_loop_2 in AVR library delay_basic.h, 4 clocks per loop. * For accurate short delays, inline _delay_loop_2 in the caller, use a constant @@ -193,44 +193,44 @@ my_delay_loop_2(uint16_t __count) ); } void -clock_delay_usec(uint16_t howlong) +clock_delay_usec(uint16_t dt) { #if 0 /* Accurate delay at any frequency, but introduces a 64 bit intermediate * and has a 279 clock overhead. */ - if(howlong<=(uint16_t)(279000000UL/F_CPU)) return; - howlong-=(uint16_t) (279000000UL/F_CPU); - my_delay_loop_2(((uint64_t)(howlong) * (uint64_t) F_CPU) / 4000000ULL); + if(dt<=(uint16_t)(279000000UL/F_CPU)) return; + dt-=(uint16_t) (279000000UL/F_CPU); + my_delay_loop_2(((uint64_t)(dt) * (uint64_t) F_CPU) / 4000000ULL); /* Remaining numbers tweaked for the breakpoint CPU frequencies */ /* Add other frequencies as necessary */ #elif F_CPU>=16000000UL - if(howlong<1) return; - my_delay_loop_2((howlong*(uint16_t)(F_CPU/3250000))); + if(dt<1) return; + my_delay_loop_2((dt*(uint16_t)(F_CPU/3250000))); #elif F_CPU >= 12000000UL - if(howlong<2) return; - howlong-=(uint16_t) (3*12000000/F_CPU); - my_delay_loop_2((howlong*(uint16_t)(F_CPU/3250000))); + if(dt<2) return; + dt-=(uint16_t) (3*12000000/F_CPU); + my_delay_loop_2((dt*(uint16_t)(F_CPU/3250000))); #elif F_CPU >= 8000000UL - if(howlong<4) return; - howlong-=(uint16_t) (3*8000000/F_CPU); - my_delay_loop_2((howlong*(uint16_t)(F_CPU/2000000))/2); + if(dt<4) return; + dt-=(uint16_t) (3*8000000/F_CPU); + my_delay_loop_2((dt*(uint16_t)(F_CPU/2000000))/2); #elif F_CPU >= 4000000UL - if(howlong<5) return; - howlong-=(uint16_t) (4*4000000/F_CPU); - my_delay_loop_2((howlong*(uint16_t)(F_CPU/2000000))/2); + if(dt<5) return; + dt-=(uint16_t) (4*4000000/F_CPU); + my_delay_loop_2((dt*(uint16_t)(F_CPU/2000000))/2); #elif F_CPU >= 2000000UL - if(howlong<11) return; - howlong-=(uint16_t) (10*2000000/F_CPU); - my_delay_loop_2((howlong*(uint16_t)(F_CPU/1000000))/4); + if(dt<11) return; + dt-=(uint16_t) (10*2000000/F_CPU); + my_delay_loop_2((dt*(uint16_t)(F_CPU/1000000))/4); #elif F_CPU >= 1000000UL - if(howlong<=17) return; - howlong-=(uint16_t) (17*1000000/F_CPU); - my_delay_loop_2((howlong*(uint16_t)(F_CPU/1000000))/4); + if(dt<=17) return; + dt-=(uint16_t) (17*1000000/F_CPU); + my_delay_loop_2((dt*(uint16_t)(F_CPU/1000000))/4); #else - howlong >> 5; - if (howlong < 1) return; - my_delay_loop_2(howlong); + dt >> 5; + if (dt < 1) return; + my_delay_loop_2(dt); #endif } #if 0 @@ -250,7 +250,7 @@ clock_delay(unsigned int howlong) /*---------------------------------------------------------------------------*/ /** * Delay up to 65535 milliseconds. - * \param dt How many milliseconds to delay. + * \param howlong How many milliseconds to delay. * * Neither interrupts nor the watchdog timer is disabled over the delay. * Platforms are not required to implement this call. @@ -279,7 +279,7 @@ clock_delay_msec(uint16_t howlong) /*---------------------------------------------------------------------------*/ /** * Adjust the system current clock time. - * \param dt How many ticks to add + * \param howmany How many ticks to add * * Typically used to add ticks after an MCU sleep * clock_seconds will increment if necessary to reflect the tick addition. diff --git a/cpu/avr/radio/rf230bb/rf230bb.h b/cpu/avr/radio/rf230bb/rf230bb.h index 020c3250f..30de9a1e5 100644 --- a/cpu/avr/radio/rf230bb/rf230bb.h +++ b/cpu/avr/radio/rf230bb/rf230bb.h @@ -49,8 +49,8 @@ * */ -#ifndef RADIO_H -#define RADIO_H +#ifndef RF230BB_H_ +#define RF230BB_H_ /*============================ INCLUDE =======================================*/ #include #include @@ -225,6 +225,6 @@ uint8_t rf230_get_raw_rssi(void); #define rf230_rssi rf230_get_raw_rssi -#endif +#endif /* RF230BB_H_ */ /** @} */ /*EOF*/ diff --git a/cpu/cc2430/dev/clock.c b/cpu/cc2430/dev/clock.c index c0b8f2c9d..1fc781b1b 100644 --- a/cpu/cc2430/dev/clock.c +++ b/cpu/cc2430/dev/clock.c @@ -54,7 +54,7 @@ static unsigned long timer_value; static volatile CC_AT_DATA clock_time_t count = 0; /* Uptime in ticks */ static volatile CC_AT_DATA clock_time_t seconds = 0; /* Uptime in secs */ /*---------------------------------------------------------------------------*/ -/** +/* * Each iteration is ~1.0xy usec, so this function delays for roughly len usec */ void @@ -68,7 +68,7 @@ clock_delay_usec(uint16_t len) ENABLE_INTERRUPTS(); } /*---------------------------------------------------------------------------*/ -/** +/* * Wait for a multiple of ~8 ms (a tick) */ void diff --git a/cpu/cc2538/Makefile.cc2538 b/cpu/cc2538/Makefile.cc2538 index b172101d1..9fd8a08be 100644 --- a/cpu/cc2538/Makefile.cc2538 +++ b/cpu/cc2538/Makefile.cc2538 @@ -52,6 +52,7 @@ CONTIKI_CPU_SOURCEFILES += nvic.c cpu.c sys-ctrl.c gpio.c ioc.c spi.c adc.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 DEBUG_IO_SOURCEFILES += dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c diff --git a/cpu/cc2538/clock.c b/cpu/cc2538/clock.c index 98abdf2e3..c0abed38b 100644 --- a/cpu/cc2538/clock.c +++ b/cpu/cc2538/clock.c @@ -96,17 +96,17 @@ clock_init(void) REG(SYS_CTRL_RCGCGPT) |= SYS_CTRL_RCGCGPT_GPT0; /* Make sure GPT0 is off */ - REG(GPT_0_BASE | GPTIMER_CTL) = 0; + REG(GPT_0_BASE + GPTIMER_CTL) = 0; /* 16-bit */ - REG(GPT_0_BASE | GPTIMER_CFG) = 0x04; + REG(GPT_0_BASE + GPTIMER_CFG) = 0x04; /* One-Shot, Count Down, No Interrupts */ - REG(GPT_0_BASE | GPTIMER_TAMR) = GPTIMER_TAMR_TAMR_ONE_SHOT; + 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; + REG(GPT_0_BASE + GPTIMER_TAPR) = 0x0F; } /*---------------------------------------------------------------------------*/ CCIF clock_time_t @@ -136,20 +136,19 @@ clock_wait(clock_time_t i) while(clock_time() - start < (clock_time_t)i); } /*---------------------------------------------------------------------------*/ -/** - * \brief Arch-specific implementation of clock_delay_usec for the cc2538 - * \param len Delay \e len uSecs +/* + * Arch-specific implementation of clock_delay_usec for the cc2538 * * See clock_init() for GPT0 Timer A's configuration */ void -clock_delay_usec(uint16_t len) +clock_delay_usec(uint16_t dt) { - REG(GPT_0_BASE | GPTIMER_TAILR) = len; - REG(GPT_0_BASE | GPTIMER_CTL) |= GPTIMER_CTL_TAEN; + REG(GPT_0_BASE + GPTIMER_TAILR) = dt; + REG(GPT_0_BASE + GPTIMER_CTL) |= GPTIMER_CTL_TAEN; /* One-Shot mode: TAEN will be cleared when the timer reaches 0 */ - while(REG(GPT_0_BASE | GPTIMER_CTL) & GPTIMER_CTL_TAEN); + while(REG(GPT_0_BASE + GPTIMER_CTL) & GPTIMER_CTL_TAEN); } /*---------------------------------------------------------------------------*/ /** diff --git a/cpu/cc2538/cpu.h b/cpu/cc2538/cpu.h index e8cd7e282..51ffa9075 100644 --- a/cpu/cc2538/cpu.h +++ b/cpu/cc2538/cpu.h @@ -29,12 +29,21 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /** - * \addtogroup cc2538 + * \addtogroup platform + * @{ + * + * \defgroup cc2538-platforms TI cc2538-powered platforms + * + * Documentation for all platforms powered by the TI cc2538 System-on-Chip + * @{ + * + * \defgroup cc2538 The TI cc2538 System-on-Chip + * CPU-Specific functionality - available to all cc2538-based platforms * @{ * * \defgroup cc2538-cpu cc2538 CPU * - * cc2538 CPU-specific functions for the cc2538 core + * CPU-specific functions for the cc2538 core * @{ * * \file @@ -60,6 +69,8 @@ unsigned long cpu_cpsie(void); #endif /* CPU_H_ */ /** + * @} + * @} * @} * @} */ diff --git a/cpu/cc2538/dbg.h b/cpu/cc2538/dbg.h index d861cadd7..2e283c0b1 100644 --- a/cpu/cc2538/dbg.h +++ b/cpu/cc2538/dbg.h @@ -34,7 +34,7 @@ * * \defgroup cc2538-char-io cc2538 Character I/O * - * cc2538 CPU-specific functions for debugging and SLIP I/O + * CPU-specific functions for debugging and SLIP I/O * * On the cc2538, character I/O can be directed over USB or UART. This is * controlled by a series of configuration directives: diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index f20354cc2..e8ec81309 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -122,6 +122,7 @@ static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /** Snif */ #endif /*---------------------------------------------------------------------------*/ static uint8_t rf_flags; +static uint8_t rf_channel = CC2538_RF_CHANNEL; static int on(void); static int off(void); @@ -186,10 +187,22 @@ set_channel(uint8_t channel) } /* Changes to FREQCTRL take effect after the next recalibration */ - off(); + + /* 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; + off(); + } REG(RFCORE_XREG_FREQCTRL) = (CC2538_RF_CHANNEL_MIN + (channel - CC2538_RF_CHANNEL_MIN) * CC2538_RF_CHANNEL_SPACING); - on(); + /* 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) { + on(); + } + + rf_channel = channel; return (int8_t) channel; } @@ -445,7 +458,7 @@ init(void) /* Set TX Power */ REG(RFCORE_XREG_TXPOWER) = CC2538_RF_TX_POWER; - set_channel(CC2538_RF_CHANNEL); + set_channel(rf_channel); /* Acknowledge RF interrupts, FIFOP only */ REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP; @@ -951,10 +964,21 @@ PROCESS_THREAD(cc2538_rf_process, ev, data) /* If we were polled due to an RF error, reset the transceiver */ if(rf_flags & RF_MUST_RESET) { + uint8_t was_on; rf_flags = 0; + /* save state so we know if to switch on again after re-init */ + if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) == 0) { + was_on = 0; + } else { + was_on = 1; + } off(); init(); + if(was_on) { + /* switch back on */ + on(); + } } } diff --git a/cpu/cc2538/dev/gpio.c b/cpu/cc2538/dev/gpio.c index 2961a2eb0..581e52839 100644 --- a/cpu/cc2538/dev/gpio.c +++ b/cpu/cc2538/dev/gpio.c @@ -87,7 +87,7 @@ gpio_port_a_isr() ENERGEST_ON(ENERGEST_TYPE_IRQ); - notify(REG(GPIO_A_BASE | GPIO_MIS), GPIO_A_NUM); + notify(REG(GPIO_A_BASE + GPIO_MIS), GPIO_A_NUM); GPIO_CLEAR_INTERRUPT(GPIO_A_BASE, 0xFF); GPIO_CLEAR_POWER_UP_INTERRUPT(GPIO_A_NUM, 0xFF); @@ -103,7 +103,7 @@ gpio_port_b_isr() ENERGEST_ON(ENERGEST_TYPE_IRQ); - notify(REG(GPIO_B_BASE | GPIO_MIS), GPIO_B_NUM); + 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); @@ -119,7 +119,7 @@ gpio_port_c_isr() ENERGEST_ON(ENERGEST_TYPE_IRQ); - notify(REG(GPIO_C_BASE | GPIO_MIS), GPIO_C_NUM); + 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); @@ -135,7 +135,7 @@ gpio_port_d_isr() ENERGEST_ON(ENERGEST_TYPE_IRQ); - notify(REG(GPIO_D_BASE | GPIO_MIS), GPIO_D_NUM); + 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); diff --git a/cpu/cc2538/dev/gpio.h b/cpu/cc2538/dev/gpio.h index 8a61f668b..33980501b 100644 --- a/cpu/cc2538/dev/gpio.h +++ b/cpu/cc2538/dev/gpio.h @@ -91,56 +91,76 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_SET_INPUT(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_DIR) &= ~(PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_DIR) &= ~(PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE to output. * \param PORT_BASE GPIO Port register offset * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_SET_OUTPUT(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_DIR) |= (PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_DIR) |= (PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE high. * \param PORT_BASE GPIO Port register offset * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_SET_PIN(PORT_BASE, PIN_MASK) \ - do { REG(((PORT_BASE) | GPIO_DATA) + ((PIN_MASK) << 2)) = 0xFF; } while(0) + do { REG((PORT_BASE) + GPIO_DATA + ((PIN_MASK) << 2)) = 0xFF; } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE low. * \param PORT_BASE GPIO Port register offset * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_CLR_PIN(PORT_BASE, PIN_MASK) \ - do { REG(((PORT_BASE) | GPIO_DATA) + ((PIN_MASK) << 2)) = 0x00; } while(0) + do { REG((PORT_BASE) + GPIO_DATA + ((PIN_MASK) << 2)) = 0x00; } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE to value. * \param PORT_BASE GPIO Port register offset * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 + * \param value The new value to write to the register. Only pins specified + * by PIN_MASK will be set. + * + * \note The outcome of this macro invocation will be to write to the register + * a new value for multiple pins. For that reason, the value argument cannot be + * a simple 0 or 1. Instead, it must be the value corresponding to the pins that + * you wish to set. + * + * Thus, if you only want to set a single pin (e.g. pin 2), do \e not pass 1, + * but you must pass 0x04 instead (1 << 2). This may seem counter-intuitive at + * first glance, but it allows a single invocation of this macro to set + * multiple pins in one go if so desired. For example, you can set pins 3 and 1 + * and the same time clear pins 2 and 0. To do so, pass 0x0F as the PIN_MASK + * and then use 0x0A as the value ((1 << 3) | (1 << 1) for pins 3 and 1) */ #define GPIO_WRITE_PIN(PORT_BASE, PIN_MASK, value) \ - do { REG(((PORT_BASE) | GPIO_DATA) + ((PIN_MASK) << 2)) = (value); } while(0) + do { REG((PORT_BASE) + GPIO_DATA + ((PIN_MASK) << 2)) = (value); } while(0) /** \brief Read pins with PIN_MASK of port with PORT_BASE. * \param PORT_BASE GPIO Port register offset * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 + * \return The value of the pins specified by PIN_MASK + * + * This macro will \e not return 0 or 1. Instead, it will return the values of + * the pins specified by PIN_MASK ORd together. Thus, if you pass 0xC3 + * (0x80 | 0x40 | 0x02 | 0x01) as the PIN_MASK and pins 7 and 0 are high, + * the macro will return 0x81. */ #define GPIO_READ_PIN(PORT_BASE, PIN_MASK) \ - REG(((PORT_BASE) | GPIO_DATA) + ((PIN_MASK) << 2)) + REG((PORT_BASE) + GPIO_DATA + ((PIN_MASK) << 2)) /** \brief Set pins with PIN_MASK of port with PORT_BASE to detect edge. * \param PORT_BASE GPIO Port register offset * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_DETECT_EDGE(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IS) &= ~(PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IS) &= ~(PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE to detect level. * \param PORT_BASE GPIO Port register offset * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_DETECT_LEVEL(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IS) |= (PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IS) |= (PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE to trigger an * interrupt on both edges. @@ -148,7 +168,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_TRIGGER_BOTH_EDGES(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IBE) |= (PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IBE) |= (PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE to trigger an * interrupt on single edge (controlled by GPIO_IEV). @@ -156,7 +176,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_TRIGGER_SINGLE_EDGE(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IBE) &= ~(PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IBE) &= ~(PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE to trigger an * interrupt on rising edge. @@ -164,7 +184,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_DETECT_RISING(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IEV) |= (PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IEV) |= (PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port with PORT_BASE to trigger an * interrupt on falling edge. @@ -172,7 +192,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_DETECT_FALLING(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IEV) &= ~(PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IEV) &= ~(PIN_MASK); } while(0) /** \brief Enable interrupt triggering for pins with PIN_MASK of port with * PORT_BASE. @@ -180,7 +200,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_ENABLE_INTERRUPT(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IE) |= (PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IE) |= (PIN_MASK); } while(0) /** \brief Disable interrupt triggering for pins with PIN_MASK of port with * PORT_BASE. @@ -188,7 +208,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_DISABLE_INTERRUPT(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IE) &= ~(PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IE) &= ~(PIN_MASK); } while(0) /** \brief Clear interrupt triggering for pins with PIN_MASK of port with * PORT_BASE. @@ -196,7 +216,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_CLEAR_INTERRUPT(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_IC) = (PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_IC) = (PIN_MASK); } while(0) /** \brief Configure the pin to be under peripheral control with PIN_MASK of * port with PORT_BASE. @@ -204,7 +224,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_PERIPHERAL_CONTROL(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_AFSEL) |= (PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_AFSEL) |= (PIN_MASK); } while(0) /** \brief Configure the pin to be software controlled with PIN_MASK of port * with PORT_BASE. @@ -212,7 +232,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_SOFTWARE_CONTROL(PORT_BASE, PIN_MASK) \ - do { REG((PORT_BASE) | GPIO_AFSEL) &= ~(PIN_MASK); } while(0) + do { REG((PORT_BASE) + GPIO_AFSEL) &= ~(PIN_MASK); } while(0) /** \brief Set pins with PIN_MASK of port PORT to trigger a power-up interrupt * on rising edge. @@ -220,7 +240,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_POWER_UP_ON_RISING(PORT, PIN_MASK) \ - do { REG(GPIO_PORT_TO_BASE(PORT) | GPIO_P_EDGE_CTRL) &= \ + do { REG(GPIO_PORT_TO_BASE(PORT) + GPIO_P_EDGE_CTRL) &= \ ~((PIN_MASK) << ((PORT) << 3)); } while(0) /** \brief Set pins with PIN_MASK of port PORT to trigger a power-up interrupt @@ -229,7 +249,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_POWER_UP_ON_FALLING(PORT, PIN_MASK) \ - do { REG(GPIO_PORT_TO_BASE(PORT) | GPIO_P_EDGE_CTRL) |= \ + do { REG(GPIO_PORT_TO_BASE(PORT) + GPIO_P_EDGE_CTRL) |= \ (PIN_MASK) << ((PORT) << 3); } while(0) /** \brief Enable power-up interrupt triggering for pins with PIN_MASK of port @@ -238,7 +258,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_ENABLE_POWER_UP_INTERRUPT(PORT, PIN_MASK) \ - do { REG(GPIO_PORT_TO_BASE(PORT) | GPIO_PI_IEN) |= \ + do { REG(GPIO_PORT_TO_BASE(PORT) + GPIO_PI_IEN) |= \ (PIN_MASK) << ((PORT) << 3); } while(0) /** \brief Disable power-up interrupt triggering for pins with PIN_MASK of port @@ -247,7 +267,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_DISABLE_POWER_UP_INTERRUPT(PORT, PIN_MASK) \ - do { REG(GPIO_PORT_TO_BASE(PORT) | GPIO_PI_IEN) &= \ + do { REG(GPIO_PORT_TO_BASE(PORT) + GPIO_PI_IEN) &= \ ~((PIN_MASK) << ((PORT) << 3)); } while(0) /** \brief Clear power-up interrupt triggering for pins with PIN_MASK of port @@ -256,12 +276,12 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 */ #define GPIO_CLEAR_POWER_UP_INTERRUPT(PORT, PIN_MASK) \ - do { REG(GPIO_PORT_TO_BASE(PORT) | GPIO_IRQ_DETECT_ACK) = \ + do { REG(GPIO_PORT_TO_BASE(PORT) + GPIO_IRQ_DETECT_ACK) = \ (PIN_MASK) << ((PORT) << 3); } while(0) /** * \brief Converts a pin number to a pin mask - * \param The pin number in the range [0..7] + * \param PIN The pin number in the range [0..7] * \return A pin mask which can be used as the PIN_MASK argument of the macros * in this category */ @@ -269,7 +289,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); /** * \brief Converts a port number to the port base address - * \param The port number in the range 0 - 3. Likely GPIO_X_NUM. + * \param PORT The port number in the range 0 - 3. Likely GPIO_X_NUM. * \return The base address for the registers corresponding to that port * number. */ diff --git a/cpu/cc2538/dev/i2c.c b/cpu/cc2538/dev/i2c.c new file mode 100644 index 000000000..29ded2967 --- /dev/null +++ b/cpu/cc2538/dev/i2c.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2015, Mehdi Migault + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this 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-i2c cc2538 I2C Control + * @{ + * + * \file + * Implementation file of the I2C Control module + * + * \author + * Mehdi Migault + */ + +#include "i2c.h" + +#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); +} +/*---------------------------------------------------------------------------*/ +void +i2c_init(uint8_t port_sda, uint8_t pin_sda, uint8_t port_scl, uint8_t pin_scl, + uint32_t bus_speed) +{ + /* Enable I2C clock in different modes */ + REG(SYS_CTRL_RCGCI2C) |= 1; /* Run mode */ + + /* Reset I2C peripheral */ + REG(SYS_CTRL_SRI2C) |= 1; /* Reset position */ + + /* Delay for a little bit */ + clock_delay_usec(50); + + REG(SYS_CTRL_SRI2C) &= ~1; /* Normal position */ + + /* Set pins in input */ + GPIO_SET_INPUT(GPIO_PORT_TO_BASE(port_sda), GPIO_PIN_MASK(pin_sda)); + GPIO_SET_INPUT(GPIO_PORT_TO_BASE(port_scl), GPIO_PIN_MASK(pin_scl)); + + /* Set peripheral control for the pins */ + GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(port_sda), GPIO_PIN_MASK(pin_sda)); + GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(port_scl), GPIO_PIN_MASK(pin_scl)); + + /* Set the pad to no drive type */ + ioc_set_over(port_sda, pin_sda, IOC_OVERRIDE_DIS); + ioc_set_over(port_scl, pin_scl, IOC_OVERRIDE_DIS); + + /* Set pins as peripheral inputs */ + REG(IOC_I2CMSSDA) = ioc_input_sel(port_sda, pin_sda); + REG(IOC_I2CMSSCL) = ioc_input_sel(port_scl, pin_scl); + + /* Set pins as peripheral outputs */ + ioc_set_sel(port_sda, pin_sda, IOC_PXX_SEL_I2C_CMSSDA); + ioc_set_sel(port_scl, pin_scl, IOC_PXX_SEL_I2C_CMSSCL); + + /* Enable the I2C master module */ + i2c_master_enable(); + + /* t the master clock frequency */ + i2c_set_frequency(bus_speed); +} +/*---------------------------------------------------------------------------*/ +void +i2c_master_enable(void) +{ + REG(I2CM_CR) |= 0x10; /* Set MFE bit */ +} +/*---------------------------------------------------------------------------*/ +void +i2c_master_disable(void) +{ + REG(I2CM_CR) &= ~0x10; /* Reset MFE bit */ +} +/*---------------------------------------------------------------------------*/ +void +i2c_set_frequency(uint32_t freq) +{ + /* Peripheral clock setting, using the system clock */ + REG(I2CM_TPR) = ((get_sys_clock() + (2 * 10 * freq) - 1) / + (2 * 10 * freq)) - 1; +} +/*---------------------------------------------------------------------------*/ +void +i2c_master_set_slave_address(uint8_t slave_addr, uint8_t access_mode) +{ + if(access_mode) { + REG(I2CM_SA) = ((slave_addr << 1) | 1); + } else { + REG(I2CM_SA) = (slave_addr << 1); + } +} +/*---------------------------------------------------------------------------*/ +void +i2c_master_data_put(uint8_t data) +{ + REG(I2CM_DR) = data; +} +/*---------------------------------------------------------------------------*/ +uint8_t +i2c_master_data_get(void) +{ + return REG(I2CM_DR); +} +/*---------------------------------------------------------------------------*/ +void +i2c_master_command(uint8_t cmd) +{ + REG(I2CM_CTRL) = cmd; + /* Here we need a delay, otherwise the I2C module keep the receiver mode */ + clock_delay_usec(1); +} +/*---------------------------------------------------------------------------*/ +uint8_t +i2c_master_busy(void) +{ + return REG(I2CM_STAT) & I2CM_STAT_BUSY; +} +/*---------------------------------------------------------------------------*/ +uint8_t +i2c_master_error(void) +{ + uint8_t temp = REG(I2CM_STAT); /* Get all status */ + if(temp & I2CM_STAT_BUSY) { /* No valid if BUSY bit is set */ + return I2C_MASTER_ERR_NONE; + } else if(temp & (I2CM_STAT_ERROR | I2CM_STAT_ARBLST)) { + return temp; /* Compare later */ + } + return I2C_MASTER_ERR_NONE; +} +/*---------------------------------------------------------------------------*/ +uint8_t +i2c_single_send(uint8_t slave_addr, uint8_t data) +{ + i2c_master_set_slave_address(slave_addr, I2C_SEND); + i2c_master_data_put(data); + i2c_master_command(I2C_MASTER_CMD_SINGLE_SEND); + + while(i2c_master_busy()); + + /* Return the STAT register of I2C module if error occured, I2C_MASTER_ERR_NONE otherwise */ + return i2c_master_error(); +} +/*---------------------------------------------------------------------------*/ +uint8_t +i2c_single_receive(uint8_t slave_addr, uint8_t *data) +{ + uint32_t temp; + + i2c_master_set_slave_address(slave_addr, I2C_RECEIVE); + i2c_master_command(I2C_MASTER_CMD_SINGLE_RECEIVE); + + while(i2c_master_busy()); + temp = i2c_master_error(); + if(temp == I2C_MASTER_ERR_NONE) { + *data = i2c_master_data_get(); + } + return temp; +} +/*---------------------------------------------------------------------------*/ +uint8_t +i2c_burst_send(uint8_t slave_addr, uint8_t *data, uint8_t len) +{ + uint8_t sent; + if((len == 0) || (data == NULL)) { + return I2CM_STAT_INVALID; + } + if(len == 1) { + return i2c_single_send(slave_addr, data[0]); + } + i2c_master_set_slave_address(slave_addr, I2C_SEND); + i2c_master_data_put(data[0]); + i2c_master_command(I2C_MASTER_CMD_BURST_SEND_START); + while(i2c_master_busy()); + if(i2c_master_error() == I2C_MASTER_ERR_NONE) { + for(sent = 1; sent <= (len - 2); sent++) { + i2c_master_data_put(data[sent]); + i2c_master_command(I2C_MASTER_CMD_BURST_SEND_CONT); + while(i2c_master_busy()); + } + /* This should be the last byte, stop sending */ + i2c_master_data_put(data[len - 1]); + i2c_master_command(I2C_MASTER_CMD_BURST_SEND_FINISH); + while(i2c_master_busy()); + } + + /* Return the STAT register of I2C module if error occurred, I2C_MASTER_ERR_NONE otherwise */ + return i2c_master_error(); +} +/*---------------------------------------------------------------------------*/ +uint8_t +i2c_burst_receive(uint8_t slave_addr, uint8_t *data, uint8_t len) +{ + uint8_t recv = 0; + if((len == 0) || data == NULL) { + return I2CM_STAT_INVALID; + } + if(len == 1) { + return i2c_single_receive(slave_addr, &data[0]); + } + i2c_master_set_slave_address(slave_addr, I2C_RECEIVE); + i2c_master_command(I2C_MASTER_CMD_BURST_RECEIVE_START); + while(i2c_master_busy()); + if(i2c_master_error() == I2C_MASTER_ERR_NONE) { + data[0] = i2c_master_data_get(); + /* If we got 2 or more bytes pending to be received, keep going*/ + for(recv = 1; recv <= (len - 2); recv++) { + i2c_master_command(I2C_MASTER_CMD_BURST_RECEIVE_CONT); + while(i2c_master_busy()); + data[recv] = i2c_master_data_get(); + } + /* This should be the last byte, stop receiving */ + i2c_master_command(I2C_MASTER_CMD_BURST_RECEIVE_FINISH); + while(i2c_master_busy()); + data[len - 1] = i2c_master_data_get(); + } + return i2c_master_error(); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc2538/dev/i2c.h b/cpu/cc2538/dev/i2c.h new file mode 100644 index 000000000..6ec606167 --- /dev/null +++ b/cpu/cc2538/dev/i2c.h @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2015, Mehdi Migault + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this 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-i2c cc2538 I2C Control + * + * cc2538 I2C Control Module + * @{ + * + * \file + * Header file with declarations for the I2C Control module + * + * \author + * Mehdi Migault + */ +#ifndef I2C_H_ +#define I2C_H_ + +#include "reg.h" +#include "sys-ctrl.h" +#include "gpio.h" +#include "ioc.h" +#include /* For debug */ +#include "clock.h" /* For temporisation */ +/*---------------------------------------------------------------------------*/ +/** \name I2C Master commands + * @{ + */ +#define I2C_MASTER_CMD_SINGLE_SEND 0x00000007 +#define I2C_MASTER_CMD_SINGLE_RECEIVE 0x00000007 +#define I2C_MASTER_CMD_BURST_SEND_START 0x00000003 +#define I2C_MASTER_CMD_BURST_SEND_CONT 0x00000001 +#define I2C_MASTER_CMD_BURST_SEND_FINISH 0x00000005 +#define I2C_MASTER_CMD_BURST_SEND_ERROR_STOP 0x00000004 +#define I2C_MASTER_CMD_BURST_RECEIVE_START 0x0000000b +#define I2C_MASTER_CMD_BURST_RECEIVE_CONT 0x00000009 +#define I2C_MASTER_CMD_BURST_RECEIVE_FINISH 0x00000005 +#define I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP 0x00000004 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name I2C Master status flags + * @{ + */ +#define I2C_MASTER_ERR_NONE 0 +#define I2CM_STAT_BUSY 0x00000001 +#define I2CM_STAT_ERROR 0x00000002 +#define I2CM_STAT_ADRACK 0x00000004 +#define I2CM_STAT_DATACK 0x00000008 +#define I2CM_STAT_ARBLST 0x00000010 +#define I2CM_STAT_IDLE 0x00000020 +#define I2CM_STAT_BUSBSY 0x00000040 +#define I2CM_STAT_INVALID 0x00000080 +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name I2C registers + * @{ + */ +#define I2CM_CR 0x40020020 /* I2C master config */ +#define I2CM_TPR 0x4002000C /* I2C master timer period */ +#define I2CM_SA 0x40020000 /* I2C master slave address */ +#define I2CM_DR 0x40020008 /* I2C master data */ +#define I2CM_CTRL 0x40020004 /* Master control in write */ +#define I2CM_STAT I2CM_CTRL /* Master status in read */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** \name I2C Miscellaneous + * @{ + */ +#define I2C_SCL_NORMAL_BUS_SPEED 100000 /* 100KHz I2C */ +#define I2C_SCL_FAST_BUS_SPEED 400000 /* 400KHz I2C */ +#define I2C_RECEIVE 0x01 /* Master receive */ +#define I2C_SEND 0x00 /* Master send */ +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \name I2C Functions + * @{ + */ + +/** + * \brief Initialize the I2C peripheral and pins + * \param port_sda The GPIO number of the pin used fort SDA + * \param pin_sda The pin number used for SDA + * \param port_scl The GPIO number of the pin used fort SCL + * \param pin_scl The pin number used for SCL + * \param bus_speed The clock frequency used by I2C module + * + * \e bus_speed can take the following values: + * + * - I2C_SCL_NORMAL_BUS_SPEED : 100KHz + * - I2C_SCL_FAST_BUS_SPEED : 400KHz + */ +void i2c_init(uint8_t port_sda, uint8_t pin_sda, uint8_t port_scl, + uint8_t pin_scl, uint32_t bus_speed); + +/** \brief Enable master I2C module */ +void i2c_master_enable(void); + +/** \brief Disable master I2C module */ +void i2c_master_disable(void); + +/** + * \brief Initialize I2C peripheral clock with given frequency + * \param freq The desired frequency + * + * \e freq can take the following values: + * + * - I2C_SCL_NORMAL_BUS_SPEED : 100KHz + * - I2C_SCL_FAST_BUS_SPEED : 400KHz + */ +void i2c_set_frequency(uint32_t freq); + +/** + * \brief Set the address of slave and access mode for the next I2C communication + * \param slave_addr The receiver slave address on 7 bits + * \param access_mode The I2C access mode (send/receive) + * + * \e access_mode can take the following values: + * + * - I2C_RECEIVE : 1 + * - I2C_SEND : 0 + */ +void i2c_master_set_slave_address(uint8_t slave_addr, uint8_t access_mode); + +/** + * \brief Prepare data to be transmitted + * \param data The byte of data to be transmitted from the I2C master + */ +void i2c_master_data_put(uint8_t data); + +/** + * \brief Return received data from I2C + * \return The byte received by I2C after à receive command + */ +uint8_t i2c_master_data_get(void); + +/** + * \brief Control the state of the master module for send and receive operations + * \param cmd The operation to perform + * + * \e cmd can take the following values: + * + * - I2C_MASTER_CMD_SINGLE_SEND + * - I2C_MASTER_CMD_SINGLE_RECEIVE + * - I2C_MASTER_CMD_BURST_SEND_START + * - I2C_MASTER_CMD_BURST_SEND_CONT + * - I2C_MASTER_CMD_BURST_SEND_FINISH + * - I2C_MASTER_CMD_BURST_SEND_ERROR_STOP + * - I2C_MASTER_CMD_BURST_RECEIVE_START + * - I2C_MASTER_CMD_BURST_RECEIVE_CONT + * - I2C_MASTER_CMD_BURST_RECEIVE_FINISH + * - I2C_MASTER_CMD_BURST_RECEIVE_ERROR_STOP + */ +void i2c_master_command(uint8_t cmd); + +/** + * \brief Return the busy state of I2C module + * \retval 0 The I2C module is not busy + * \retval 1 The I2C module is busy + */ +uint8_t i2c_master_busy(void); + +/** + * \brief Return the status register if error occurred during last communication + * \retval I2C_MASTER_ERR_NONE Return 0 if no error occurred + * + * If an error occurred, return the status register of the I2C module. + * Use the result with the I2CM_STAT_* flags to custom your processing + */ +uint8_t i2c_master_error(void); +/** + * \brief Perform all operations to send a byte to a slave + * \param slave_addr The adress of the slave to which data are sent + * \param data The data to send to the slave + * \return Return the value of i2c_master_error() after the I2C operation + */ +uint8_t i2c_single_send(uint8_t slave_addr, uint8_t data); + +/** + * \brief Perform all operations to receive a byte from a slave + * \param slave_addr The address of the slave from which data are received + * \param data A pointer to store the received data + * \return Return the value of i2c_master_error() after the I2C operation + */ +uint8_t i2c_single_receive(uint8_t slave_addr, uint8_t *data); +/** + * \brief Perform all operations to send multiple bytes to a slave + * \param slave_addr The address of the slave to which data are sent + * \param data A pointer to the data to send to the slave + * \param len Number of bytes to send + * \return Return the value of i2c_master_error() after the I2C operation + */ +uint8_t i2c_burst_send(uint8_t slave_addr, uint8_t *data, uint8_t len); + +/** + * \brief Perform all operations to receive multiple bytes from a slave + * \param slave_addr The address of the slave from which data are received + * \param data A pointer to store the received data + * \param len Number of bytes to receive + * \return Return the value of i2c_master_error() after the I2C operation + */ +uint8_t i2c_burst_receive(uint8_t slave_addr, uint8_t *data, uint8_t len); +/** @} */ + +#endif /* I2C_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc2538/dev/ioc.h b/cpu/cc2538/dev/ioc.h index 34fcce809..7fad9d275 100644 --- a/cpu/cc2538/dev/ioc.h +++ b/cpu/cc2538/dev/ioc.h @@ -34,7 +34,7 @@ * * \defgroup cc2538-ioc cc2538 I/O Control * - * cc2538 I/O Control Module + * Driver for the cc2538 I/O Control Module * @{ * * \file diff --git a/cpu/cc2538/dev/nvic.c b/cpu/cc2538/dev/nvic.c index 8e2e991ab..86e97c093 100644 --- a/cpu/cc2538/dev/nvic.c +++ b/cpu/cc2538/dev/nvic.c @@ -57,7 +57,7 @@ nvic_init() interrupt_unpend = (uint32_t *)NVIC_UNPEND0; /* Provide our interrupt table to the NVIC */ - REG(SCB_VTABLE) = (NVIC_CONF_VTABLE_BASE | NVIC_CONF_VTABLE_OFFSET); + REG(SCB_VTABLE) = (NVIC_CONF_VTABLE_BASE + NVIC_CONF_VTABLE_OFFSET); } /*---------------------------------------------------------------------------*/ void diff --git a/cpu/cc2538/dev/scb.h b/cpu/cc2538/dev/scb.h index 53b1535e4..e91951ecb 100644 --- a/cpu/cc2538/dev/scb.h +++ b/cpu/cc2538/dev/scb.h @@ -32,7 +32,9 @@ * \addtogroup cc2538 * @{ * - * \defgroup cc2538-scb cc2538 System Control Block + * \defgroup cc2538-scb cc2538 System Control Block (SCB) + * + * Offsets and bit definitions for SCB registers * @{ * * \file diff --git a/cpu/cc2538/dev/spi.c b/cpu/cc2538/dev/spi.c index 586c738bc..bff1783b5 100644 --- a/cpu/cc2538/dev/spi.c +++ b/cpu/cc2538/dev/spi.c @@ -31,7 +31,7 @@ * @{ * * \file - * Implementation of the cc2538 SPI peripheral + * Implementation of the cc2538 SPI peripheral driver */ #include "contiki.h" #include "reg.h" @@ -52,7 +52,7 @@ /** * \brief Initialize the SPI bus. * - * This SPI init() function uses the following #defines to set the pins: + * 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 @@ -126,7 +126,9 @@ spi_disable(void) 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) +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; diff --git a/cpu/cc2538/dev/sys-ctrl.h b/cpu/cc2538/dev/sys-ctrl.h index f63fd5a50..3c9885a89 100644 --- a/cpu/cc2538/dev/sys-ctrl.h +++ b/cpu/cc2538/dev/sys-ctrl.h @@ -32,7 +32,7 @@ * \addtogroup cc2538 * @{ * - * \defgroup cc2538-sys-ctrl cc2538 System Control + * \defgroup cc2538-sys-ctrl cc2538 System Control (SysCtrl) * * Driver for the cc2538 System Control Module * @{ diff --git a/cpu/cc2538/dev/uart.c b/cpu/cc2538/dev/uart.c index bf5e16b8c..ea6a6a57a 100644 --- a/cpu/cc2538/dev/uart.c +++ b/cpu/cc2538/dev/uart.c @@ -206,22 +206,22 @@ reset(uint32_t uart_base) uint32_t lchr; /* Make sure the UART is disabled before trying to configure it */ - REG(uart_base | UART_CTL) = UART_CTL_VALUE; + REG(uart_base + UART_CTL) = UART_CTL_VALUE; /* Clear error status */ - REG(uart_base | UART_ECR) = 0xFF; + REG(uart_base + UART_ECR) = 0xFF; /* Store LCHR configuration */ - lchr = REG(uart_base | UART_LCRH); + lchr = REG(uart_base + UART_LCRH); /* Flush FIFOs by clearing LCHR.FEN */ - REG(uart_base | UART_LCRH) = 0; + REG(uart_base + UART_LCRH) = 0; /* Restore LCHR configuration */ - REG(uart_base | UART_LCRH) = lchr; + REG(uart_base + UART_LCRH) = lchr; /* UART Enable */ - REG(uart_base | UART_CTL) |= UART_CTL_UARTEN; + REG(uart_base + UART_CTL) |= UART_CTL_UARTEN; } /*---------------------------------------------------------------------------*/ static bool @@ -232,7 +232,7 @@ permit_pm1(void) for(regs = &uart_regs[0]; regs < &uart_regs[UART_INSTANCE_COUNT]; regs++) { /* Note: UART_FR.TXFE reads 0 if the UART clock is gated. */ if((REG(SYS_CTRL_RCGCUART) & regs->sys_ctrl_rcgcuart_uart) != 0 && - (REG(regs->base | UART_FR) & UART_FR_TXFE) == 0) { + (REG(regs->base + UART_FR) & UART_FR_TXFE) == 0) { return false; } } @@ -261,7 +261,7 @@ uart_init(uint8_t uart) REG(SYS_CTRL_DCGCUART) |= regs->sys_ctrl_dcgcuart_uart; /* Run on SYS_DIV */ - REG(regs->base | UART_CC) = 0; + REG(regs->base + UART_CC) = 0; /* * Select the UARTx RX pin by writing to the IOC_UARTRXD_UARTn register @@ -292,21 +292,21 @@ uart_init(uint8_t uart) * Acknowledge RX and RX Timeout * Acknowledge Framing, Overrun and Break Errors */ - REG(regs->base | UART_IM) = UART_IM_RXIM | UART_IM_RTIM; - REG(regs->base | UART_IM) |= UART_IM_OEIM | UART_IM_BEIM | UART_IM_FEIM; + REG(regs->base + UART_IM) = UART_IM_RXIM | UART_IM_RTIM; + REG(regs->base + UART_IM) |= UART_IM_OEIM | UART_IM_BEIM | UART_IM_FEIM; - REG(regs->base | UART_IFLS) = + REG(regs->base + UART_IFLS) = UART_IFLS_RXIFLSEL_1_8 | UART_IFLS_TXIFLSEL_1_2; /* Make sure the UART is disabled before trying to configure it */ - REG(regs->base | UART_CTL) = UART_CTL_VALUE; + REG(regs->base + UART_CTL) = UART_CTL_VALUE; /* Baud Rate Generation */ - REG(regs->base | UART_IBRD) = regs->ibrd; - REG(regs->base | UART_FBRD) = regs->fbrd; + REG(regs->base + UART_IBRD) = regs->ibrd; + REG(regs->base + UART_FBRD) = regs->fbrd; /* UART Control: 8N1 with FIFOs */ - REG(regs->base | UART_LCRH) = UART_LCRH_WLEN_8 | UART_LCRH_FEN; + REG(regs->base + UART_LCRH) = UART_LCRH_WLEN_8 | UART_LCRH_FEN; /* * Enable hardware flow control (RTS/CTS) if requested. @@ -316,18 +316,18 @@ uart_init(uint8_t uart) REG(IOC_UARTCTS_UART1) = ioc_input_sel(regs->cts.port, regs->cts.pin); GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->cts.port), GPIO_PIN_MASK(regs->cts.pin)); ioc_set_over(regs->cts.port, regs->cts.pin, IOC_OVERRIDE_DIS); - REG(UART_1_BASE | UART_CTL) |= UART_CTL_CTSEN; + REG(UART_1_BASE + UART_CTL) |= UART_CTL_CTSEN; } if(regs->rts.port >= 0) { ioc_set_sel(regs->rts.port, regs->rts.pin, IOC_PXX_SEL_UART1_RTS); GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->rts.port), GPIO_PIN_MASK(regs->rts.pin)); ioc_set_over(regs->rts.port, regs->rts.pin, IOC_OVERRIDE_OE); - REG(UART_1_BASE | UART_CTL) |= UART_CTL_RTSEN; + REG(UART_1_BASE + UART_CTL) |= UART_CTL_RTSEN; } /* UART Enable */ - REG(regs->base | UART_CTL) |= UART_CTL_UARTEN; + REG(regs->base + UART_CTL) |= UART_CTL_UARTEN; /* Enable UART0 Interrupts */ nvic_interrupt_enable(regs->nvic_int); @@ -354,9 +354,9 @@ uart_write_byte(uint8_t uart, uint8_t b) uart_base = uart_regs[uart].base; /* Block if the TX FIFO is full */ - while(REG(uart_base | UART_FR) & UART_FR_TXFF); + while(REG(uart_base + UART_FR) & UART_FR_TXFF); - REG(uart_base | UART_DR) = b; + REG(uart_base + UART_DR) = b; } /*---------------------------------------------------------------------------*/ void @@ -371,18 +371,18 @@ uart_isr(uint8_t uart) /* Store the current MIS and clear all flags early, except the RTM flag. * This will clear itself when we read out the entire FIFO contents */ - mis = REG(uart_base | UART_MIS) & 0x0000FFFF; + mis = REG(uart_base + UART_MIS) & 0x0000FFFF; - REG(uart_base | UART_ICR) = 0x0000FFBF; + REG(uart_base + UART_ICR) = 0x0000FFBF; if(mis & (UART_MIS_RXMIS | UART_MIS_RTMIS)) { - while(!(REG(uart_base | UART_FR) & UART_FR_RXFE)) { + while(!(REG(uart_base + UART_FR) & UART_FR_RXFE)) { if(input_handler[uart] != NULL) { - input_handler[uart]((unsigned char)(REG(uart_base | UART_DR) & 0xFF)); + input_handler[uart]((unsigned char)(REG(uart_base + UART_DR) & 0xFF)); } else { /* To prevent an Overrun Error, we need to flush the FIFO even if we * don't have an input_handler. Use mis as a data trash can */ - mis = REG(uart_base | UART_DR); + mis = REG(uart_base + UART_DR); } } } else if(mis & (UART_MIS_OEMIS | UART_MIS_BEMIS | UART_MIS_FEMIS)) { diff --git a/cpu/cc2538/dev/udma.h b/cpu/cc2538/dev/udma.h index a6ddfc199..79cd58c20 100644 --- a/cpu/cc2538/dev/udma.h +++ b/cpu/cc2538/dev/udma.h @@ -560,12 +560,13 @@ void udma_init(void); /** * \brief Sets the channels source address * \param channel The channel as a value in [0 , UDMA_CONF_MAX_CHANNEL] - * \param + * \param src_end The source's end address */ void udma_set_channel_src(uint8_t channel, uint32_t src_end); /** - * \brief + * \brief Sets the channel's destination address + * \param dst_end The destination's end address * \param channel The channel as a value in [0 , UDMA_CONF_MAX_CHANNEL] */ void udma_set_channel_dst(uint8_t channel, uint32_t dst_end); diff --git a/cpu/cc2538/spi-arch.h b/cpu/cc2538/spi-arch.h index 53d7fe78d..46d8d3bf4 100644 --- a/cpu/cc2538/spi-arch.h +++ b/cpu/cc2538/spi-arch.h @@ -27,16 +27,13 @@ * SUCH DAMAGE. */ /** - * \addtogroup cc2538 + * \addtogroup cc2538-spi * @{ * - * Implementation of the low-level SPI primitives such as waiting for the TX - * FIFO to be ready, inserting into the TX FIFO, etc. - * @{ - */ -/** * \file - * Header file for the cc2538 SPI commands + * 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. */ #ifndef SPI_ARCH_H_ #define SPI_ARCH_H_ @@ -121,6 +118,5 @@ void spi_set_mode(uint32_t frame_format, uint32_t clock_polarity, #endif /* SPI_ARCH_H_ */ /** - * @} * @} */ diff --git a/cpu/cc253x/dev/clock.c b/cpu/cc253x/dev/clock.c index ff1c4cf4a..e78635361 100644 --- a/cpu/cc253x/dev/clock.c +++ b/cpu/cc253x/dev/clock.c @@ -70,7 +70,7 @@ clock_delay_usec(uint16_t len) ENABLE_INTERRUPTS(); } /*---------------------------------------------------------------------------*/ -/** +/* * Wait for a multiple of ~8 ms (a tick) */ void diff --git a/cpu/cc253x/dev/uart0.c b/cpu/cc253x/dev/uart0.c index a6a358a18..f5dc35640 100644 --- a/cpu/cc253x/dev/uart0.c +++ b/cpu/cc253x/dev/uart0.c @@ -39,7 +39,7 @@ uart0_init() #else PERCFG &= ~PERCFG_U0CFG; /* alternative port 1 = P0.5-2 */ #ifdef UART0_RTSCTS - P0SEL |= 0x20 | 0x10; /* peripheral select for TX and RX */ + P0SEL |= 0x3C; /* peripheral select for RTS and CTS, TX, RX */ #else P0SEL |= 0x0C; /* peripheral select for TX and RX */ P0 &= ~0x20; /* RTS down */ diff --git a/cpu/cc26xx/Makefile.cc26xx b/cpu/cc26xx/Makefile.cc26xx new file mode 100644 index 000000000..a339bd9f1 --- /dev/null +++ b/cpu/cc26xx/Makefile.cc26xx @@ -0,0 +1,132 @@ +CC = arm-none-eabi-gcc +CPP = arm-none-eabi-cpp +LD = arm-none-eabi-gcc +AR = arm-none-eabi-ar +OBJCOPY = arm-none-eabi-objcopy +OBJDUMP = arm-none-eabi-objdump +NM = arm-none-eabi-nm +SIZE = arm-none-eabi-size + +### 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 + +### cc26xxware sources will be added to the MODULES list +TI_CC26XXWARE_SRC = $(TI_CC26XXWARE)/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_SRCS = ccfg.c startup_gcc.c + +### MODULES will add some of these to the include pach, 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 +MODULES += $(TI_CC26XXWARE_SRC) + +LDSCRIPT = $(CONTIKI_CPU)/cc26xx.ld + +CFLAGS += -mcpu=cortex-m3 -mthumb -mlittle-endian +CFLAGS += -ffunction-sections -fdata-sections +CFLAGS += -fshort-enums -fomit-frame-pointer -fno-strict-aliasing +CFLAGS += -Wall -std=c99 + +### Workaround for driverlib's cpu.h which tests if defined(gcc) +### Delete if it gets fixed or if we stop using the driverlib +CFLAGS += -Dgcc=__GNUC__ + +LDFLAGS += -mcpu=cortex-m3 -mthumb -mlittle-endian -nostartfiles +LDFLAGS += -T $(LDSCRIPT) +LDFLAGS += -Wl,--gc-sections,--sort-section=alignment +LDFLAGS += -Wl,-Map=$(@:.elf=-$(TARGET).map),--cref,--no-warn-mismatch +OBJCOPY_FLAGS += -O binary --gap-fill 0xff +OBJDUMP_FLAGS += --disassemble --source --disassembler-options=force-thumb + +### Are we building with code size optimisations? +ifeq ($(SMALL),1) + CFLAGS += -Os +else + CFLAGS += -O2 +endif + +### If the user-specified a Node ID, pass a define +ifdef NODEID + CFLAGS += -DIEEE_ADDR_NODE_ID=$(NODEID) +endif + +### CPU-dependent cleanup files +CLEAN += symbols.c symbols.h *.d *.elf *.hex + +### CPU-dependent directories +CONTIKI_CPU_DIRS = . dev dev/rfc-api $(TI_CC26XXWARE_STARTUP) + +### Use the existing debug I/O in cpu/arm/common +CONTIKI_CPU_DIRS += ../arm/common/dbg-io + +### CPU-dependent source files +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 + +DEBUG_IO_SOURCEFILES += dbg-printf.c dbg-snprintf.c dbg-sprintf.c strformat.c + +CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES) $(DEBUG_IO_SOURCEFILES) + +TARGET_START_SOURCEFILES += fault-handlers.c $(TI_CC26XXWARE_STARTUP_SRCS) +TARGET_STARTFILES = $(addprefix $(OBJECTDIR)/,$(call oname, $(TARGET_START_SOURCEFILES))) + +### Don't treat the .elf as intermediate +.PRECIOUS: %.elf %.hex %.bin + +### Always re-build ieee-addr.o in case the command line passes a new NODEID +FORCE: + +$(OBJECTDIR)/ieee-addr.o: ieee-addr.c FORCE | $(OBJECTDIR) + $(TRACE_CC) + $(Q)$(CC) $(CFLAGS) -c $< -o $@ + +### Compilation rules +CUSTOM_RULE_LINK=1 + +%.elf: $(TARGET_STARTFILES) %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a $(LDSCRIPT) + $(TRACE_LD) + $(Q)$(LD) $(LDFLAGS) ${filter-out $(LDSCRIPT) %.a,$^} ${filter %.a,$^} $(TARGET_LIBFILES) -lm -o $@ + +%.hex: %.elf + $(OBJCOPY) -O ihex $< $@ + +%.bin: %.elf + $(OBJCOPY) $(OBJCOPY_FLAGS) $< $@ + +%.lst: %.elf + $(OBJDUMP) $(OBJDUMP_FLAGS) $< > $@ + +### We don't really need the .hex and .bin for the .$(TARGET) but let's make +### sure they get built +%.$(TARGET): %.elf %.hex %.bin + cp $< $@ + +# a target that gives a user-friendly memory profile, taking into account the RAM +# that is statically occupied by the stack as defined in the linker script +# see $(LDSCRIPT) +RAM_SIZE = 0x00003E00 +FLASH_SIZE = 0x0001E000 +STACK_SIZE = 0 +%.size: %.$(TARGET) + @$(SIZE) -A $< | egrep "data|bss" | awk '{s+=$$2} END {s=s+$(STACK_SIZE); f=$(RAM_SIZE)-s; printf "[RAM] used %6d, free %6d\n",s,f;}' + @$(SIZE) -A $< | egrep "text|isr_vector" | awk '{s+=$$2} END {f=$(FLASH_SIZE)-s; printf "[Flash] used %6d, free %6d\n",s,f;}' + diff --git a/cpu/cc26xx/cc26xx-model.h b/cpu/cc26xx/cc26xx-model.h new file mode 100644 index 000000000..44ee1cfe3 --- /dev/null +++ b/cpu/cc26xx/cc26xx-model.h @@ -0,0 +1,74 @@ +/* + * 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-models CC26xx models + * + * The CC26xx comes out in various flavours. Most notable within the context + * of this Contiki port: The CC2630 with IEEE (but no BLE) support and the + * CC2650 with IEEE and BLE support. + * + * This port supports both models and will automatically turn off the BLE code + * if the CC2630 is selected. + * + * @{ + */ +/** + * \file + * Header file with definitions relating to various CC26xx variants + */ +/*---------------------------------------------------------------------------*/ +#ifndef CC26XX_MODEL_H_ +#define CC26XX_MODEL_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +/*---------------------------------------------------------------------------*/ +#ifdef CC26XX_MODEL_CONF_CPU_VARIANT +#define CC26XX_MODEL_CPU_VARIANT CC26XX_MODEL_CONF_CPU_VARIANT +#else +#define CC26XX_MODEL_CPU_VARIANT 2650 +#endif + +#if (CC26XX_MODEL_CPU_VARIANT != 2630) && (CC26XX_MODEL_CPU_VARIANT != 2650) +#error Incorrect CC26xx variant selected. +#error Check the value of CC26XX_MODEL_CONF_CPU_VARIANT +#error Supported values: 2630 and 2650 +#endif +/*---------------------------------------------------------------------------*/ +#endif /* CC26XX_MODEL_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/cc26xx.ld b/cpu/cc26xx/cc26xx.ld new file mode 100644 index 000000000..27c39c6c5 --- /dev/null +++ b/cpu/cc26xx/cc26xx.ld @@ -0,0 +1,103 @@ +/* + * 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. + */ + +/* CC26XX linker script */ + +/* Entry Point */ +ENTRY(ResetISR) + +MEMORY +{ + /* Flash Size 128 KB minus the CCA area below (76 bytes) */ + FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x0001FFAC + + /* + * Customer Configuration Area and Bootloader Backdoor configuration + * in flash, up to 80 bytes + */ + FLASH_CCFG (RX) : ORIGIN = 0x0001FFAC, LENGTH = 84 + + /* RAM Size 20KB (PG2.1) */ + SRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 0x00005000 +} + +/*. Highest address of the stack. Used in startup file .*/ +_estack = ORIGIN(SRAM) + LENGTH(SRAM); /* End of SRAM */ + +/*. Generate a link error if heap and stack don’t fit into RAM .*/ +_Min_Heap_Size = 0; +_Min_Stack_Size = 0x100; + +SECTIONS +{ + .text : + { + _text = .; + KEEP(*(.vectors)) + *(.text*) + *(.rodata*) + _etext = .; + } > FLASH = 0 + + .data : + { + _data = .; + *(vtable) + *(.data*) + _edata = .; + } > SRAM AT > FLASH + + .ARM.exidx : + { + *(.ARM.exidx*) + } > FLASH + + .bss : + { + _bss = .; + *(.bss*) + *(COMMON) + _ebss = .; + } > SRAM + + .ccfg : + { + KEEP(*(.ccfg)) + } > FLASH_CCFG + + /* User_heap_stack section, used to check that there is enough RAM left */ + ._user_heap_stack : + { + . = ALIGN(4); + . = . + _Min_Heap_Size; + . = . + _Min_Stack_Size; + . = ALIGN(4); + } >SRAM +} diff --git a/cpu/cc26xx/clock.c b/cpu/cc26xx/clock.c new file mode 100644 index 000000000..c96158b48 --- /dev/null +++ b/cpu/cc26xx/clock.c @@ -0,0 +1,189 @@ +/* + * 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 platform + * @{ + * + * \defgroup cc26xx-platforms TI CC26xx-powered Platforms + * @{ + * + * \defgroup cc26xx The TI CC26xx CPU + * @{ + * + * \addtogroup cc26xx-clocks + * @{ + * + * \defgroup cc26xx-software-clock CC26xx Software Clock + * + * Implementation of the clock module for the cc26xx. + * + * The software clock uses the facilities provided by the AON RTC driver + * @{ + * + * \file + * Software clock implementation for the TI CC26xx + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include "ti-lib.h" +/*---------------------------------------------------------------------------*/ +static volatile clock_time_t count; +static volatile clock_time_t second_countdown; +static volatile unsigned long secs; +/*---------------------------------------------------------------------------*/ +static void +power_domain_on(void) +{ + ti_lib_prcm_power_domain_on(PRCM_DOMAIN_PERIPH); + while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) != + PRCM_DOMAIN_POWER_ON); +} +/*---------------------------------------------------------------------------*/ +void +clock_init(void) +{ + count = 0; + secs = 0; + second_countdown = CLOCK_SECOND; + + /* + * 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 + */ + ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_TIMER0); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + /* Disable both GPT0 timers */ + HWREG(GPT0_BASE + GPT_O_CTL) &= ~(GPT_CTL_TAEN | GPT_CTL_TBEN); + + /* + * We assume that the clock is running at 48MHz, we use GPT0 Timer A, + * one-shot, countdown, prescaled by 48 gives us 1 tick per usec + */ + ti_lib_timer_configure(GPT0_BASE, + TIMER_CFG_SPLIT_PAIR | TIMER_CFG_B_ONE_SHOT); + + /* Global config: split pair (2 x 16-bit wide) */ + HWREG(GPT0_BASE + GPT_O_CFG) = TIMER_CFG_SPLIT_PAIR >> 24; + + /* + * Pre-scale value 47 pre-scales by 48 + * + * ToDo: The theoretical value here should be 47 (to provide x48 prescale) + * However, 49 seems to give results much closer to the desired delay + */ + ti_lib_timer_prescale_set(GPT0_BASE, TIMER_B, 49); + + /* GPT0 / Timer B: One shot, PWM interrupt enable */ + HWREG(GPT0_BASE + GPT_O_TBMR) = + ((TIMER_CFG_B_ONE_SHOT >> 8) & 0xFF) | GPT_TBMR_TBPWMIE; +} +/*---------------------------------------------------------------------------*/ +CCIF clock_time_t +clock_time(void) +{ + return count; +} +/*---------------------------------------------------------------------------*/ +void +clock_update(void) +{ + count++; + if(etimer_pending()) { + etimer_request_poll(); + } + + if(--second_countdown == 0) { + secs++; + second_countdown = CLOCK_SECOND; + } +} +/*---------------------------------------------------------------------------*/ +void +clock_set_seconds(unsigned long sec) +{ + secs = sec; +} +/*---------------------------------------------------------------------------*/ +CCIF unsigned long +clock_seconds(void) +{ + return secs; +} +/*---------------------------------------------------------------------------*/ +void +clock_wait(clock_time_t i) +{ + clock_time_t start; + + start = clock_time(); + while(clock_time() - start < (clock_time_t)i); +} +/*---------------------------------------------------------------------------*/ +void +clock_delay_usec(uint16_t len) +{ + if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH) != + PRCM_DOMAIN_POWER_ON) { + power_domain_on(); + } + + ti_lib_timer_load_set(GPT0_BASE, TIMER_B, len); + ti_lib_timer_enable(GPT0_BASE, TIMER_B); + + /* + * Wait for TBEN to clear. CC26xxware does not provide us with a convenient + * function, hence the direct register access here + */ + while(HWREG(GPT0_BASE + GPT_O_CTL) & GPT_CTL_TBEN); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Obsolete delay function but we implement it here since some code + * still uses it + */ +void +clock_delay(unsigned int i) +{ + clock_delay_usec(i); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + * @} + * @} + */ diff --git a/cpu/cc26xx/dbg.h b/cpu/cc26xx/dbg.h new file mode 100644 index 000000000..a5bff7513 --- /dev/null +++ b/cpu/cc26xx/dbg.h @@ -0,0 +1,65 @@ +/* + * 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 cc26xx + * @{ + * + * \defgroup cc26xx-char-io CC26xx Character I/O + * + * CC26xx CPU-specific functions for debugging and SLIP I/O + * @{ + * + * \file + * Header file for the CC26xx Debug I/O module + */ +#ifndef DBG_H_ +#define DBG_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +/*---------------------------------------------------------------------------*/ +/** + * \brief Print a stream of bytes + * \param seq A pointer to the stream + * \param len The number of bytes to print + * \return The number of printed bytes + * + * This function is an arch-specific implementation required by the dbg-io + * API in cpu/arm/common/dbg-io. It prints a stream of bytes over the + * peripheral used by the platform. + */ +unsigned int dbg_send_bytes(const unsigned char *seq, unsigned int len); +/*---------------------------------------------------------------------------*/ +#endif /* DBG_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/debug-uart.h b/cpu/cc26xx/debug-uart.h new file mode 100644 index 000000000..c2d9b0ffb --- /dev/null +++ b/cpu/cc26xx/debug-uart.h @@ -0,0 +1,49 @@ +/* + * 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 cc26xx-char-io + * @{ + * + * \file + * This file is here because DBG I/O expects it to be. It just includes + * our own dbg.h which has a non-misleading name and which also adheres + * to Contiki's naming convention + */ +/*---------------------------------------------------------------------------*/ +#ifndef DEBUG_UART_H_ +#define DEBUG_UART_H_ +/*---------------------------------------------------------------------------*/ +#include "dbg.h" +/*---------------------------------------------------------------------------*/ +#endif /* DEBUG_UART_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc26xx/dev/batmon-sensor.c b/cpu/cc26xx/dev/batmon-sensor.c new file mode 100644 index 000000000..8131307a0 --- /dev/null +++ b/cpu/cc26xx/dev/batmon-sensor.c @@ -0,0 +1,143 @@ +/* + * 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 cc26xx-batmon + * @{ + * + * \file + * Driver for the CC26xx AON battery monitor + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "lib/sensors.h" +#include "batmon-sensor.h" + +#include "ti-lib.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +#define SENSOR_STATUS_DISABLED 0 +#define SENSOR_STATUS_ENABLED 1 + +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 + */ +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(); + } else if(type == BATMON_SENSOR_TYPE_VOLT) { + tmp_value = ti_lib_aon_batmon_battery_voltage_get(); + } else { + PRINTF("Invalid type\n"); + return 0; + } + + return (int)tmp_value; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Configuration function for the battery monitor sensor. + * + * \param type Activate, enable or disable the sensor. See below + * \param enable If + * + * 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: + ti_lib_aon_batmon_enable(); + ti_lib_aon_batmon_measurement_cycle_set(AON_BATMON_CYCLE_32); + enabled = SENSOR_STATUS_ENABLED; + break; + case SENSORS_ACTIVE: + if(enable) { + ti_lib_aon_batmon_enable(); + enabled = SENSOR_STATUS_ENABLED; + } else { + ti_lib_aon_batmon_disable(); + enabled = SENSOR_STATUS_DISABLED; + } + break; + default: + break; + } + return enabled; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the status of the sensor + * \param type SENSORS_ACTIVE or SENSORS_READY + * \return 1 if the sensor is enabled + */ +static int +status(int type) +{ + switch(type) { + case SENSORS_ACTIVE: + case SENSORS_READY: + return enabled; + break; + default: + break; + } + return SENSOR_STATUS_DISABLED; +} +/*---------------------------------------------------------------------------*/ +SENSORS_SENSOR(batmon_sensor, "Battery Monitor", value, configure, status); +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc26xx/dev/batmon-sensor.h b/cpu/cc26xx/dev/batmon-sensor.h new file mode 100644 index 000000000..12b0c6bbd --- /dev/null +++ b/cpu/cc26xx/dev/batmon-sensor.h @@ -0,0 +1,57 @@ +/* + * 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 cc26xx + * @{ + * + * \defgroup cc26xx-batmon CC26xx BatMon sensor driver + * + * Driver for the on-chip battery voltage and chip temperature sensor. + * @{ + * + * \file + * Header file for the CC26xx battery monitor + */ +/*---------------------------------------------------------------------------*/ +#ifndef BATMON_SENSOR_H_ +#define BATMON_SENSOR_H_ +/*---------------------------------------------------------------------------*/ +#define BATMON_SENSOR_TYPE_TEMP 1 +#define BATMON_SENSOR_TYPE_VOLT 2 +/*---------------------------------------------------------------------------*/ +extern const struct sensors_sensor batmon_sensor; +/*---------------------------------------------------------------------------*/ +#endif /* BATMON_SENSOR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/dev/cc26xx-rf.c b/cpu/cc26xx/dev/cc26xx-rf.c new file mode 100644 index 000000000..2f874ceef --- /dev/null +++ b/cpu/cc26xx/dev/cc26xx-rf.c @@ -0,0 +1,2180 @@ +/* + * 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 cc26xx-rf + * @{ + * + * \file + * Implementation of the CC26xx RF driver + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "dev/radio.h" +#include "dev/cc26xx-rf.h" +#include "net/packetbuf.h" +#include "net/rime/rimestats.h" +#include "net/linkaddr.h" +#include "net/netstack.h" +#include "sys/energest.h" +#include "sys/clock.h" +#include "sys/rtimer.h" +#include "lpm.h" +#include "ti-lib.h" +/*---------------------------------------------------------------------------*/ +/* RF core and RF HAL API */ +#include "hw_rfc_dbell.h" +#include "hw_rfc_pwr.h" +/*---------------------------------------------------------------------------*/ +/* RF Core Mailbox API */ +#include "mailbox.h" +#include "common_cmd.h" +#include "common_cmd_field.h" +#include "ble_cmd.h" +#include "ble_cmd_field.h" +#include "ieee_cmd.h" +#include "ieee_cmd_field.h" +#include "data_entry.h" +#include "ble_mailbox.h" +#include "ieee_mailbox.h" +/*---------------------------------------------------------------------------*/ +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#define BUSYWAIT_UNTIL(cond, max_time) \ + do { \ + rtimer_clock_t t0; \ + t0 = RTIMER_NOW(); \ + while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \ + } while(0) +/*---------------------------------------------------------------------------*/ +#ifndef MIN +#define MIN(n, m) (((n) < (m)) ? (n) : (m)) +#endif +/*---------------------------------------------------------------------------*/ +#ifdef __GNUC__ +#define CC_ALIGN_ATTR(n) __attribute__ ((aligned(n))) +#else +#define CC_ALIGN_ATTR(n) +#endif +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +/* Data entry status field constants */ +#define DATA_ENTRY_STATUS_PENDING 0x00 /* Not in use by the Radio CPU */ +#define DATA_ENTRY_STATUS_ACTIVE 0x01 /* Open for r/w by the radio CPU */ +#define DATA_ENTRY_STATUS_BUSY 0x02 /* Ongoing r/w */ +#define DATA_ENTRY_STATUS_FINISHED 0x03 /* Free to use and to free */ +#define DATA_ENTRY_STATUS_UNFINISHED 0x04 /* Partial RX entry */ +/*---------------------------------------------------------------------------*/ +/* RF stats data structure */ +static uint8_t rf_stats[16] = { 0 }; +/*---------------------------------------------------------------------------*/ +/* RF Command status constants - Correspond to values in the CMDSTA register */ +#define RF_CMD_STATUS_PENDING 0x00 +#define RF_CMD_STATUS_DONE 0x01 +#define RF_CMD_STATUS_ILLEGAL_PTR 0x81 +#define RF_CMD_STATUS_UNKNOWN_CMD 0x82 +#define RF_CMD_STATUS_UNKNOWN_DIR_CMD 0x83 +#define RF_CMD_STATUS_CONTEXT_ERR 0x85 +#define RF_CMD_STATUS_SCHEDULING_ERR 0x86 +#define RF_CMD_STATUS_PAR_ERR 0x87 +#define RF_CMD_STATUS_QUEUE_ERR 0x88 +#define RF_CMD_STATUS_QUEUE_BUSY 0x89 + +/* Status values starting with 0x8 correspond to errors */ +#define RF_CMD_STATUS_ERR_MASK 0x80 + +/* Return values for rf_send_cmd_ok */ +#define RF_CMD_ERROR 0 +#define RF_CMD_OK 1 + +/* The size of the RF commands buffer */ +#define RF_CMD_BUFFER_SIZE 128 +/*---------------------------------------------------------------------------*/ +/* RF Radio Op status constants. Field 'status' in Radio Op command struct */ +#define RF_RADIO_OP_STATUS_IDLE 0x0000 +#define RF_RADIO_OP_STATUS_PENDING 0x0001 +#define RF_RADIO_OP_STATUS_ACTIVE 0x0002 +#define RF_RADIO_OP_STATUS_SKIPPED 0x0003 +#define RF_RADIO_OP_STATUS_DONE_OK 0x0400 +#define RF_RADIO_OP_STATUS_DONE_COUNTDOWN 0x0401 +#define RF_RADIO_OP_STATUS_DONE_RXERR 0x0402 +#define RF_RADIO_OP_STATUS_DONE_TIMEOUT 0x0403 +#define RF_RADIO_OP_STATUS_DONE_STOPPED 0x0404 +#define RF_RADIO_OP_STATUS_DONE_ABORT 0x0405 +#define RF_RADIO_OP_STATUS_ERROR_PAST_START 0x0800 +#define RF_RADIO_OP_STATUS_ERROR_START_TRIG 0x0801 +#define RF_RADIO_OP_STATUS_ERROR_CONDITION 0x0802 +#define RF_RADIO_OP_STATUS_ERROR_PAR 0x0803 +#define RF_RADIO_OP_STATUS_ERROR_POINTER 0x0804 +#define RF_RADIO_OP_STATUS_ERROR_CMDID 0x0805 +#define RF_RADIO_OP_STATUS_ERROR_NO_SETUP 0x0807 +#define RF_RADIO_OP_STATUS_ERROR_NO_FS 0x0808 +#define RF_RADIO_OP_STATUS_ERROR_SYNTH_PROG 0x0809 + +/* Additional Op status values for IEEE mode */ +#define RF_RADIO_OP_STATUS_IEEE_SUSPENDED 0x2001 +#define RF_RADIO_OP_STATUS_IEEE_DONE_OK 0x2400 +#define RF_RADIO_OP_STATUS_IEEE_DONE_BUSY 0x2401 +#define RF_RADIO_OP_STATUS_IEEE_DONE_STOPPED 0x2402 +#define RF_RADIO_OP_STATUS_IEEE_DONE_ACK 0x2403 +#define RF_RADIO_OP_STATUS_IEEE_DONE_ACKPEND 0x2404 +#define RF_RADIO_OP_STATUS_IEEE_DONE_TIMEOUT 0x2405 +#define RF_RADIO_OP_STATUS_IEEE_DONE_BGEND 0x2406 +#define RF_RADIO_OP_STATUS_IEEE_DONE_ABORT 0x2407 +#define RF_RADIO_OP_STATUS_ERROR_WRONG_BG 0x0806 +#define RF_RADIO_OP_STATUS_IEEE_ERROR_PAR 0x2800 +#define RF_RADIO_OP_STATUS_IEEE_ERROR_NO_SETUP 0x2801 +#define RF_RADIO_OP_STATUS_IEEE_ERROR_NO_FS 0x2802 +#define RF_RADIO_OP_STATUS_IEEE_ERROR_SYNTH_PROG 0x2803 +#define RF_RADIO_OP_STATUS_IEEE_ERROR_RXOVF 0x2804 +#define RF_RADIO_OP_STATUS_IEEE_ERROR_TXUNF 0x2805 + +/* Op status values for BLE mode */ +#define RF_RADIO_OP_STATUS_BLE_DONE_OK 0x1400 +#define RF_RADIO_OP_STATUS_BLE_DONE_RXTIMEOUT 0x1401 +#define RF_RADIO_OP_STATUS_BLE_DONE_NOSYNC 0x1402 +#define RF_RADIO_OP_STATUS_BLE_DONE_RXERR 0x1403 +#define RF_RADIO_OP_STATUS_BLE_DONE_CONNECT 0x1404 +#define RF_RADIO_OP_STATUS_BLE_DONE_MAXNACK 0x1405 +#define RF_RADIO_OP_STATUS_BLE_DONE_ENDED 0x1406 +#define RF_RADIO_OP_STATUS_BLE_DONE_ABORT 0x1407 +#define RF_RADIO_OP_STATUS_BLE_DONE_STOPPED 0x1408 +#define RF_RADIO_OP_STATUS_BLE_ERROR_PAR 0x1800 +#define RF_RADIO_OP_STATUS_BLE_ERROR_RXBUF 0x1801 +#define RF_RADIO_OP_STATUS_BLE_ERROR_NO_SETUP 0x1802 +#define RF_RADIO_OP_STATUS_BLE_ERROR_NO_FS 0x1803 +#define RF_RADIO_OP_STATUS_BLE_ERROR_SYNTH_PROG 0x1804 +#define RF_RADIO_OP_STATUS_BLE_ERROR_RXOVF 0x1805 +#define RF_RADIO_OP_STATUS_BLE_ERROR_TXUNF 0x1806 + +/* Bits 15:12 signify the protocol */ +#define RF_RADIO_OP_STATUS_PROTO_MASK 0xF000 +#define RF_RADIO_OP_STATUS_PROTO_GENERIC 0x0000 +#define RF_RADIO_OP_STATUS_PROTO_BLE 0x1000 +#define RF_RADIO_OP_STATUS_PROTO_IEEE 0x2000 +#define RF_RADIO_OP_STATUS_PROTO_PROP 0x3000 + +/* Bits 11:10 signify Running / Done OK / Done with error */ +#define RF_RADIO_OP_MASKED_STATUS 0x0C00 +#define RF_RADIO_OP_MASKED_STATUS_RUNNING 0x0000 +#define RF_RADIO_OP_MASKED_STATUS_DONE 0x0400 +#define RF_RADIO_OP_MASKED_STATUS_ERROR 0x0800 +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the current status of a running Radio Op command + * \param a A pointer with the buffer used to initiate the command + * \return The value of the Radio Op buffer's status field + * + * This macro can be used to e.g. return the status of a previously + * initiated background operation, or of an immediate command + */ +#define RF_RADIO_OP_GET_STATUS(a) GET_FIELD_V(a, radioOp, status) +/*---------------------------------------------------------------------------*/ +/* Special value returned by CMD_IEEE_CCA_REQ when an RSSI is not available */ +#define RF_CMD_CCA_REQ_RSSI_UNKNOWN -128 + +/* Used for the return value of channel_clear */ +#define RF_CCA_CLEAR 1 +#define RF_CCA_BUSY 0 + +/* Used as an error return value for get_cca_info */ +#define RF_GET_CCA_INFO_ERROR 0xFF + +/* + * Values of the individual bits of the ccaInfo field in CMD_IEEE_CCA_REQ's + * status struct + */ +#define RF_CMD_CCA_REQ_CCA_STATE_IDLE 0 /* 00 */ +#define RF_CMD_CCA_REQ_CCA_STATE_BUSY 1 /* 01 */ +#define RF_CMD_CCA_REQ_CCA_STATE_INVALID 2 /* 10 */ +/*---------------------------------------------------------------------------*/ +#define RF_MODE_BLE 0 +#define RF_MODE_IEEE 1 +/*---------------------------------------------------------------------------*/ +/* How long to wait for an ongoing ACK TX to finish before starting frame TX */ +#define TX_WAIT_TIMEOUT (RTIMER_SECOND >> 11) + +/* How long to wait for the RF to enter RX in rf_cmd_ieee_rx */ +#define ENTER_RX_WAIT_TIMEOUT (RTIMER_SECOND >> 10) +/*---------------------------------------------------------------------------*/ +/* TX Power dBm lookup table - values from SmartRF Studio */ +typedef struct output_config { + radio_value_t dbm; + uint8_t register_ib; + uint8_t register_gc; +} output_config_t; + +static const output_config_t output_power[] = { + { 5, 0x29, 0x00 }, + { 4, 0x20, 0x00 }, + { 3, 0x19, 0x00 }, + { 2, 0x25, 0x01 }, + { 1, 0x21, 0x01 }, + { 0, 0x1D, 0x01 }, + { -3, 0x19, 0x03 }, + { -6, 0x13, 0x03 }, + { -9, 0x0F, 0x03 }, +}; + +#define OUTPUT_CONFIG_COUNT (sizeof(output_power) / sizeof(output_config_t)) + +/* Max and Min Output Power in dBm */ +#define OUTPUT_POWER_MIN (output_power[OUTPUT_CONFIG_COUNT - 1].dbm) +#define OUTPUT_POWER_MAX (output_power[0].dbm) +#define OUTPUT_POWER_UNKNOWN 0xFFFF + +/* Default TX Power - position in output_power[] */ +#define CC26XX_RF_TX_POWER 0 +const output_config_t *tx_power_current = &output_power[0]; +/*---------------------------------------------------------------------------*/ +#define RF_CORE_CLOCKS_MASK (RFC_PWR_PWMCLKEN_RFC_M | RFC_PWR_PWMCLKEN_CPE_M \ + | RFC_PWR_PWMCLKEN_CPERAM_M) +/*---------------------------------------------------------------------------*/ +/* 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 + +/* + * 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 + */ +#define ENABLED_IRQS (RX_IRQ + TX_IRQ + ERROR_IRQ) + +#define cc26xx_rf_cpe0_isr RFCCPE0IntHandler +#define cc26xx_rf_cpe1_isr RFCCPE1IntHandler +/*---------------------------------------------------------------------------*/ +/* + * Buffers used to send commands to the RF core (generic and IEEE commands). + * Some of those buffers are re-usable, some are not. + * + * If you are uncertain, declare a new buffer. + */ +/* + * A buffer to send a CMD_IEEE_RX and to subsequently monitor its status + * Do not use this buffer for any commands other than CMD_IEEE_RX + */ +static uint8_t cmd_ieee_rx_buf[RF_CMD_BUFFER_SIZE] CC_ALIGN_ATTR(4); + +/* + * A buffer used to send immediate and foreground Radio Op (e.g. CMD_IEEE_TX) + * commands. + * + * Do not re-use this buffer to send a command before the previous command + * has been completed. + * + * Do not intermingle preparation of this buffer to send a command with calls + * that might lead to a different command, since the latter will overwrite what + * you have written in preparation for the former. + */ +static uint8_t cmd_immediate_buf[RF_CMD_BUFFER_SIZE] CC_ALIGN_ATTR(4); +/*---------------------------------------------------------------------------*/ +/* BLE macros, variables and buffers */ + +/* BLE Intervals: Send a burst of advertisements every BLE_ADV_INTERVAL secs */ +#define BLE_ADV_INTERVAL (CLOCK_SECOND * 5) +#define BLE_ADV_DUTY_CYCLE (CLOCK_SECOND / 10) +#define BLE_ADV_MESSAGES 10 + +/* BLE Advertisement-related macros */ +#define BLE_ADV_TYPE_DEVINFO 0x01 +#define BLE_ADV_TYPE_NAME 0x09 +#define BLE_ADV_TYPE_MANUFACTURER 0xFF +#define BLE_ADV_NAME_BUF_LEN 32 +#define BLE_ADV_PAYLOAD_BUF_LEN 64 +#define BLE_UUID_SIZE 16 + +#if CC26XX_RF_BLE_SUPPORT +/* BLE buffers / variables */ +static unsigned char ble_cmd_buf[32] CC_ALIGN_ATTR(4) = { 0 }; +static unsigned char ble_tx_rx_buf[128] CC_ALIGN_ATTR(4); +static uint8_t ble_mode_on; + +/* BLE beacond config */ +static struct ble_beacond_config { + clock_time_t interval; + char adv_name[BLE_ADV_NAME_BUF_LEN]; +} beacond_config; + +/* BLE overrides */ +static uint32_t ble_overrides[] = { + 0x00364038, /* Synth: Set RTRIM (POTAILRESTRIM) to 6 */ + 0x000784A3, /* Synth: Set FREF = 3.43 MHz (24 MHz / 7) */ + 0xA47E0583, /* Synth: Set loop bandwidth after lock to 80 kHz (K2) */ + 0xEAE00603, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, LSB) */ + 0x00010623, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, MSB) */ + 0x00456088, /* Adjust AGC reference level */ + 0xFFFFFFFF, /* End of override list */ +}; + +PROCESS(cc26xx_rf_ble_beacon_process, "CC26xx RF BLE Beacon Process"); + +static void init_ble(void); +#else +#define init_ble(...) +#endif /* CC26XX_RF_BLE_SUPPORT */ +/*---------------------------------------------------------------------------*/ +#define RX_BUF_SIZE 140 +/* Four receive buffers entries with room for 1 IEEE802.15.4 frame in each */ +static uint8_t rx_buf_0[RX_BUF_SIZE] CC_ALIGN_ATTR(4); +static uint8_t rx_buf_1[RX_BUF_SIZE] CC_ALIGN_ATTR(4); +static uint8_t rx_buf_2[RX_BUF_SIZE] CC_ALIGN_ATTR(4); +static uint8_t rx_buf_3[RX_BUF_SIZE] CC_ALIGN_ATTR(4); + +/* The RX Data Queue */ +static dataQueue_t rx_data_queue = { 0 }; + +/* Receive entry pointer to keep track of read items */ +volatile static uint8_t *rx_read_entry; +/*---------------------------------------------------------------------------*/ +/* The outgoing frame buffer */ +#define TX_BUF_SIZE 180 + +static uint8_t tx_buf[TX_BUF_SIZE]; +/*---------------------------------------------------------------------------*/ +/* Overrides for IEEE 802.15.4, differential mode */ +static uint32_t ieee_overrides[] = { + 0x00354038, /* Synth: Set RTRIM (POTAILRESTRIM) to 5 */ + 0x4001402D, /* Synth: Correct CKVD latency setting (address) */ + 0x00608402, /* Synth: Correct CKVD latency setting (value) */ + 0x4001405D, /* Synth: Set ANADIV DIV_BIAS_MODE to PG1 (address) */ + 0x1801F800, /* Synth: Set ANADIV DIV_BIAS_MODE to PG1 (value) */ + 0x000784A3, /* Synth: Set FREF = 3.43 MHz (24 MHz / 7) */ + 0xA47E0583, /* Synth: Set loop bandwidth after lock to 80 kHz (K2) */ + 0xEAE00603, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, LSB) */ + 0x00010623, /* Synth: Set loop bandwidth after lock to 80 kHz (K3, MSB) */ + 0x002B50DC, /* Adjust AGC DC filter */ + 0x05000243, /* Increase synth programming timeout */ + 0x002082C3, /* Increase synth programming timeout */ + 0xFFFFFFFF, /* End of override list */ +}; +/*---------------------------------------------------------------------------*/ +PROCESS(cc26xx_rf_process, "CC26xx RF driver"); +/*---------------------------------------------------------------------------*/ +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) { + return 1; + } + return 0; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Sends a command to the RF core. + * + * \param cmd The command value or a pointer to a command buffer + * \param status A pointer to a variable which will hold the status + * \return RF_CMD_OK or RF_CMD_ERROR + * + * This function supports all three types of command (Radio OP, immediate and + * direct) + * + * For immediate and Radio OPs, cmd is a pointer to the data structure + * containing the command and its parameters. This data structure must be + * 4-byte aligned. + * + * For direct commands, cmd contains the value of the command alongside its + * parameters + * + * The caller is responsible of allocating and populating cmd for Radio OP and + * immediate commands + * + * The caller is responsible for allocating status + */ +static uint_fast8_t +rf_send_cmd(uint32_t cmd, uint32_t *status) +{ + uint32_t timeout_count = 0; + + /* + * Make sure ContikiMAC doesn't turn us off from within an interrupt while + * we are accessing RF Core registers + */ + ti_lib_int_master_disable(); + + if(!rf_is_accessible()) { + PRINTF("rf_send_cmd: RF was off\n"); + ti_lib_int_master_enable(); + return RF_CMD_ERROR; + } + + HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDR) = cmd; + do { + *status = HWREG(RFC_DBELL_BASE + RFC_DBELL_O_CMDSTA); + if(++timeout_count > 50000) { + PRINTF("rf_send_cmd: Timeout\n"); + ti_lib_int_master_enable(); + return RF_CMD_ERROR; + } + } while(*status == RF_CMD_STATUS_PENDING); + + ti_lib_int_master_enable(); + + /* + * If we reach here the command is no longer pending. It is either completed + * successfully or with error + */ + return *status == RF_CMD_STATUS_DONE; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Checks whether the RFC domain is accessible and the RFC is in IEEE RX + * \return 1: RFC in RX mode (and therefore accessible too). 0 otherwise + */ +static uint8_t +rf_is_on(void) +{ + if(!rf_is_accessible()) { + return 0; + } + + return RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == RF_RADIO_OP_STATUS_ACTIVE; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Check the RF's TX status + * \return 1 RF is transmitting + * \return 0 RF is not transmitting + * + * TX mode may be triggered either by a CMD_IEEE_TX or by the automatic + * transmission of an ACK frame. + */ +static uint8_t +transmitting(void) +{ + uint32_t cmd_status; + + /* If we are off, we are not in TX */ + if(!rf_is_accessible()) { + return 0; + } + + memset(cmd_immediate_buf, 0x00, SIZEOF_STRUCT(CMD_IEEE_CCA_REQ)); + GET_FIELD(cmd_immediate_buf, command, commandNo) = CMD_IEEE_CCA_REQ; + + if(rf_send_cmd((uint32_t)cmd_immediate_buf, &cmd_status) == RF_CMD_ERROR) { + PRINTF("transmitting: CMDSTA=0x%08lx, status=0x%04x\n", + cmd_status, RF_RADIO_OP_GET_STATUS(cmd_immediate_buf)); + return 0; + } + + if((GET_FIELD(cmd_immediate_buf, CMD_IEEE_CCA_REQ, currentRssi) + == RF_CMD_CCA_REQ_RSSI_UNKNOWN) && + (GET_BITFIELD(cmd_immediate_buf, CMD_IEEE_CCA_REQ, ccaInfo, ccaEnergy) + == RF_CMD_CCA_REQ_CCA_STATE_BUSY)) { + return 1; + } + + return 0; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns CCA information + * \return RF_GET_CCA_INFO_ERROR if the RF was not on + * \return On success, the return value is formatted as per the ccaInfo field + * of CMD_IEEE_CCA_REQ + * + * It is the caller's responsibility to make sure the RF is on. This function + * will return RF_GET_CCA_INFO_ERROR if the RF is off + * + * This function will in fact wait for a valid RSSI signal + */ +static uint8_t +get_cca_info(void) +{ + uint32_t cmd_status; + int8_t rssi; + + if(!rf_is_on()) { + PRINTF("get_cca_info: Not on\n"); + return RF_GET_CCA_INFO_ERROR; + } + + rssi = RF_CMD_CCA_REQ_RSSI_UNKNOWN; + + while(rssi == RF_CMD_CCA_REQ_RSSI_UNKNOWN || rssi == 0) { + memset(cmd_immediate_buf, 0x00, SIZEOF_STRUCT(CMD_IEEE_CCA_REQ)); + GET_FIELD(cmd_immediate_buf, command, commandNo) = CMD_IEEE_CCA_REQ; + + if(rf_send_cmd((uint32_t)cmd_immediate_buf, &cmd_status) == RF_CMD_ERROR) { + PRINTF("get_cca_info: CMDSTA=0x%08lx, status=0x%04x\n", + cmd_status, RF_RADIO_OP_GET_STATUS(cmd_immediate_buf)); + + return RF_GET_CCA_INFO_ERROR; + } + + rssi = GET_FIELD(cmd_immediate_buf, CMD_IEEE_CCA_REQ, currentRssi); + } + + /* We have a valid RSSI signal. Return the CCA Info */ + return GET_FIELD(cmd_immediate_buf, CMD_IEEE_CCA_REQ, ccaInfo); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Reads the current signal strength (RSSI) + * \return The current RSSI in dBm or CMD_GET_RSSI_UNKNOWN + * + * This function reads the current RSSI on the currently configured + * channel. + */ +static radio_value_t +get_rssi(void) +{ + uint32_t cmd_status; + int8_t rssi; + uint8_t was_off = 0; + + /* If we are off, turn on first */ + if(!rf_is_on()) { + was_off = 1; + if(on() != RF_CMD_OK) { + PRINTF("get_rssi: on() failed\n"); + return RF_CMD_CCA_REQ_RSSI_UNKNOWN; + } + } + + memset(cmd_immediate_buf, 0x00, SIZEOF_STRUCT(CMD_GET_RSSI)); + GET_FIELD(cmd_immediate_buf, command, commandNo) = CMD_GET_RSSI; + + if(rf_send_cmd((uint32_t)cmd_immediate_buf, &cmd_status) == RF_CMD_ERROR) { + rssi = RF_CMD_CCA_REQ_RSSI_UNKNOWN; + } + + /* Current RSSI in bits 23:16 of cmd_status */ + rssi = (cmd_status >> 16) & 0xFF; + + /* If we were off, turn back off */ + if(was_off) { + off(); + } + + return rssi; +} +/*---------------------------------------------------------------------------*/ +/* Returns the current TX power in dBm */ +static radio_value_t +get_tx_power(void) +{ + return tx_power_current->dbm; +} +/*---------------------------------------------------------------------------*/ +/* + * Set TX power to 'at least' power dBm + * This works with a lookup table. If the value of 'power' does not exist in + * the lookup table, TXPOWER will be set to the immediately higher available + * value + */ +static void +set_tx_power(radio_value_t power) +{ + uint32_t cmd_status; + int i; + + /* Send a CMD_SET_TX_POWER command to the RF */ + memset(cmd_immediate_buf, 0x00, SIZEOF_STRUCT(CMD_SET_TX_POWER)); + + GET_FIELD(cmd_immediate_buf, command, commandNo) = CMD_SET_TX_POWER; + + for(i = OUTPUT_CONFIG_COUNT - 1; i >= 0; --i) { + if(power <= output_power[i].dbm) { + GET_FIELD(cmd_immediate_buf, CMD_SET_TX_POWER, txPower) = + BITVALUE(CMD_SET_TX_POWER, txPower, IB, output_power[i].register_ib) | + BITVALUE(CMD_SET_TX_POWER, txPower, GC, output_power[i].register_gc) | + BITVALUE(CMD_SET_TX_POWER, txPower, tempCoeff, 0); + + if(rf_send_cmd((uint32_t)cmd_immediate_buf, &cmd_status) == RF_CMD_OK) { + /* Success: Remember the new setting */ + tx_power_current = &output_power[i]; + } else { + PRINTF("set_tx_power: CMDSTA=0x%08lx\n", cmd_status); + } + return; + } + } +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Wait till running radio Op command completes + * + * \return RF_CMD_ERROR or RF_CMD_OK + * + * RF_CMD_OK will be returned if the Radio Op returned with + * RF_RADIO_OP_STATUS_DONE_OK + * + * RF_CMD_ERROR will be returned in the radio op returned with any other + * RF_RADIO_OP_STATUS_DONE_xyz + */ +static uint_fast8_t +rf_wait_cmd_completed_ok(uint8_t *cmd) +{ + _TYPE_radioOp_status tmp_status; + uint32_t timeoutCount = 0; + + /* + * 0x04XX=DONE, 0x0400=DONE_OK while all other "DONE" values means done + * but with some kind of error (ref. "Common radio operation status codes") + */ + do { + tmp_status = GET_FIELD_V(cmd, radioOp, status); + if(++timeoutCount > 500000) { + return RF_CMD_ERROR; + } + } while((tmp_status & RF_RADIO_OP_MASKED_STATUS) != RF_RADIO_OP_MASKED_STATUS_DONE); + + return tmp_status == RF_RADIO_OP_STATUS_DONE_OK; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Builds common radio parameters for radio operations + * + * \param *cmd Pointer to buffer to add parameters to + * \param command Radio command number (e.g. COMMAND_RADIO_SETUP) + * + * \note The buffer must be emptied with memset() before calling this function + * + * \return None + */ +static void +rf_build_radio_op_cmd(uint8_t *cmd, uint16_t command) +{ + GET_FIELD(cmd, radioOp, commandNo) = command; + GET_FIELD(cmd, radioOp, status) = IDLE; + GET_FIELD(cmd, radioOp, pNextOp) = NULL; + GET_FIELD(cmd, radioOp, startTime) = 0; + GET_FIELD(cmd, radioOp, startTrigger) = TRIG_NOW; + GET_FIELD(cmd, radioOp, condition) = COND_NEVER; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Sends a CMD_RADIO_SETUP for the selected mode (IEEE or BLE) + * \param mode RF_MODE_BLE or RF_MODE_IEEE + * \return RF_CMD_OK or RF_CMD_ERROR + * + * ToDo: Likely to need one more argument to set bNoAdi on first startup + * vs when coming back from sleep + */ +static uint8_t +rf_radio_setup(uint8_t mode) +{ + uint32_t cmd_status; + + /* Create radio setup command */ + memset(cmd_immediate_buf, 0x00, SIZEOF_RADIO_OP(CMD_RADIO_SETUP)); + rf_build_radio_op_cmd(cmd_immediate_buf, CMD_RADIO_SETUP); + + /* Set output power to the current (or default) value */ + GET_FIELD(cmd_immediate_buf, CMD_RADIO_SETUP, txPower) = + BITVALUE(CMD_RADIO_SETUP, txPower, IB, tx_power_current->register_ib) | + BITVALUE(CMD_RADIO_SETUP, txPower, GC, tx_power_current->register_gc) | + BITVALUE(CMD_RADIO_SETUP, txPower, tempCoeff, 0); + + /* Do mode-dependent things (e.g. apply overrides) */ + if(mode == RF_MODE_IEEE) { + /* Add override control pointer */ + GET_FIELD(cmd_immediate_buf, CMD_RADIO_SETUP, pRegOverride) = ieee_overrides; +#if CC26XX_RF_BLE_SUPPORT + } else if(mode == RF_MODE_BLE) { + /* Add override control pointer */ + GET_FIELD(cmd_immediate_buf, CMD_RADIO_SETUP, pRegOverride) = ble_overrides; +#endif + } else { + PRINTF("rf_radio_setup: Unknown mode %u\n", mode); + return RF_CMD_ERROR; + } + + /* Lastly, set the mode */ + GET_FIELD(cmd_immediate_buf, CMD_RADIO_SETUP, mode) = mode; + + /* Send Radio setup to RF Core */ + if(rf_send_cmd((uint32_t)cmd_immediate_buf, &cmd_status) != RF_CMD_OK) { + PRINTF("rf_radio_setup: CMD_RADIO_SETUP, CMDSTA=0x%08lx, status=0x%04x\n", + cmd_status, RF_RADIO_OP_GET_STATUS(cmd_immediate_buf)); + return RF_CMD_ERROR; + } + + /* Wait until radio setup is done */ + if(rf_wait_cmd_completed_ok(cmd_immediate_buf) != RF_CMD_OK) { + PRINTF("rf_radio_setup: CMD_RADIO_SETUP wait, CMDSTA=0x%08lx, status=0x%04x\n", + cmd_status, RF_RADIO_OP_GET_STATUS(cmd_immediate_buf)); + return RF_CMD_ERROR; + } + + return RF_CMD_OK; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Applies patches (if any) + * \return RF_CMD_OK or RF_CMD_ERROR + * + * Currently patches are not required. + */ +static uint8_t +apply_patches() +{ + uint32_t cmd_status; + + /* Patch of uninitialized pointer */ + *((uint32_t *)0x21000028) = 0x00000000; + + /* Start radio timer (RAT) */ + if(rf_send_cmd(CMDR_DIR_CMD(CMD_START_RAT), &cmd_status) != RF_CMD_OK) { + PRINTF("apply_patches: START_RAT fail, CMDSTA=0x%08lx\n", cmd_status); + return RF_CMD_ERROR; + } + + return RF_CMD_OK; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Set up radio in IEEE802.15.4 RX mode + * + * \return RF_CMD_OK Succeeded + * \return RF_CMD_ERROR Failed + * + * This function assumes that cmd_ieee_rx_buf has been previously populated + * with correct values. This can be done through init_rf_params (sets defaults) + * or through Contiki's extended RF API (set_value, set_object) + */ +static uint8_t +rf_cmd_ieee_rx() +{ + uint32_t cmd_status; + rtimer_clock_t t0; + int ret; + + ret = rf_send_cmd((uint32_t)cmd_ieee_rx_buf, &cmd_status); + + if(ret != RF_CMD_OK) { + PRINTF("rf_cmd_ieee_rx: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n", + ret, cmd_status, RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf)); + } + + t0 = RTIMER_NOW(); + + while(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) != RF_RADIO_OP_STATUS_ACTIVE && + (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + ENTER_RX_WAIT_TIMEOUT))); + + /* Wait to enter RX */ + if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) != RF_RADIO_OP_STATUS_ACTIVE) { + PRINTF("rf_cmd_ieee_rx: CMDSTA=0x%08lx, status=0x%04x\n", + cmd_status, RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf)); + return RF_CMD_ERROR; + } + + return ret; +} +/*---------------------------------------------------------------------------*/ +static void +init_rx_buffers(void) +{ + /* Two-element circular buffer, hardcoded for now.. */ + GET_FIELD(rx_buf_0, dataEntry, pNextEntry) = rx_buf_1; + GET_FIELD(rx_buf_0, dataEntry, config) = 0x04; + GET_FIELD(rx_buf_0, dataEntry, length) = sizeof(rx_buf_0) - 8; + + GET_FIELD(rx_buf_1, dataEntry, pNextEntry) = rx_buf_2; + GET_FIELD(rx_buf_1, dataEntry, config) = 0x04; + GET_FIELD(rx_buf_1, dataEntry, length) = sizeof(rx_buf_1) - 8; + + GET_FIELD(rx_buf_2, dataEntry, pNextEntry) = rx_buf_3; + GET_FIELD(rx_buf_2, dataEntry, config) = 0x04; + GET_FIELD(rx_buf_2, dataEntry, length) = sizeof(rx_buf_2) - 8; + + /* Point to first element again */ + GET_FIELD(rx_buf_3, dataEntry, pNextEntry) = rx_buf_0; + GET_FIELD(rx_buf_3, dataEntry, config) = 0x04; + GET_FIELD(rx_buf_3, dataEntry, length) = sizeof(rx_buf_3) - 8; +} +/*---------------------------------------------------------------------------*/ +static void +init_rf_params(void) +{ + memset(cmd_ieee_rx_buf, 0x00, SIZEOF_RADIO_OP(CMD_IEEE_RX)); + + GET_FIELD(cmd_ieee_rx_buf, radioOp, commandNo) = CMD_IEEE_RX; + GET_FIELD(cmd_ieee_rx_buf, radioOp, status) = IDLE; + GET_FIELD(cmd_ieee_rx_buf, radioOp, pNextOp) = NULL; + GET_FIELD(cmd_ieee_rx_buf, radioOp, startTime) = 0x00000000; + GET_FIELD(cmd_ieee_rx_buf, radioOp, startTrigger) = TRIG_NOW; + GET_FIELD(cmd_ieee_rx_buf, radioOp, condition) = COND_NEVER; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, channel) = CC26XX_RF_CHANNEL; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, rxConfig) = + BITVALUE(CMD_IEEE_RX, rxConfig, bAutoFlushCrc, 0) | + BITVALUE(CMD_IEEE_RX, rxConfig, bAutoFlushIgn, 0) | + BITVALUE(CMD_IEEE_RX, rxConfig, bIncludePhyHdr, 0) | + BITVALUE(CMD_IEEE_RX, rxConfig, bIncludeCrc, 1) | + BITVALUE(CMD_IEEE_RX, rxConfig, bAppendRssi, 1) | + BITVALUE(CMD_IEEE_RX, rxConfig, bAppendCorrCrc, 1) | + BITVALUE(CMD_IEEE_RX, rxConfig, bAppendSrcInd, 0) | + BITVALUE(CMD_IEEE_RX, rxConfig, bAppendTimestamp, 0); + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, pRxQ) = &rx_data_queue; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, pOutput) = rf_stats; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, frameFiltOpt) = +#if CC26XX_RF_CONF_PROMISCOUS + BITVALUE(CMD_IEEE_RX, frameFiltOpt, frameFiltEn, 0) | +#else + BITVALUE(CMD_IEEE_RX, frameFiltOpt, frameFiltEn, 1) | +#endif + BITVALUE(CMD_IEEE_RX, frameFiltOpt, frameFiltStop, 1) | +#if CC26XX_RF_CONF_AUTOACK + BITVALUE(CMD_IEEE_RX, frameFiltOpt, autoAckEn, 1) | +#else + BITVALUE(CMD_IEEE_RX, frameFiltOpt, autoAckEn, 0) | +#endif + BITVALUE(CMD_IEEE_RX, frameFiltOpt, slottedAckEn, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, autoPendEn, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, defaultPend, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, bPendDataReqOnly, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, bPanCoord, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, maxFrameVersion, 1) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, bStrictLenFilter, 0); + /* Receive all frame types */ + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, frameTypes) = + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt0Beacon, 1) | + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt1Data, 1) | + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt2Ack, 1) | + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt3MacCmd, 1) | + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt4Reserved, 1) | + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt5Reserved, 1) | + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt6Reserved, 1) | + BITVALUE(CMD_IEEE_RX, frameTypes, bAcceptFt7Reserved, 1); + /* Configure CCA settings */ + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, ccaOpt) = + BITVALUE(CMD_IEEE_RX, ccaOpt, ccaEnEnergy, 1) | + BITVALUE(CMD_IEEE_RX, ccaOpt, ccaEnCorr, 0) | + BITVALUE(CMD_IEEE_RX, ccaOpt, ccaEnSync, 0) | + BITVALUE(CMD_IEEE_RX, ccaOpt, ccaCorrOp, 0) | + BITVALUE(CMD_IEEE_RX, ccaOpt, ccaSyncOp, 0); + /* Set CCA RSSI Threshold, 0xA6 corresponds to -90dBm (two's comp.)*/ + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, ccaRssiThr) = 0xA6; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, numExtEntries) = 0x00; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, numShortEntries) = 0x00; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, pExtEntryList) = 0; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, pShortEntryList) = 0; + + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, endTrigger) = TRIG_NEVER; + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, endTime) = 0x00000000; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Turn on power to the RFC and boot it. + * + * \return RF_CMD_OK or RF_CMD_ERROR + */ +static int +power_up(void) +{ + uint32_t cmd_status; + + 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); + ti_lib_int_disable(INT_RF_CPE1); + + /* Enable RF Core power domain */ + ti_lib_prcm_power_domain_on(PRCM_DOMAIN_RFCORE); + while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE) + != PRCM_DOMAIN_POWER_ON); + + ti_lib_prcm_domain_enable(PRCM_DOMAIN_RFCORE); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + while(!rf_is_accessible()) { + PRINTF("power_up: Not ready\n"); + } + + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0; + 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(); + + /* Let CPE boot */ + HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = RF_CORE_CLOCKS_MASK; + + /* Send ping (to verify RFCore is ready and alive) */ + if(rf_send_cmd(CMDR_DIR_CMD(CMD_PING), &cmd_status) != RF_CMD_OK) { + PRINTF("power_up: CMD_PING fail, CMDSTA=0x%08lx\n", cmd_status); + return RF_CMD_ERROR; + } + + return RF_CMD_OK; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Disable RFCORE clock domain in the MCU VD and turn off the RFCORE PD + */ +static void +power_down(void) +{ + ti_lib_int_master_disable(); + ti_lib_int_disable(INT_RF_CPE0); + ti_lib_int_disable(INT_RF_CPE1); + + if(rf_is_accessible()) { + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0; + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = 0x0; + } + + /* Shut down the RFCORE clock domain in the MCU VD */ + ti_lib_prcm_domain_disable(PRCM_DOMAIN_RFCORE); + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + /* Turn off RFCORE PD */ + ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE); + while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_RFCORE) + != PRCM_DOMAIN_POWER_OFF); + + ti_lib_int_pend_clear(INT_RF_CPE0); + 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(); +} +/*---------------------------------------------------------------------------*/ +static int +rx_on(void) +{ + int ret; + + /* Get status of running IEEE_RX (if any) */ + if(rf_is_on()) { + PRINTF("rx_on: We were on. PD=%u, RX=0x%04x \n", rf_is_accessible(), + RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf)); + return RF_CMD_OK; + } + + /* Put CPE in RX using the currently configured parameters */ + ret = rf_cmd_ieee_rx(); + + if(ret) { + ENERGEST_ON(ENERGEST_TYPE_LISTEN); + } + + return ret; +} +/*---------------------------------------------------------------------------*/ +static int +rx_off(void) +{ + uint32_t cmd_status; + int ret; + + /* If we are off, do nothing */ + if(!rf_is_on()) { + return RF_CMD_OK; + } + + /* Wait for ongoing ACK TX to finish */ + while(transmitting()); + + /* Send a CMD_STOP command to RF Core */ + if(rf_send_cmd(CMDR_DIR_CMD(CMD_ABORT), &cmd_status) != RF_CMD_OK) { + PRINTF("RX off: CMD_ABORT status=0x%08lx\n", cmd_status); + /* Continue nonetheless */ + } + + while(rf_is_on()); + + if(RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_STOPPED || + RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf) == IEEE_DONE_ABORT) { + /* Stopped gracefully */ + ENERGEST_OFF(ENERGEST_TYPE_LISTEN); + ret = RF_CMD_OK; + } else { + PRINTF("RX off: BG status=0x%04x\n", RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf)); + ret = RF_CMD_ERROR; + } + + return ret; +} +/*---------------------------------------------------------------------------*/ +static void +rx_isr(void) +{ + process_poll(&cc26xx_rf_process); +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_rf_cpe1_isr(void) +{ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + ti_lib_int_master_disable(); + PRINTF("RF Error\n"); + + if(!rf_is_accessible()) { + if(power_up() != RF_CMD_OK) { + return; + } + } + + /* Clear interrupt flags */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0; + ti_lib_int_master_enable(); + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_rf_cpe0_isr(void) +{ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + if(!rf_is_accessible()) { + printf("RF ISR called but RF not ready... PANIC!!\n"); + if(power_up() != RF_CMD_OK) { + PRINTF("power_up() failed\n"); + return; + } + } + + ti_lib_int_master_disable(); + if(HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) & RX_IRQ) { + rx_isr(); + } + + /* Clear interrupt flags */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0; + ti_lib_int_master_enable(); + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +/*---------------------------------------------------------------------------*/ +static void +setup_interrupts(void) +{ + /* We are already turned on by the caller, so this should not happen */ + if(!rf_is_accessible()) { + PRINTF("setup_interrupts: No access\n"); + return; + } + + /* Disable interrupts */ + 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; + + /* Acknowledge TX_Frame, Rx_Entry_Done and ERROR */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIEN) = ENABLED_IRQS; + + /* Clear interrupt flags, active low clear(?) */ + HWREG(RFC_DBELL_NONBUF_BASE + RFC_DBELL_O_RFCPEIFG) = 0x0; + + ti_lib_int_pend_clear(INT_RF_CPE0); + 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(); +} +/*---------------------------------------------------------------------------*/ +static uint8_t +request(void) +{ + /* + * We rely on the RDC layer to turn us on and off. Thus, if we are on we + * will only allow sleep, standby otherwise + */ + if(rf_is_on()) { + return LPM_MODE_SLEEP; + } + + return LPM_MODE_MAX_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +LPM_MODULE(cc26xx_rf_lpm_module, request, NULL, NULL); +/*---------------------------------------------------------------------------*/ +static int +init(void) +{ + lpm_register_module(&cc26xx_rf_lpm_module); + + /* Enable IEEE, BLE and Common-CMD APIs */ + HWREG(PRCM_BASE + PRCM_O_RFCMODESEL) = PRCM_RFCMODESEL_CURR_MODE5; + + /* Wipe out the BLE adv buffer */ + init_ble(); + + /* Initialise RX buffers */ + memset(rx_buf_0, 0, RX_BUF_SIZE); + memset(rx_buf_1, 0, RX_BUF_SIZE); + memset(rx_buf_2, 0, RX_BUF_SIZE); + memset(rx_buf_3, 0, RX_BUF_SIZE); + + /* Set of RF Core data queue. Circular buffer, no last entry */ + rx_data_queue.pCurrEntry = rx_buf_0; + + rx_data_queue.pLastEntry = NULL; + + /* Initialize current read pointer to first element (used in ISR) */ + rx_read_entry = rx_buf_0; + + /* Populate the RF parameters data structure with default values */ + init_rf_params(); + + if(on() != RF_CMD_OK) { + PRINTF("init: on() failed\n"); + return RF_CMD_ERROR; + } + + ENERGEST_ON(ENERGEST_TYPE_LISTEN); + + process_start(&cc26xx_rf_process, NULL); + return 1; +} +/*---------------------------------------------------------------------------*/ +static int +prepare(const void *payload, unsigned short payload_len) +{ + int len = MIN(payload_len, sizeof(tx_buf)); + + memcpy(tx_buf, payload, len); + return RF_CMD_OK; +} +/*---------------------------------------------------------------------------*/ +static int +transmit(unsigned short transmit_len) +{ + int ret; + uint8_t was_off = 0; + uint32_t cmd_status; + uint16_t stat; + uint8_t tx_active = 0; + rtimer_clock_t t0; + + if(!rf_is_on()) { + was_off = 1; + if(on() != RF_CMD_OK) { + PRINTF("transmit: on() failed\n"); + return RF_CMD_ERROR; + } + } + + /* + * We are certainly not TXing a frame as a result of CMD_IEEE_TX, but we may + * be in the process of TXing an ACK. In that case, wait for the TX to finish + * or return after approx TX_WAIT_TIMEOUT + */ + t0 = RTIMER_NOW(); + + do { + tx_active = transmitting(); + } while(tx_active == 1 && + (RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + TX_WAIT_TIMEOUT))); + + if(tx_active) { + PRINTF("transmit: Already TXing and wait timed out\n"); + + if(was_off) { + off(); + } + + return RADIO_TX_COLLISION; + } + + /* Send the CMD_IEEE_TX command */ + memset(cmd_immediate_buf, 0, SIZEOF_RADIO_OP(CMD_IEEE_TX)); + + rf_build_radio_op_cmd(cmd_immediate_buf, CMD_IEEE_TX); + + GET_FIELD(cmd_immediate_buf, CMD_IEEE_TX, payloadLen) = transmit_len; + GET_FIELD(cmd_immediate_buf, CMD_IEEE_TX, pPayload) = tx_buf; + + ret = rf_send_cmd((uint32_t)cmd_immediate_buf, &cmd_status); + + if(ret) { + /* If we enter here, TX actually started */ + ENERGEST_OFF(ENERGEST_TYPE_LISTEN); + ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); + + /* Idle away while the command is running */ + while((RF_RADIO_OP_GET_STATUS(cmd_immediate_buf) & RF_RADIO_OP_MASKED_STATUS) + == RF_RADIO_OP_MASKED_STATUS_RUNNING) { + lpm_sleep(); + } + + stat = RF_RADIO_OP_GET_STATUS(cmd_immediate_buf); + + if(stat == RF_RADIO_OP_STATUS_IEEE_DONE_OK) { + /* Sent OK */ + RIMESTATS_ADD(lltx); + ret = RADIO_TX_OK; + } else { + /* Operation completed, but frame was not sent */ + PRINTF("transmit: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n", ret, + cmd_status, stat); + ret = RADIO_TX_ERR; + } + } else { + /* Failure sending the CMD_IEEE_TX command */ + PRINTF("transmit: ret=%d, CMDSTA=0x%08lx, status=0x%04x\n", + ret, cmd_status, RF_RADIO_OP_GET_STATUS(cmd_immediate_buf)); + + ret = RADIO_TX_ERR; + } + + /* + * Update ENERGEST state here, before a potential call to off(), which + * will correctly update it if required. + */ + ENERGEST_OFF(ENERGEST_TYPE_TRANSMIT); + ENERGEST_ON(ENERGEST_TYPE_LISTEN); + + if(was_off) { + off(); + } + + return ret; +} +/*---------------------------------------------------------------------------*/ +static int +send(const void *payload, unsigned short payload_len) +{ + prepare(payload, payload_len); + return transmit(payload_len); +} +/*---------------------------------------------------------------------------*/ +static int +read_frame(void *buf, unsigned short buf_len) +{ + int len = 0; + + if(GET_FIELD_V(rx_read_entry, dataEntry, status) == DATA_ENTRY_STATUS_FINISHED) { + /* Set status to 0 "Pending" in element */ + GET_FIELD_V(rx_read_entry, dataEntry, status) = DATA_ENTRY_STATUS_PENDING; + + if(rx_read_entry[8] > 0) { + memcpy(buf, (char *)&rx_read_entry[9], buf_len); + + /* Remove the footer */ + len = MIN(buf_len, rx_read_entry[8] - 4); + + int rssi = (int8_t)rx_read_entry[9 + len + 2]; + + packetbuf_set_attr(PACKETBUF_ATTR_RSSI, rssi); + RIMESTATS_ADD(llrx); + + /* Clear the length byte */ + rx_read_entry[8] = 0; + } + + /* Move read entry pointer to next entry */ + rx_read_entry = GET_FIELD_V(rx_read_entry, dataEntry, pNextEntry); + } + + return len; +} +/*---------------------------------------------------------------------------*/ +static int +channel_clear(void) +{ + uint8_t was_off = 0; + uint8_t cca_info; + int ret = RF_CCA_CLEAR; + + /* + * If we are in the middle of a BLE operation, we got called by ContikiMAC + * from within an interrupt context. Indicate a clear channel + */ +#if CC26XX_RF_BLE_SUPPORT + if(ble_mode_on) { + PRINTF("channel_clear: Interrupt context but BLE in progress\n"); + return RF_CCA_CLEAR; + } +#endif + + if(rf_is_on()) { + /* + * Wait for potential leftover ACK still being sent. + * Strictly speaking, if we are TXing an ACK then the channel is not clear. + * However, channel_clear is only ever called to determine whether there is + * someone else's packet in the air, not ours. + * + * We could probably even simply return that the channel is clear + */ + while(transmitting()); + } else { + was_off = 1; + if(on() != RF_CMD_OK) { + PRINTF("channel_clear: on() failed\n"); + if(was_off) { + off(); + } + return RF_CCA_CLEAR; + } + } + + cca_info = get_cca_info(); + + if(cca_info == RF_GET_CCA_INFO_ERROR) { + PRINTF("channel_clear: CCA error\n"); + ret = RF_CCA_CLEAR; + } else { + /* + * cca_info bits 1:0 - ccaStatus + * Return 1 (clear) if idle or invalid. + */ + ret = (cca_info & 0x03) != RF_CMD_CCA_REQ_CCA_STATE_BUSY; + } + + if(was_off) { + off(); + } + + return ret; +} +/*---------------------------------------------------------------------------*/ +static int +receiving_packet(void) +{ + int ret = 0; + uint8_t cca_info; + uint8_t was_off = 0; + + if(!rf_is_on()) { + was_off = 1; + if(on() != RF_CMD_OK) { + PRINTF("receiving_packet: on() failed\n"); + return RF_CMD_ERROR; + } + } + + /* + * If we are in the middle of a BLE operation, we got called by ContikiMAC + * from within an interrupt context. We are not receiving + */ +#if CC26XX_RF_BLE_SUPPORT + if(ble_mode_on) { + PRINTF("receiving_packet: Interrupt context but BLE in progress\n"); + return 0; + } +#endif + + /* If we are off, we are not receiving */ + if(!rf_is_on()) { + PRINTF("receiving_packet: We were off\n"); + return 0; + } + + /* If we are transmitting (can only be an ACK here), we are not receiving */ + if(transmitting()) { + PRINTF("receiving_packet: We were TXing\n"); + return 0; + } + + cca_info = get_cca_info(); + + if(cca_info == RF_GET_CCA_INFO_ERROR) { + /* If we can't read CCA info, return "not receiving" */ + ret = 0; + } else { + /* Return 1 (receiving) if ccaState is busy */ + ret = (cca_info & 0x03) == RF_CMD_CCA_REQ_CCA_STATE_BUSY; + } + + if(was_off) { + off(); + } + + return ret; +} +/*---------------------------------------------------------------------------*/ +static int +pending_packet(void) +{ + volatile uint8_t *current = rx_data_queue.pCurrEntry; + int rv = 0; + + /* Go through all RX buffers and check their status */ + do { + if(GET_FIELD_V(current, dataEntry, status) == + DATA_ENTRY_STATUS_FINISHED) { + rv = 1; + process_poll(&cc26xx_rf_process); + } + + current = GET_FIELD_V(current, dataEntry, pNextEntry); + } while(current != rx_data_queue.pCurrEntry); + + /* If we didn't find an entry at status finished, no frames are pending */ + return rv; +} +/*---------------------------------------------------------------------------*/ +static int +on(void) +{ + /* + * Request the HF XOSC as the source for the HF clock. Needed before we can + * use the FS. This will only request, it will _not_ perform the switch. + */ + request_hf_xosc(); + + /* + * If we are in the middle of a BLE operation, we got called by ContikiMAC + * from within an interrupt context. Abort, but pretend everything is OK. + */ +#if CC26XX_RF_BLE_SUPPORT + if(ble_mode_on) { + PRINTF("on: Interrupt context but BLE in progress\n"); + return RF_CMD_OK; + } +#endif + + if(rf_is_on()) { + PRINTF("on: We were on. PD=%u, RX=0x%04x \n", rf_is_accessible(), + RF_RADIO_OP_GET_STATUS(cmd_ieee_rx_buf)); + return RF_CMD_OK; + } + + if(power_up() != RF_CMD_OK) { + PRINTF("on: power_up() failed\n"); + return RF_CMD_ERROR; + } + + if(apply_patches() != RF_CMD_OK) { + PRINTF("on: apply_patches() failed\n"); + return RF_CMD_ERROR; + } + + init_rx_buffers(); + + setup_interrupts(); + + /* + * Trigger a switch to the XOSC, so that we can subsequently use the RF FS + * This will block until the XOSC is actually ready, but give how we + * requested it early on, this won't be too long a wait/ + */ + switch_to_hf_xosc(); + + if(rf_radio_setup(RF_MODE_IEEE) != RF_CMD_OK) { + PRINTF("on: radio_setup() failed\n"); + return RF_CMD_ERROR; + } + + return rx_on(); +} +/*---------------------------------------------------------------------------*/ +static int +off(void) +{ + /* + * If we are in the middle of a BLE operation, we got called by ContikiMAC + * from within an interrupt context. Abort, but pretend everything is OK. + */ +#if CC26XX_RF_BLE_SUPPORT + if(ble_mode_on) { + PRINTF("off: Interrupt context but BLE in progress\n"); + return RF_CMD_OK; + } +#endif + + while(transmitting()); + + power_down(); + + /* Switch HF clock source to the RCOSC to preserve power */ + switch_to_hf_rc_osc(); + + /* We pulled the plug, so we need to restore the status manually */ + GET_FIELD(cmd_ieee_rx_buf, radioOp, status) = IDLE; + + /* + * Just in case there was an ongoing RX (which started after we begun the + * shutdown sequence), we don't want to leave the buffer in state == ongoing + */ + GET_FIELD_V(rx_buf_0, dataEntry, status) = DATA_ENTRY_STATUS_PENDING; + GET_FIELD_V(rx_buf_1, dataEntry, status) = DATA_ENTRY_STATUS_PENDING; + GET_FIELD_V(rx_buf_2, dataEntry, status) = DATA_ENTRY_STATUS_PENDING; + GET_FIELD_V(rx_buf_3, dataEntry, status) = DATA_ENTRY_STATUS_PENDING; + + return RF_CMD_OK; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_value(radio_param_t param, radio_value_t *value) +{ + if(!value) { + return RADIO_RESULT_INVALID_VALUE; + } + + switch(param) { + case RADIO_PARAM_POWER_MODE: + /* On / off */ + *value = rf_is_on() ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF; + return RADIO_RESULT_OK; + case RADIO_PARAM_CHANNEL: + *value = (radio_value_t)GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, channel); + return RADIO_RESULT_OK; + case RADIO_PARAM_PAN_ID: + *value = (radio_value_t)GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, localPanID); + return RADIO_RESULT_OK; + case RADIO_PARAM_16BIT_ADDR: + *value = (radio_value_t)GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, localShortAddr); + return RADIO_RESULT_OK; + case RADIO_PARAM_RX_MODE: + *value = 0; + if(GET_BITFIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, frameFiltOpt, frameFiltEn)) { + *value |= RADIO_RX_MODE_ADDRESS_FILTER; + } + if(GET_BITFIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, frameFiltOpt, autoAckEn)) { + *value |= RADIO_RX_MODE_AUTOACK; + } + + return RADIO_RESULT_OK; + case RADIO_PARAM_TXPOWER: + *value = get_tx_power(); + return RADIO_RESULT_OK; + case RADIO_PARAM_CCA_THRESHOLD: + *value = GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, ccaRssiThr); + return RADIO_RESULT_OK; + case RADIO_PARAM_RSSI: + *value = get_rssi(); + + if(*value == RF_CMD_CCA_REQ_RSSI_UNKNOWN) { + return RADIO_RESULT_ERROR; + } else { + return RADIO_RESULT_OK; + } + case RADIO_CONST_CHANNEL_MIN: + *value = CC26XX_RF_CHANNEL_MIN; + return RADIO_RESULT_OK; + case RADIO_CONST_CHANNEL_MAX: + *value = CC26XX_RF_CHANNEL_MAX; + return RADIO_RESULT_OK; + case RADIO_CONST_TXPOWER_MIN: + *value = OUTPUT_POWER_MIN; + return RADIO_RESULT_OK; + case RADIO_CONST_TXPOWER_MAX: + *value = OUTPUT_POWER_MAX; + return RADIO_RESULT_OK; + default: + return RADIO_RESULT_NOT_SUPPORTED; + } +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_value(radio_param_t param, radio_value_t value) +{ + uint8_t was_off = 0; + radio_result_t rv; + + switch(param) { + case RADIO_PARAM_POWER_MODE: + if(value == RADIO_POWER_MODE_ON) { + if(on() != RF_CMD_OK) { + PRINTF("set_value: on() failed (1)\n"); + return RADIO_RESULT_ERROR; + } + return RADIO_RESULT_OK; + } + if(value == RADIO_POWER_MODE_OFF) { + off(); + return RADIO_RESULT_OK; + } + return RADIO_RESULT_INVALID_VALUE; + case RADIO_PARAM_CHANNEL: + if(value < CC26XX_RF_CHANNEL_MIN || + value > CC26XX_RF_CHANNEL_MAX) { + return RADIO_RESULT_INVALID_VALUE; + } + + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, channel) = (uint8_t)value; + break; + case RADIO_PARAM_PAN_ID: + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, localPanID) = (uint16_t)value; + break; + case RADIO_PARAM_16BIT_ADDR: + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, localShortAddr) = (uint16_t)value; + break; + case RADIO_PARAM_RX_MODE: + { + if(value & ~(RADIO_RX_MODE_ADDRESS_FILTER | + RADIO_RX_MODE_AUTOACK)) { + return RADIO_RESULT_INVALID_VALUE; + } + + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, frameFiltOpt) = + BITVALUE(CMD_IEEE_RX, frameFiltOpt, frameFiltEn, + (value & RADIO_RX_MODE_ADDRESS_FILTER) != 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, frameFiltStop, 1) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, autoAckEn, + (value & RADIO_RX_MODE_AUTOACK) != 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, slottedAckEn, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, autoPendEn, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, defaultPend, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, bPendDataReqOnly, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, bPanCoord, 0) | + BITVALUE(CMD_IEEE_RX, frameFiltOpt, bStrictLenFilter, 0); + + break; + } + case RADIO_PARAM_TXPOWER: + if(value < OUTPUT_POWER_MIN || value > OUTPUT_POWER_MAX) { + return RADIO_RESULT_INVALID_VALUE; + } + + set_tx_power(value); + + return RADIO_RESULT_OK; + case RADIO_PARAM_CCA_THRESHOLD: + GET_FIELD(cmd_ieee_rx_buf, CMD_IEEE_RX, ccaRssiThr) = (int8_t)value; + break; + default: + return RADIO_RESULT_NOT_SUPPORTED; + } + + /* If we reach here we had no errors. Apply new settings */ + if(!rf_is_on()) { + was_off = 1; + if(on() != RF_CMD_OK) { + PRINTF("set_value: on() failed (2)\n"); + return RADIO_RESULT_ERROR; + } + } + + if(rx_off() != RF_CMD_OK) { + PRINTF("set_value: rx_off() failed\n"); + rv = RADIO_RESULT_ERROR; + } + + if(rx_on() != RF_CMD_OK) { + PRINTF("set_value: rx_on() failed\n"); + rv = RADIO_RESULT_ERROR; + } + + /* If we were off, turn back off */ + if(was_off) { + off(); + } + + return rv; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +get_object(radio_param_t param, void *dest, size_t size) +{ + uint8_t *target; + uint8_t *src; + int i; + + if(param == RADIO_PARAM_64BIT_ADDR) { + if(size != 8 || !dest) { + return RADIO_RESULT_INVALID_VALUE; + } + + target = dest; + src = (uint8_t *)(GET_FIELD_PTR(cmd_ieee_rx_buf, CMD_IEEE_RX, localExtAddr)); + + for(i = 0; i < 8; i++) { + target[i] = src[7 - i]; + } + + return RADIO_RESULT_OK; + } + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +static radio_result_t +set_object(radio_param_t param, const void *src, size_t size) +{ + uint8_t was_off = 0; + radio_result_t rv; + int i; + uint8_t *dst; + + if(param == RADIO_PARAM_64BIT_ADDR) { + if(size != 8 || !src) { + return RADIO_RESULT_INVALID_VALUE; + } + + dst = (uint8_t *)(GET_FIELD_PTR(cmd_ieee_rx_buf, CMD_IEEE_RX, + localExtAddr)); + + for(i = 0; i < 8; i++) { + dst[i] = ((uint8_t *)src)[7 - i]; + } + + if(!rf_is_on()) { + was_off = 1; + if(on() != RF_CMD_OK) { + PRINTF("set_object: on() failed\n"); + return RADIO_RESULT_ERROR; + } + } + + if(rx_off() != RF_CMD_OK) { + PRINTF("set_object: rx_off() failed\n"); + rv = RADIO_RESULT_ERROR; + } + + if(rx_on() != RF_CMD_OK) { + PRINTF("set_object: rx_on() failed\n"); + rv = RADIO_RESULT_ERROR; + } + + /* If we were off, turn back off */ + if(was_off) { + off(); + } + + return rv; + } + return RADIO_RESULT_NOT_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +const struct radio_driver cc26xx_rf_driver = { + init, + prepare, + transmit, + send, + read_frame, + channel_clear, + receiving_packet, + pending_packet, + on, + off, + get_value, + set_value, + get_object, + set_object, +}; +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(cc26xx_rf_process, ev, data) +{ + int len; + + PROCESS_BEGIN(); + + while(1) { + PROCESS_WAIT_EVENT(); + do { + packetbuf_clear(); + len = read_frame(packetbuf_dataptr(), PACKETBUF_SIZE); + + if(len > 0) { + packetbuf_set_datalen(len); + + NETSTACK_RDC.input(); + } + } while(len > 0); + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +#if CC26XX_RF_BLE_SUPPORT +/*---------------------------------------------------------------------------*/ +/** + * \brief Builds common radio parameters for radio operations + * + * \param *cmd Pointer to buffer to add parameters to + * \param command Radio command number (e.g. COMMAND_RADIO_SETUP) + * + * \note The buffer must be emptied with memset() before calling this function + * + * \return None + */ +static void +rf_build_ble_radio_op_cmd(uint8_t *cmd, uint16_t command) +{ + GET_FIELD(cmd, radioOp, commandNo) = command; + GET_FIELD(cmd, radioOp, status) = IDLE; + GET_FIELD(cmd, radioOp, pNextOp) = NULL; + GET_FIELD(cmd, radioOp, startTime) = 0; + GET_FIELD(cmd, radioOp, startTrigger) = TRIG_NOW; + GET_FIELD(cmd, radioOp, condition) = COND_NEVER; +} +/*---------------------------------------------------------------------------*/ +static void +init_ble() +{ + ble_mode_on = 0; + + memset(beacond_config.adv_name, 0, BLE_ADV_NAME_BUF_LEN); + beacond_config.interval = BLE_ADV_INTERVAL; +} +/*---------------------------------------------------------------------------*/ +static int +send_ble_adv_nc(int channel, uint8_t *output, uint8_t *adv_payload, + int adv_payload_len, uint16_t *dev_address) +{ + uint32_t cmd_status; + int ret; + + /* Erase ble_tx_rx_buf array */ + memset(ble_tx_rx_buf, 0x00, SIZEOF_RADIO_OP(CMD_BLE_ADV_NC)); + rf_build_ble_radio_op_cmd(ble_tx_rx_buf, CMD_BLE_ADV_NC); + + GET_FIELD(ble_tx_rx_buf, bleRadioOp, channel) = channel; + GET_FIELD(ble_tx_rx_buf, bleRadioOp, whitening) = 0; + + memset(ble_cmd_buf, 0x00, SIZEOF_STRUCT(bleAdvPar)); + GET_FIELD(ble_tx_rx_buf, bleRadioOp, pParams) = (uint8_t *)ble_cmd_buf; + GET_FIELD(ble_tx_rx_buf, bleRadioOp, pOutput) = output; + + /* Set up BLE Advertisement parameters */ + GET_FIELD(ble_cmd_buf, bleAdvPar, pRxQ) = NULL; + GET_FIELD(ble_cmd_buf, bleAdvPar, rxConfig) = 0; + GET_FIELD(ble_cmd_buf, bleAdvPar, advConfig) = 0; + GET_FIELD(ble_cmd_buf, bleAdvPar, advLen) = adv_payload_len; + GET_FIELD(ble_cmd_buf, bleAdvPar, scanRspLen) = 0; + GET_FIELD(ble_cmd_buf, bleAdvPar, pAdvData) = adv_payload; + GET_FIELD(ble_cmd_buf, bleAdvPar, pScanRspData) = NULL; + GET_FIELD(ble_cmd_buf, bleAdvPar, pDeviceAddress) = dev_address; + GET_FIELD(ble_cmd_buf, bleAdvPar, pWhiteList) = NULL; + GET_FIELD(ble_cmd_buf, bleAdvPar, endTrigger) = TRIG_NEVER; + GET_FIELD(ble_cmd_buf, bleAdvPar, endTime) = TRIG_NEVER; + + if(rf_send_cmd((uint32_t)ble_tx_rx_buf, &cmd_status) == RF_CMD_ERROR) { + PRINTF("send_ble_adv_nc: Chan=%d CMDSTA=0x%08lx, status=0x%04x\n", + channel, cmd_status, RF_RADIO_OP_GET_STATUS(ble_tx_rx_buf)); + return RF_CMD_ERROR; + } + + /* Wait for the ADV_NC to go out */ + while((RF_RADIO_OP_GET_STATUS(ble_tx_rx_buf) & RF_RADIO_OP_MASKED_STATUS) + == RF_RADIO_OP_MASKED_STATUS_RUNNING); + + if(RF_RADIO_OP_GET_STATUS(ble_tx_rx_buf) == RF_RADIO_OP_STATUS_BLE_DONE_OK) { + /* Sent OK */ + ret = RF_CMD_OK; + } else { + /* Radio Op completed, but ADV NC was not sent */ + PRINTF("send_ble_adv_nc: Chan=%d CMDSTA=0x%08lx, status=0x%04x\n", + channel, cmd_status, RF_RADIO_OP_GET_STATUS(ble_tx_rx_buf)); + ret = RF_CMD_ERROR; + } + + return ret; +} +/*---------------------------------------------------------------------------*/ +static int +send_ble_adv(int channel, uint8_t *adv_payload, int adv_payload_len) +{ + if(send_ble_adv_nc(channel, rf_stats, adv_payload, adv_payload_len, + (uint16_t *)&linkaddr_node_addr.u8[2]) != RF_CMD_OK) { + PRINTF("send_ble_adv: Channel=%d, Error advertising\n", channel); + /* Break the loop, but don't return just yet */ + return RF_CMD_ERROR; + } + + return RF_CMD_OK; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(cc26xx_rf_ble_beacon_process, ev, data) +{ + static struct etimer ble_adv_et; + static uint8_t payload[BLE_ADV_PAYLOAD_BUF_LEN]; + static int p = 0; + static int i; + uint8_t was_on; + int j; + uint32_t cmd_status; + + PROCESS_BEGIN(); + + while(1) { + etimer_set(&ble_adv_et, beacond_config.interval); + + PROCESS_WAIT_EVENT(); + + if(ev == PROCESS_EVENT_EXIT) { + PROCESS_EXIT(); + } + + /* Set the adv payload each pass: The device name may have changed */ + p = 0; + + /* device info */ + payload[p++] = 0x02; /* 2 bytes */ + payload[p++] = BLE_ADV_TYPE_DEVINFO; + payload[p++] = 0x1a; /* LE general discoverable + BR/EDR */ + payload[p++] = 1 + strlen(beacond_config.adv_name); + payload[p++] = BLE_ADV_TYPE_NAME; + memcpy(&payload[p], beacond_config.adv_name, + strlen(beacond_config.adv_name)); + p += strlen(beacond_config.adv_name); + + for(i = 0; i < BLE_ADV_MESSAGES; i++) { + /* + * 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(); + ble_mode_on = 1; + ti_lib_int_master_enable(); + + /* + * Send BLE_ADV_MESSAGES beacon bursts. Each burst on all three + * channels, with a BLE_ADV_DUTY_CYCLE interval between bursts + * + * First, determine our state: + * + * If we are running NullRDC, we are likely in IEEE RX mode. We need to + * abort the IEEE BG Op before entering BLE mode. + * If we are ContikiMAC, we are likely off, in which case we need to + * boot the CPE before entering BLE mode + */ + was_on = rf_is_accessible(); + + if(was_on) { + /* + * We were on: If we are in the process of receiving an IEEE frame, + * abort the BLE beacon burst. Otherwise, terminate the IEEE BG Op + * so we can switch to BLE mode + */ + if(receiving_packet()) { + PRINTF("cc26xx_rf_ble_beacon_process: We were receiving\n"); + + /* Abort this pass */ + break; + } + + if(rx_off() != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: rx_off() failed\n"); + + /* Abort this pass */ + break; + } + } else { + /* Request the HF XOSC to source the HF clock. */ + request_hf_xosc(); + + /* We were off: Boot the CPE */ + if(power_up() != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: power_up() failed\n"); + + /* Abort this pass */ + break; + } + + if(apply_patches() != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: apply_patches() failed\n"); + + /* Abort this pass */ + break; + } + + /* Trigger a switch to the XOSC, so that we can use the FS */ + switch_to_hf_xosc(); + } + + /* Enter BLE mode */ + if(rf_radio_setup(RF_MODE_BLE) != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: Error entering BLE mode\n"); + /* Continue so we can at least try to restore our previous state */ + } else { + /* Send advertising packets on all 3 advertising channels */ + for(j = 37; j <= 39; j++) { + if(send_ble_adv(j, payload, p) != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: Channel=%d," + "Error advertising\n", j); + /* Break the loop, but don't return just yet */ + break; + } + } + } + + /* Send a CMD_STOP command to RF Core */ + if(rf_send_cmd(CMDR_DIR_CMD(CMD_STOP), &cmd_status) != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: status=0x%08lx\n", cmd_status); + /* Continue... */ + } + + if(was_on) { + /* We were on, go back to IEEE mode */ + if(rf_radio_setup(RF_MODE_IEEE) != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: radio_setup() failed\n"); + } + + /* Enter IEEE RX mode */ + if(rx_on() != RF_CMD_OK) { + PRINTF("cc26xx_rf_ble_beacon_process: rx_on() failed\n"); + } + } else { + power_down(); + + /* Switch HF clock source to the RCOSC to preserve power */ + switch_to_hf_rc_osc(); + } + etimer_set(&ble_adv_et, BLE_ADV_DUTY_CYCLE); + + ti_lib_int_master_disable(); + ble_mode_on = 0; + ti_lib_int_master_enable(); + + /* Wait unless this is the last burst */ + if(i < BLE_ADV_MESSAGES - 1) { + PROCESS_WAIT_EVENT(); + } + } + + ti_lib_int_master_disable(); + ble_mode_on = 0; + ti_lib_int_master_enable(); + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +#endif /* CC26XX_RF_BLE_SUPPORT */ +/*---------------------------------------------------------------------------*/ +void +cc26xx_rf_ble_beacond_config(clock_time_t interval, const char *name) +{ +#if CC26XX_RF_BLE_SUPPORT + if(name != NULL) { + memset(beacond_config.adv_name, 0, BLE_ADV_NAME_BUF_LEN); + + if(strlen(name) == 0 || strlen(name) >= BLE_ADV_NAME_BUF_LEN) { + return; + } + + memcpy(beacond_config.adv_name, name, strlen(name)); + } + + if(interval != 0) { + beacond_config.interval = interval; + } +#endif +} +/*---------------------------------------------------------------------------*/ +uint8_t +cc26xx_rf_ble_beacond_start() +{ +#if CC26XX_RF_BLE_SUPPORT + if(beacond_config.adv_name[0] == 0) { + return RF_CMD_ERROR; + } + + process_start(&cc26xx_rf_ble_beacon_process, NULL); + + return RF_CMD_OK; +#else + return RF_CMD_ERROR; +#endif +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_rf_ble_beacond_stop() +{ +#if CC26XX_RF_BLE_SUPPORT + process_exit(&cc26xx_rf_ble_beacon_process); +#endif +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc26xx/dev/cc26xx-rf.h b/cpu/cc26xx/dev/cc26xx-rf.h new file mode 100644 index 000000000..4087a037d --- /dev/null +++ b/cpu/cc26xx/dev/cc26xx-rf.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. + */ +/** + * \addtogroup cc26xx + * @{ + * + * \defgroup cc26xx-rf CC26xx RF driver + * + * The CC26xx RF has dual capability: It can operate in IEEE 802.15.4 mode at + * 2.4GHz, but it can also operate in BLE mode. This driver provides a fully + * contiki-compliant .15.4 functionality, but it also provides some very basic + * BLE capability. + * + * @{ + */ +/** + * \file + * Header file for the CC26xx RF driver + */ +#ifndef CC26XX_RF_H_ +#define CC26XX_RF_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "cc26xx-model.h" +#include "dev/radio.h" +/*---------------------------------------------------------------------------*/ +#include +/*---------------------------------------------------------------------------*/ +#ifdef CC26XX_RF_CONF_CHANNEL +#define CC26XX_RF_CHANNEL CC26XX_RF_CONF_CHANNEL +#else +#define CC26XX_RF_CHANNEL 18 +#endif /* CC26XX_RF_CONF_CHANNEL */ + +#ifdef CC26XX_RF_CONF_AUTOACK +#define CC26XX_RF_AUTOACK CC26XX_RF_CONF_AUTOACK +#else +#define CC26XX_RF_AUTOACK 1 +#endif /* CC26XX_RF_CONF_AUTOACK */ + +#if defined (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 +#endif +/*--------------------------------------------------------------------------- + * RF Config + *---------------------------------------------------------------------------*/ +/* Constants */ +#define CC26XX_RF_CHANNEL_MIN 11 +#define CC26XX_RF_CHANNEL_MAX 26 +#define CC26XX_RF_CHANNEL_SPACING 5 +#define CC26XX_RF_CHANNEL_SET_ERROR -1 +#define CC26XX_RF_MAX_PACKET_LEN 127 +#define CC26XX_RF_MIN_PACKET_LEN 4 +/*---------------------------------------------------------------------------*/ +/** + * \brief Set the device name to use with the BLE advertisement/beacon daemon + * \param interval The interval (ticks) between two consecutive beacon bursts + * \param name The device name to advertise + * + * If name is NULL it will be ignored. If interval==0 it will be ignored. Thus, + * this function can be used to configure a single parameter at a time if so + * desired. + */ +void cc26xx_rf_ble_beacond_config(clock_time_t interval, const char *name); + +/** + * \brief Start the BLE advertisement/beacon daemon + * \return 1: Success, 0: Failure + * + * Before calling this function, the name to advertise must first be set by + * calling cc26xx_rf_ble_beacond_set_adv_name(). Otherwise, this function will + * return an error. + */ +uint8_t cc26xx_rf_ble_beacond_start(void); + +/** + * \brief Stop the BLE advertisement/beacon daemon + */ +void cc26xx_rf_ble_beacond_stop(void); +/*---------------------------------------------------------------------------*/ +#endif /* CC26XX_RF_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/dev/cc26xx-rtc.c b/cpu/cc26xx/dev/cc26xx-rtc.c new file mode 100644 index 000000000..b06aebd22 --- /dev/null +++ b/cpu/cc26xx/dev/cc26xx-rtc.c @@ -0,0 +1,127 @@ +/* + * 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 cc26xx-rtc + * @{ + * + */ +/** + * \file + * Implementation of the CC26xx AON RTC driver + */ +#include "contiki.h" +#include "sys/energest.h" +#include "rtimer.h" +#include "lpm.h" + +#include "ti-lib.h" + +#include +/*---------------------------------------------------------------------------*/ +#define cc26xx_rtc_isr(...) AONRTCIntHandler(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* Prototype of a function in clock.c. Called every time the handler fires */ +void clock_update(void); +/*---------------------------------------------------------------------------*/ +void +cc26xx_rtc_init(void) +{ + uint32_t compare_value; + + /* Disable and clear interrupts */ + ti_lib_int_master_disable(); + ti_lib_aon_rtc_disable(); + + ti_lib_aon_rtc_event_clear(AON_RTC_CH0); + ti_lib_aon_rtc_event_clear(AON_RTC_CH2); + + /* Setup the wakeup event */ + ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU0, AON_EVENT_RTC0); + ti_lib_aon_event_mcu_wake_up_set(AON_EVENT_MCU_WU1, AON_EVENT_RTC2); + + /* Configure channel 2 in continuous compare, 128 ticks / sec */ + 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); + 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(); +} +/*---------------------------------------------------------------------------*/ +rtimer_clock_t +cc26xx_rtc_get_next_trigger() +{ + rtimer_clock_t ch2 = ti_lib_aon_rtc_compare_value_get(AON_RTC_CH2); + + 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 ch2; +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_rtc_schedule_one_shot(uint32_t ticks) +{ + /* Set the channel to fire a one-shot compare event at time==ticks */ + ti_lib_aon_rtc_compare_value_set(AON_RTC_CH0, ticks); + ti_lib_aon_rtc_channel_enable(AON_RTC_CH0); +} +/*---------------------------------------------------------------------------*/ +/* The AON RTC interrupt handler */ +void +cc26xx_rtc_isr(void) +{ + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + if(ti_lib_aon_rtc_event_get(AON_RTC_CH0)) { + ti_lib_aon_rtc_event_clear(AON_RTC_CH0); + rtimer_run_next(); + } + + if(ti_lib_aon_rtc_event_get(AON_RTC_CH2)) { + ti_lib_aon_rtc_event_clear(AON_RTC_CH2); + clock_update(); + } + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc26xx/dev/cc26xx-rtc.h b/cpu/cc26xx/dev/cc26xx-rtc.h new file mode 100644 index 000000000..4fbaa1795 --- /dev/null +++ b/cpu/cc26xx/dev/cc26xx-rtc.h @@ -0,0 +1,100 @@ +/* + * 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 cc26xx + * @{ + * + * \defgroup cc26xx-clocks CC26xx clock and timer subsystem + * + * For the CC26xx cpu we use the AON RTC as the basis for all clocks and timers + * + * We configure the AON RTC's channel 2 to run in continuous mode, generating + * 128 interrupts / second. In continuous mode, the next compare event is + * scheduled by the hardware automatically; the events are equidistant and + * this also means we don't need the overhead of re-scheduling within the + * interrupt handler + * + * For rtimers, we use the RTC's channel 0 in one-shot compare mode. When the + * compare event fires, we call rtimer_run_next + * + * The RTC runs in all power modes except 'shutdown' + * + * \sa cpu/cc26xx/clock.c cpu/cc26xx/rtimer-arch.c + * @{ + * + * \defgroup cc26xx-rtc CC26xx AON RTC driver + * + * Underpins the platform's software clocks and timers + * + * @{ + * \file + * Header file for the CC26XX AON RTC driver + */ +#ifndef CC26XX_RTC_H_ +#define CC26XX_RTC_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" + +#include "rtimer.h" + +#include +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise the CC26XX AON RTC module + * + * This timer configures the AON RTC's channel 2 to run in continuous mode + * This function must be called before clock_init() and rtimer_init() + */ +void cc26xx_rtc_init(void); + +/** + * \brief Return the time of the next scheduled rtimer event + * \return The time at which the next rtimer event is due to fire + * + * This function will check both AON RTC channels and will only take CH0's + * compare into account if the channel is actually enabled + */ +rtimer_clock_t cc26xx_rtc_get_next_trigger(void); + +/** + * \brief Schedule an AON RTC channel 0 one-shot compare event + * \param t The time when the event will be fired. This is an absolute + * time, in other words the event will fire AT time \e t, + * not IN \e t ticks + */ +void cc26xx_rtc_schedule_one_shot(uint32_t t); +/*---------------------------------------------------------------------------*/ +#endif /* CC26XX_RTC_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + * @} + */ diff --git a/cpu/cc26xx/dev/cc26xx-uart.c b/cpu/cc26xx/dev/cc26xx-uart.c new file mode 100644 index 000000000..5a45bb03b --- /dev/null +++ b/cpu/cc26xx/dev/cc26xx-uart.c @@ -0,0 +1,249 @@ +/* + * 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. + */ +#include "contiki-conf.h" +#include "cc26xx-uart.h" +#include "hw_types.h" +#include "hw_memmap.h" +#include "sys_ctrl.h" +#include "prcm.h" +#include "ioc.h" +#include "uart.h" +#include "lpm.h" +#include "ti-lib.h" +#include "sys/energest.h" + +#include +/*---------------------------------------------------------------------------*/ +/* Which events to trigger a UART interrupt */ +#define CC26XX_UART_RX_INTERRUPT_TRIGGERS (UART_INT_RX | UART_INT_RT) + +/* All interrupt masks */ +#define CC26XX_UART_INTERRUPT_ALL (UART_INT_OE | UART_INT_BE | UART_INT_PE | \ + UART_INT_FE | UART_INT_RT | UART_INT_TX | \ + UART_INT_RX | UART_INT_CTS) +/*---------------------------------------------------------------------------*/ +#define cc26xx_uart_isr UART0IntHandler +/*---------------------------------------------------------------------------*/ +static int (*input_handler)(unsigned char c); +/*---------------------------------------------------------------------------*/ +static void +power_domain_on(void) +{ + ti_lib_prcm_power_domain_on(PRCM_DOMAIN_SERIAL); + while(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) + != PRCM_DOMAIN_POWER_ON); +} +/*---------------------------------------------------------------------------*/ +static void +configure_baud_rate(void) +{ + /* + * 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. + */ + 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) +{ + /* + * Map UART signals to the correct GPIO pins and configure them as + * hardware controlled. + */ + 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(); + + /* + * Generate an RX interrupt at FIFO 1/2 full. + * We don't really care about the TX interrupt + */ + 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(); + + /* 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); + } +} +/*---------------------------------------------------------------------------*/ +static uint8_t +lpm_permit_max_pm_handler(void) +{ + return LPM_MODE_MAX_SUPPORTED; +} +/*---------------------------------------------------------------------------*/ +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; + } + + /* 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((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) { + return; + } + + /* Enable the serial domain and wait for domain to be on */ + power_domain_on(); + + /* Enable the UART clock when running and sleeping */ + ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_UART0); + + /* Apply clock settings and wait for them to take effect */ + ti_lib_prcm_load_set(); + while(!ti_lib_prcm_load_get()); + + /* Disable Interrupts */ + ti_lib_int_master_disable(); + + /* 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); + + configure_registers(); + + /* Acknowledge UART interrupts */ + ti_lib_int_enable(INT_UART0); + + /* Re-enable processor interrupts */ + ti_lib_int_master_enable(); + + /* Enable UART */ + ti_lib_uart_enable(UART0_BASE); + + /* Register ourselves with the LPM module */ + lpm_register_module(&uart_module); +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_uart_write_byte(uint8_t c) +{ + if(ti_lib_prcm_power_domain_status(PRCM_DOMAIN_SERIAL) + != PRCM_DOMAIN_POWER_ON) { + return; + } + + ti_lib_uart_char_put(UART0_BASE, c); +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_uart_set_input(int (*input)(unsigned char c)) +{ + input_handler = input; + return; +} +/*---------------------------------------------------------------------------*/ +void +cc26xx_uart_isr(void) +{ + char the_char; + uint32_t flags; + + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + /* Read out the masked interrupt status */ + flags = ti_lib_uart_int_status(UART0_BASE, true); + + /* Clear all UART interrupt flags */ + ti_lib_uart_int_clear(UART0_BASE, CC26XX_UART_INTERRUPT_ALL); + + if((flags & CC26XX_UART_RX_INTERRUPT_TRIGGERS) != 0) { + /* + * If this was a FIFO RX or an RX timeout, read all bytes available in the + * RX FIFO. + */ + while(ti_lib_uart_chars_avail(UART0_BASE)) { + the_char = ti_lib_uart_char_get_non_blocking(UART0_BASE); + + if(input_handler != NULL) { + input_handler((unsigned char)the_char); + } + } + } + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} diff --git a/cpu/cc26xx/dev/cc26xx-uart.h b/cpu/cc26xx/dev/cc26xx-uart.h new file mode 100644 index 000000000..4647b9339 --- /dev/null +++ b/cpu/cc26xx/dev/cc26xx-uart.h @@ -0,0 +1,76 @@ +/* + * 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 cc26xx + * @{ + * + * \defgroup cc26xx-uart CC26xx UARTs + * + * Driver for the CC26xx UART controller + * @{ + * + * \file + * Header file for the CC26xx UART driver + */ +#ifndef CC26XX_UART_H_ +#define CC26XX_UART_H_ + +#include +/*---------------------------------------------------------------------------*/ +/** \name UART functions + * @{ + */ + +/** + * \brief Initialises the UART controller, configures I/O control + * and interrupts + */ +void cc26xx_uart_init(); + +/** + * \brief Sends a single character down the UART + * \param b The character to transmit + */ +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 + */ +void cc26xx_uart_set_input(int (*input)(unsigned char c)); + +/** @} */ +/*---------------------------------------------------------------------------*/ +#endif /* CC26XX_UART_H_ */ + +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/dev/contiki-watchdog.c b/cpu/cc26xx/dev/contiki-watchdog.c new file mode 100644 index 000000000..8241b5045 --- /dev/null +++ b/cpu/cc26xx/dev/contiki-watchdog.c @@ -0,0 +1,99 @@ +/* + * 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 cc26xx-clocks + * @{ + * + * \defgroup cc26xx-wdt CC26xx watchdog timer driver + * + * Driver for the CC26xx Watchdog Timer + * + * This file is not called watchdog.c because the filename is in use by + * TI CC26xxware + * @{ + * + * \file + * Implementation of the cc26xx watchdog driver. + */ +#include "watchdog.h" +#include "ti-lib.h" +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialises the CC26xx WDT + * + * Simply sets the reload counter to a default value. The WDT is not started + * yet. To start it, watchdog_start() must be called. + */ +void +watchdog_init(void) +{ + ti_lib_wathdog_reload_set(0xFFFFF); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Starts the CC26xx WDT + */ +void +watchdog_start(void) +{ + ti_lib_wathdog_reset_enable(); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Refreshes the CC26xx WDT + */ +void +watchdog_periodic(void) +{ + ti_lib_wathdog_int_clear(); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Stub function to satisfy API requirements + */ +void +watchdog_stop(void) +{ +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Manually trigger a WDT reboot + */ +void +watchdog_reboot(void) +{ + watchdog_start(); + while(1); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/dev/gpio-interrupt.c b/cpu/cc26xx/dev/gpio-interrupt.c new file mode 100644 index 000000000..a2c6dd42b --- /dev/null +++ b/cpu/cc26xx/dev/gpio-interrupt.c @@ -0,0 +1,97 @@ +/* + * 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. + */ +/*---------------------------------------------------------------------------*/ +#include "ioc.h" +#include "gpio-interrupt.h" +#include "sys/energest.h" +#include "lpm.h" +#include "ti-lib.h" + +#include +/*---------------------------------------------------------------------------*/ +#define gpio_interrupt_isr GPIOIntHandler +/*---------------------------------------------------------------------------*/ +/* Handler array */ +static gpio_interrupt_handler_t handlers[NUM_IO_MAX]; +/*---------------------------------------------------------------------------*/ +void +gpio_interrupt_register_handler(uint8_t ioid, gpio_interrupt_handler_t f) +{ + uint8_t interrupts_disabled = ti_lib_int_master_disable(); + + /* Clear interrupts on specified pins */ + ti_lib_gpio_event_clear(1 << ioid); + + handlers[ioid] = f; + + /* Re-enable interrupts */ + if(!interrupts_disabled) { + ti_lib_int_master_enable(); + } +} +/*---------------------------------------------------------------------------*/ +void +gpio_interrupt_init() +{ + int i; + + for(i = 0; i < NUM_IO_MAX; i++) { + handlers[i] = NULL; + } + + ti_lib_int_enable(INT_EDGE_DETECT); +} +/*---------------------------------------------------------------------------*/ +void +gpio_interrupt_isr(void) +{ + uint32_t pin_mask; + uint8_t i; + + ENERGEST_ON(ENERGEST_TYPE_IRQ); + + /* Read interrupt flags */ + pin_mask = (HWREG(GPIO_BASE + GPIO_O_EVFLAGS31_0) & GPIO_PIN_MASK); + + /* Clear the interrupt flags */ + HWREG(GPIO_BASE + GPIO_O_EVFLAGS31_0) = pin_mask; + + /* Run custom ISRs */ + for(i = 0; i < NUM_GPIO_PINS; i++) { + /* Call the handler if there is one registered for this event */ + if((pin_mask & (1 << i)) && handlers[i] != NULL) { + handlers[i](i); + } + } + + ENERGEST_OFF(ENERGEST_TYPE_IRQ); +} +/*---------------------------------------------------------------------------*/ + diff --git a/cpu/cc26xx/dev/gpio-interrupt.h b/cpu/cc26xx/dev/gpio-interrupt.h new file mode 100644 index 000000000..6a64f26f6 --- /dev/null +++ b/cpu/cc26xx/dev/gpio-interrupt.h @@ -0,0 +1,71 @@ +/* + * 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 cc26xx + * @{ + * + * \defgroup cc26xx-gpio-interrupts CC26xx GPIO interrupt handling + * + * The CC26xx GPIO interrupt handler and an API which can be used by other + * parts of the code when they wish to be notified of a GPIO interrupt + * + * @{ + * + * \file + * Header file for the CC26xx GPIO interrupt management + */ +/*---------------------------------------------------------------------------*/ +#ifndef GPIO_INTERRUPT_H_ +#define GPIO_INTERRUPT_H_ +/*---------------------------------------------------------------------------*/ +#include +/*---------------------------------------------------------------------------*/ +typedef void (*gpio_interrupt_handler_t)(uint8_t ioid); +/*---------------------------------------------------------------------------*/ +/** \brief Initialise the GPIO interrupt handling module */ +void gpio_interrupt_init(void); + +/** + * \brief Register a GPIO interrupt handler + * \param f Pointer to a handler to be called when an interrupt is raised on + * ioid + * \param ioid Associate \a f with this ioid. \e ioid must be specified with + * its numeric representation (0, 1, .. 31). Defines for these + * numeric representations are IOID_x + */ +void gpio_interrupt_register_handler(uint8_t ioid, gpio_interrupt_handler_t f); + +#endif /* GPIO_INTERRUPT_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/dev/rfc-api/ble_cmd.h b/cpu/cc26xx/dev/rfc-api/ble_cmd.h new file mode 100644 index 000000000..f7320fe4d --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/ble_cmd.h @@ -0,0 +1,1082 @@ +/****************************************************************************** +* Filename: ble_cmd.h +* Revised: $ $ +* Revision: $ $ +* +* Description: CC26xx/CC13xx API for Bluetooth Low Energy commands +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef __BLE_CMD_H +#define __BLE_CMD_H + +#ifndef __RFC_STRUCT +#ifdef __GNUC__ +#define __RFC_STRUCT __attribute__ ((aligned (4))) +#else +#define __RFC_STRUCT +#endif +#endif + +//! \addtogroup rfc +//! @{ + +//! \addtogroup ble_cmd +//! @{ + +#include +#include "mailbox.h" +#include "common_cmd.h" + +typedef struct __RFC_STRUCT rfc_bleMasterPar_s rfc_bleMasterPar_t; +typedef struct __RFC_STRUCT rfc_bleMasterSlavePar_s rfc_bleMasterSlavePar_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_INITIATOR_s rfc_CMD_BLE_INITIATOR_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_TX_TEST_s rfc_CMD_BLE_TX_TEST_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_MASTER_s rfc_CMD_BLE_MASTER_t; +typedef struct __RFC_STRUCT rfc_bleWhiteListEntry_s rfc_bleWhiteListEntry_t; +typedef struct __RFC_STRUCT rfc_bleGenericRxPar_s rfc_bleGenericRxPar_t; +typedef struct __RFC_STRUCT rfc_bleTxTestPar_s rfc_bleTxTestPar_t; +typedef struct __RFC_STRUCT rfc_bleInitiatorOutput_s rfc_bleInitiatorOutput_t; +typedef struct __RFC_STRUCT rfc_bleWhiteListEntryWords_s rfc_bleWhiteListEntryWords_t; +typedef struct __RFC_STRUCT rfc_bleMasterSlaveOutput_s rfc_bleMasterSlaveOutput_t; +typedef struct __RFC_STRUCT rfc_bleRxStatus_s rfc_bleRxStatus_t; +typedef struct __RFC_STRUCT rfc_bleRadioOp_s rfc_bleRadioOp_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_ADV_NC_s rfc_CMD_BLE_ADV_NC_t; +typedef struct __RFC_STRUCT rfc_bleTxTestOutput_s rfc_bleTxTestOutput_t; +typedef struct __RFC_STRUCT rfc_bleAdvPar_s rfc_bleAdvPar_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_ADV_SCAN_s rfc_CMD_BLE_ADV_SCAN_t; +typedef struct __RFC_STRUCT rfc_bleAdvOutput_s rfc_bleAdvOutput_t; +typedef struct __RFC_STRUCT rfc_bleScannerOutput_s rfc_bleScannerOutput_t; +typedef struct __RFC_STRUCT rfc_bleSlavePar_s rfc_bleSlavePar_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_ADV_DIR_s rfc_CMD_BLE_ADV_DIR_t; +typedef struct __RFC_STRUCT rfc_bleInitiatorPar_s rfc_bleInitiatorPar_t; +typedef struct __RFC_STRUCT rfc_bleScannerPar_s rfc_bleScannerPar_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_SLAVE_s rfc_CMD_BLE_SLAVE_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_ADV_s rfc_CMD_BLE_ADV_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_SCANNER_s rfc_CMD_BLE_SCANNER_t; +typedef struct __RFC_STRUCT rfc_bleGenericRxOutput_s rfc_bleGenericRxOutput_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_GENERIC_RX_s rfc_CMD_BLE_GENERIC_RX_t; +typedef struct __RFC_STRUCT rfc_CMD_BLE_ADV_PAYLOAD_s rfc_CMD_BLE_ADV_PAYLOAD_t; + +//! \addtogroup bleRadioOp +//! @{ +struct __RFC_STRUCT rfc_bleRadioOp_s { + uint16_t commandNo; //!< The command ID number + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + uint8_t* pParams; //!< Pointer to command specific parameter structure + uint8_t* pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_SLAVE +//! @{ +#define CMD_BLE_SLAVE 0x1801 +struct __RFC_STRUCT rfc_CMD_BLE_SLAVE_s { + uint16_t commandNo; //!< The command ID number 0x1801 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleSlavePar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleMasterSlaveOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_MASTER +//! @{ +#define CMD_BLE_MASTER 0x1802 +struct __RFC_STRUCT rfc_CMD_BLE_MASTER_s { + uint16_t commandNo; //!< The command ID number 0x1802 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleMasterPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleMasterSlaveOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_ADV +//! @{ +#define CMD_BLE_ADV 0x1803 +struct __RFC_STRUCT rfc_CMD_BLE_ADV_s { + uint16_t commandNo; //!< The command ID number 0x1803 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleAdvPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleAdvOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_ADV_DIR +//! @{ +#define CMD_BLE_ADV_DIR 0x1804 +struct __RFC_STRUCT rfc_CMD_BLE_ADV_DIR_s { + uint16_t commandNo; //!< The command ID number 0x1804 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleAdvPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleAdvOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_ADV_NC +//! @{ +#define CMD_BLE_ADV_NC 0x1805 +struct __RFC_STRUCT rfc_CMD_BLE_ADV_NC_s { + uint16_t commandNo; //!< The command ID number 0x1805 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleAdvPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleAdvOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_ADV_SCAN +//! @{ +#define CMD_BLE_ADV_SCAN 0x1806 +struct __RFC_STRUCT rfc_CMD_BLE_ADV_SCAN_s { + uint16_t commandNo; //!< The command ID number 0x1806 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleAdvPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleAdvOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_SCANNER +//! @{ +#define CMD_BLE_SCANNER 0x1807 +struct __RFC_STRUCT rfc_CMD_BLE_SCANNER_s { + uint16_t commandNo; //!< The command ID number 0x1807 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleScannerPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleScannerOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_INITIATOR +//! @{ +#define CMD_BLE_INITIATOR 0x1808 +struct __RFC_STRUCT rfc_CMD_BLE_INITIATOR_s { + uint16_t commandNo; //!< The command ID number 0x1808 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleInitiatorPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleInitiatorOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_GENERIC_RX +//! @{ +#define CMD_BLE_GENERIC_RX 0x1809 +struct __RFC_STRUCT rfc_CMD_BLE_GENERIC_RX_s { + uint16_t commandNo; //!< The command ID number 0x1809 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleGenericRxPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleGenericRxOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_TX_TEST +//! @{ +#define CMD_BLE_TX_TEST 0x180A +struct __RFC_STRUCT rfc_CMD_BLE_TX_TEST_s { + uint16_t commandNo; //!< The command ID number 0x180A + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to use
+ //!< 0–39: BLE advertising/data channel number + //!< 60–207: Custom frequency; (2300 + channel) MHz + //!< 255: Use existing frequency + //!< Others: Reserved + struct { + uint8_t init:7; //!< \brief If bOverride = 1 or custom frequency is used:
+ //!< 0: Do not use whitening
+ //!< Other value: Initialization for 7-bit LFSR whitener + uint8_t bOverride:1; //!< \brief 0: Use default whitening for BLE advertising/data channels
+ //!< 1: Override whitening initialization with value of init + } whitening; + rfc_bleTxTestPar_t *pParams; //!< Pointer to command specific parameter structure + rfc_bleTxTestOutput_t *pOutput; //!< Pointer to command specific output structure +}; + +//! @} + +//! \addtogroup CMD_BLE_ADV_PAYLOAD +//! @{ +#define CMD_BLE_ADV_PAYLOAD 0x1001 +struct __RFC_STRUCT rfc_CMD_BLE_ADV_PAYLOAD_s { + uint16_t commandNo; //!< The command ID number 0x1001 + uint8_t payloadType; //!< \brief 0: Advertising data
+ //!< 1: Scan response data + uint8_t newLen; //!< Length of the new payload + uint8_t* pNewData; //!< Pointer to the buffer containing the new data + rfc_bleAdvPar_t *pParams; //!< Pointer to the parameter structure to update +}; + +//! @} + +//! \addtogroup bleMasterSlavePar +//! @{ +struct __RFC_STRUCT rfc_bleMasterSlavePar_s { + dataQueue_t* pRxQ; //!< Pointer to receive queue + dataQueue_t* pTxQ; //!< Pointer to transmit queue + struct { + uint8_t bAutoFlushIgnored:1; //!< If 1, automatically remove ignored packets from Rx queue + uint8_t bAutoFlushCrcErr:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushEmpty:1; //!< If 1, automatically remove empty packets from Rx queue + uint8_t bIncludeLenByte:1; //!< If 1, include the received length byte in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendStatus:1; //!< If 1, append a status byte to the packet in the Rx queue + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; //!< Configuration bits for the receive queue entries + struct { + uint8_t lastRxSn:1; //!< The SN bit of the header of the last packet received with CRC OK + uint8_t lastTxSn:1; //!< The SN bit of the header of the last transmitted packet + uint8_t nextTxSn:1; //!< The SN bit of the header of the next packet to transmit + uint8_t bFirstPkt:1; //!< For slave: 0 if a packet has been transmitted on the connection, 1 otherwise + uint8_t bAutoEmpty:1; //!< 1 if the last transmitted packet was an auto-empty packet + uint8_t bLlCtrlTx:1; //!< 1 if the last transmitted packet was an LL control packet (LLID = 11) + uint8_t bLlCtrlAckRx:1; //!< 1 if the last received packet was the ACK of an LL control packet + uint8_t bLlCtrlAckPending:1; //!< 1 if the last successfully received packet was an LL control packet which has not yet been ACK'ed + } seqStat; + uint8_t maxNack; //!< Maximum number of NACKs received before operation ends. 0: No limit + uint8_t maxPkt; //!< Maximum number of packets transmitted in the operation before it ends. 0: No limit + uint32_t accessAddress; //!< Access address used on the connection + uint8_t crcInit0; //!< CRC initialization value used on the connection – least significant byte + uint8_t crcInit1; //!< CRC initialization value used on the connection – middle byte + uint8_t crcInit2; //!< CRC initialization value used on the connection – most significant byte +}; + +//! @} + +//! \addtogroup bleMasterPar +//! @{ +//! Parameter structure for master (CMD_BLE_MASTER) + +struct __RFC_STRUCT rfc_bleMasterPar_s { + dataQueue_t* pRxQ; //!< Pointer to receive queue + dataQueue_t* pTxQ; //!< Pointer to transmit queue + struct { + uint8_t bAutoFlushIgnored:1; //!< If 1, automatically remove ignored packets from Rx queue + uint8_t bAutoFlushCrcErr:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushEmpty:1; //!< If 1, automatically remove empty packets from Rx queue + uint8_t bIncludeLenByte:1; //!< If 1, include the received length byte in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendStatus:1; //!< If 1, append a status byte to the packet in the Rx queue + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; //!< Configuration bits for the receive queue entries + struct { + uint8_t lastRxSn:1; //!< The SN bit of the header of the last packet received with CRC OK + uint8_t lastTxSn:1; //!< The SN bit of the header of the last transmitted packet + uint8_t nextTxSn:1; //!< The SN bit of the header of the next packet to transmit + uint8_t bFirstPkt:1; //!< For slave: 0 if a packet has been transmitted on the connection, 1 otherwise + uint8_t bAutoEmpty:1; //!< 1 if the last transmitted packet was an auto-empty packet + uint8_t bLlCtrlTx:1; //!< 1 if the last transmitted packet was an LL control packet (LLID = 11) + uint8_t bLlCtrlAckRx:1; //!< 1 if the last received packet was the ACK of an LL control packet + uint8_t bLlCtrlAckPending:1; //!< 1 if the last successfully received packet was an LL control packet which has not yet been ACK'ed + } seqStat; + uint8_t maxNack; //!< Maximum number of NACKs received before operation ends. 0: No limit + uint8_t maxPkt; //!< Maximum number of packets transmitted in the operation before it ends. 0: No limit + uint32_t accessAddress; //!< Access address used on the connection + uint8_t crcInit0; //!< CRC initialization value used on the connection – least significant byte + uint8_t crcInit1; //!< CRC initialization value used on the connection – middle byte + uint8_t crcInit2; //!< CRC initialization value used on the connection – most significant byte + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the connection event as soon as allowed + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the + //!< connection event as soon as allowed +}; + +//! @} + +//! \addtogroup bleSlavePar +//! @{ +//! Parameter structure for slave (CMD_BLE_SLAVE) + +struct __RFC_STRUCT rfc_bleSlavePar_s { + dataQueue_t* pRxQ; //!< Pointer to receive queue + dataQueue_t* pTxQ; //!< Pointer to transmit queue + struct { + uint8_t bAutoFlushIgnored:1; //!< If 1, automatically remove ignored packets from Rx queue + uint8_t bAutoFlushCrcErr:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushEmpty:1; //!< If 1, automatically remove empty packets from Rx queue + uint8_t bIncludeLenByte:1; //!< If 1, include the received length byte in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendStatus:1; //!< If 1, append a status byte to the packet in the Rx queue + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; //!< Configuration bits for the receive queue entries + struct { + uint8_t lastRxSn:1; //!< The SN bit of the header of the last packet received with CRC OK + uint8_t lastTxSn:1; //!< The SN bit of the header of the last transmitted packet + uint8_t nextTxSn:1; //!< The SN bit of the header of the next packet to transmit + uint8_t bFirstPkt:1; //!< For slave: 0 if a packet has been transmitted on the connection, 1 otherwise + uint8_t bAutoEmpty:1; //!< 1 if the last transmitted packet was an auto-empty packet + uint8_t bLlCtrlTx:1; //!< 1 if the last transmitted packet was an LL control packet (LLID = 11) + uint8_t bLlCtrlAckRx:1; //!< 1 if the last received packet was the ACK of an LL control packet + uint8_t bLlCtrlAckPending:1; //!< 1 if the last successfully received packet was an LL control packet which has not yet been ACK'ed + } seqStat; + uint8_t maxNack; //!< Maximum number of NACKs received before operation ends. 0: No limit + uint8_t maxPkt; //!< Maximum number of packets transmitted in the operation before it ends. 0: No limit + uint32_t accessAddress; //!< Access address used on the connection + uint8_t crcInit0; //!< CRC initialization value used on the connection – least significant byte + uint8_t crcInit1; //!< CRC initialization value used on the connection – middle byte + uint8_t crcInit2; //!< CRC initialization value used on the connection – most significant byte + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } timeoutTrigger; //!< Trigger that defines timeout of the first receive operation + ratmr_t timeoutTime; //!< \brief Time used together with timeoutTrigger that defines timeout of the first + //!< receive operation + uint16_t __dummy0; + uint8_t __dummy1; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the connection event as soon as allowed + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the + //!< connection event as soon as allowed +}; + +//! @} + +//! \addtogroup bleAdvPar +//! @{ +//! Parameter structure for advertiser (CMD_BLE_ADV*) + +struct __RFC_STRUCT rfc_bleAdvPar_s { + dataQueue_t* pRxQ; //!< Pointer to receive queue + struct { + uint8_t bAutoFlushIgnored:1; //!< If 1, automatically remove ignored packets from Rx queue + uint8_t bAutoFlushCrcErr:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushEmpty:1; //!< If 1, automatically remove empty packets from Rx queue + uint8_t bIncludeLenByte:1; //!< If 1, include the received length byte in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendStatus:1; //!< If 1, append a status byte to the packet in the Rx queue + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; //!< Configuration bits for the receive queue entries + struct { + uint8_t advFilterPolicy:2; //!< \brief The advertiser filter policy, as defined in Volume 2, Part E, Section 7.8.5 of + //!< the Bluetooth 4.0 spec + uint8_t deviceAddrType:1; //!< The type of the device address – public (0) or random (1) + uint8_t peerAddrType:1; //!< Directed advertiser: The type of the peer address – public (0) or random (1) + uint8_t bStrictLenFilter:1; //!< 1: Discard messages with illegal length + } advConfig; + uint8_t advLen; //!< Size of advertiser data + uint8_t scanRspLen; //!< Size of scan response data + uint8_t* pAdvData; //!< Pointer to buffer containing ADV*_IND data + uint8_t* pScanRspData; //!< Pointer to buffer containing SCAN_RSP data + uint16_t* pDeviceAddress; //!< Pointer to device address used for this device + rfc_bleWhiteListEntry_t *pWhiteList; //!< Pointer to white list or peer address (directed advertiser) + uint16_t __dummy0; + uint8_t __dummy1; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the advertiser event as soon as allowed + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the + //!< advertiser event as soon as allowed +}; + +//! @} + +//! \addtogroup bleScannerPar +//! @{ +//! Parameter structure for scanner (CMD_BLE_SCANNER) + +struct __RFC_STRUCT rfc_bleScannerPar_s { + dataQueue_t* pRxQ; //!< Pointer to receive queue + struct { + uint8_t bAutoFlushIgnored:1; //!< If 1, automatically remove ignored packets from Rx queue + uint8_t bAutoFlushCrcErr:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushEmpty:1; //!< If 1, automatically remove empty packets from Rx queue + uint8_t bIncludeLenByte:1; //!< If 1, include the received length byte in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendStatus:1; //!< If 1, append a status byte to the packet in the Rx queue + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; //!< Configuration bits for the receive queue entries + struct { + uint8_t scanFilterPolicy:1; //!< \brief The advertiser filter policy, as defined in Volume 2, Part E, Section 7.8.10 of + //!< the Bluetooth 4.0 spec + uint8_t bActiveScan:1; //!< \brief 0: Passive scan
+ //!< 1: Active scan + uint8_t deviceAddrType:1; //!< The type of the device address – public (0) or random (1) + uint8_t :1; + uint8_t bStrictLenFilter:1; //!< 1: Discard messages with illegal length + uint8_t bAutoWlIgnore:1; //!< 1: Automatically set ignore bit in white list + uint8_t bEndOnRpt:1; //!< 1: End scanner operation after each reported ADV*_IND and potentially SCAN_RSP + } scanConfig; + uint16_t randomState; //!< State for pseudo-random number generation used in backoff procedure + uint16_t backoffCount; //!< Parameter backoffCount used in backoff procedure, cf. Bluetooth 4.0 spec + struct { + uint8_t logUpperLimit:4; //!< Binary logarithm of parameter upperLimit used in scanner backoff procedure + uint8_t bLastSucceeded:1; //!< \brief 1 if the last SCAN_RSP was successfully received and upperLimit + //!< not changed + uint8_t bLastFailed:1; //!< \brief 1 if reception of the last SCAN_RSP failed and upperLimit was not + //!< changed + } backoffPar; + uint8_t scanReqLen; //!< Size of scan request data + uint8_t* pScanReqData; //!< Pointer to buffer containing SCAN_REQ data + uint16_t* pDeviceAddress; //!< Pointer to device address used for this device + rfc_bleWhiteListEntry_t *pWhiteList; //!< Pointer to white list + uint16_t __dummy0; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } timeoutTrigger; //!< Trigger that causes the device to stop receiving as soon as allowed + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to stop receiving as soon as allowed + ratmr_t timeoutTime; //!< \brief Time used together with timeoutTrigger that causes the device to stop + //!< receiving as soon as allowed, ending with BLE_DONE_RXTIMEOUT + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to stop + //!< receiving as soon as allowed, ending with BLE_DONE_ENDED +}; + +//! @} + +//! \addtogroup bleInitiatorPar +//! @{ +//! Parameter structure for initiator (CMD_BLE_INITIATOR) + +struct __RFC_STRUCT rfc_bleInitiatorPar_s { + dataQueue_t* pRxQ; //!< Pointer to receive queue + struct { + uint8_t bAutoFlushIgnored:1; //!< If 1, automatically remove ignored packets from Rx queue + uint8_t bAutoFlushCrcErr:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushEmpty:1; //!< If 1, automatically remove empty packets from Rx queue + uint8_t bIncludeLenByte:1; //!< If 1, include the received length byte in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendStatus:1; //!< If 1, append a status byte to the packet in the Rx queue + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; //!< Configuration bits for the receive queue entries + struct { + uint8_t bUseWhiteList:1; //!< \brief Initiator filter policy, cf. Volume 2, Part E, Section 7.8.10 of the + //!< Bluetooth 4.0 spec:
+ //!< 0: Use specific peer address
+ //!< 1: Use white list + uint8_t bDynamicWinOffset:1; //!< 1: Use dynamic WinOffset insertion + uint8_t deviceAddrType:1; //!< The type of the device address – public (0) or random (1) + uint8_t peerAddrType:1; //!< The type of the peer address – public (0) or random (1) + uint8_t bStrictLenFilter:1; //!< 1: Discard messages with illegal length + } initConfig; + uint8_t __dummy0; + uint8_t connectReqLen; //!< Size of connect request data + uint8_t* pConnectReqData; //!< Pointer to buffer containing LLData to go in the CONNECT_REQ + uint16_t* pDeviceAddress; //!< Pointer to device address used for this device + rfc_bleWhiteListEntry_t *pWhiteList; //!< Pointer to white list or peer address + ratmr_t connectTime; //!< \brief Indication of timer value of the first possible start time of the first connection event. + //!< Set to the calculated value if a connection is made and to the next possible connection + //!< time if not. + uint16_t __dummy1; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } timeoutTrigger; //!< Trigger that causes the device to stop receiving as soon as allowed + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to stop receiving as soon as allowed + ratmr_t timeoutTime; //!< \brief Time used together with timeoutTrigger that causes the device to stop + //!< receiving as soon as allowed, ending with BLE_DONE_RXTIMEOUT + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to stop + //!< receiving as soon as allowed, ending with BLE_DONE_ENDED +}; + +//! @} + +//! \addtogroup bleGenericRxPar +//! @{ +//! Parameter structure for generic Rx (CMD_BLE_GENERIC_RX) + +struct __RFC_STRUCT rfc_bleGenericRxPar_s { + dataQueue_t* pRxQ; //!< Pointer to receive queue. May be NULL; if so, received packets are not stored + struct { + uint8_t bAutoFlushIgnored:1; //!< If 1, automatically remove ignored packets from Rx queue + uint8_t bAutoFlushCrcErr:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushEmpty:1; //!< If 1, automatically remove empty packets from Rx queue + uint8_t bIncludeLenByte:1; //!< If 1, include the received length byte in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendStatus:1; //!< If 1, append a status byte to the packet in the Rx queue + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; //!< Configuration bits for the receive queue entries + uint8_t bRepeat; //!< \brief 0: End operation after receiving a packet
+ //!< 1: Restart receiver after receiving a packet + uint16_t __dummy0; + uint32_t accessAddress; //!< Access address used on the connection + uint8_t crcInit0; //!< CRC initialization value used on the connection – least significant byte + uint8_t crcInit1; //!< CRC initialization value used on the connection – middle byte + uint8_t crcInit2; //!< CRC initialization value used on the connection – most significant byte + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the Rx operation + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the + //!< Rx operation +}; + +//! @} + +//! \addtogroup bleTxTestPar +//! @{ +//! Parameter structure for Tx test (CMD_BLE_TX_TEST) + +struct __RFC_STRUCT rfc_bleTxTestPar_s { + uint16_t numPackets; //!< \brief Number of packets to transmit
+ //!< 0: Transmit unlimited number of packets + uint8_t payloadLength; //!< The number of payload bytes in each packet. + uint8_t packetType; //!< \brief The packet type to be used, encoded according to the Bluetooth 4.0 spec, Volume 2, Part E, + //!< Section 7.8.29 + ratmr_t period; //!< Number of radio timer cycles between the start of each packet + struct { + uint8_t bOverrideDefault:1; //!< \brief 0: Use default packet encoding
+ //!< 1: Override packet contents + uint8_t bUsePrbs9:1; //!< \brief If bOverride is 1:
+ //!< 1: Use PRBS9 encoding of packet + uint8_t bUsePrbs15:1; //!< \brief If bOverride is 1:
+ //!< 1: Use PRBS15 encoding of packet + } config; + uint8_t byteVal; //!< If config.bOverride is 1, value of each byte to be sent + uint8_t __dummy0; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the Test Tx operation + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the + //!< Test Tx operation +}; + +//! @} + +//! \addtogroup bleMasterSlaveOutput +//! @{ +//! Output structure for master and slave (CMD_BLE_MASTER/CMD_BLE_SLAVE) + +struct __RFC_STRUCT rfc_bleMasterSlaveOutput_s { + uint8_t nTx; //!< \brief Total number of packets (including auto-empty and retransmissions) that have been + //!< transmitted + uint8_t nTxAck; //!< Total number of transmitted packets (including auto-empty) that have been ACK'ed + uint8_t nTxCtrl; //!< Number of unique LL control packets from the Tx queue that have been transmitted + uint8_t nTxCtrlAck; //!< Number of LL control packets from the Tx queue that have been finished (ACK'ed) + uint8_t nTxCtrlAckAck; //!< \brief Number of LL control packets that have been ACK'ed and where an ACK has been sent in + //!< response + uint8_t nTxRetrans; //!< Number of retransmissions that has been done + uint8_t nTxEntryDone; //!< Number of packets from the Tx queue that have been finished (ACK'ed) + uint8_t nRxOk; //!< Number of packets that have been received with payload, CRC OK and not ignored + uint8_t nRxCtrl; //!< Number of LL control packets that have been received with CRC OK and not ignored + uint8_t nRxCtrlAck; //!< \brief Number of LL control packets that have been received with CRC OK and not ignored, and + //!< then ACK'ed + uint8_t nRxNok; //!< Number of packets that have been received with CRC error + uint8_t nRxIgnored; //!< \brief Number of packets that have been received with CRC OK and ignored due to repeated + //!< sequence number + uint8_t nRxEmpty; //!< Number of packets that have been received with CRC OK and no payload + uint8_t nRxBufFull; //!< Number of packets that have been received and discarded due to lack of buffer space + int8_t lastRssi; //!< RSSI of last received packet + struct { + uint8_t bTimeStampValid:1; //!< 1 if a valid time stamp has been written to timeStamp; 0 otherwise + uint8_t bLastCrcErr:1; //!< 1 if the last received packet had CRC error; 0 otherwise + uint8_t bLastIgnored:1; //!< 1 if the last received packet with CRC OK was ignored; 0 otherwise + uint8_t bLastEmpty:1; //!< 1 if the last received packet with CRC OK was empty; 0 otherwise + uint8_t bLastCtrl:1; //!< 1 if the last received packet with CRC OK was empty; 0 otherwise + uint8_t bLastMd:1; //!< 1 if the last received packet with CRC OK had MD = 1; 0 otherwise + uint8_t bLastAck:1; //!< \brief 1 if the last received packet with CRC OK was an ACK of a transmitted packet; + //!< 0 otherwise + } pktStatus; + ratmr_t timeStamp; //!< Slave operation: Time stamp of first received packet +}; + +//! @} + +//! \addtogroup bleAdvOutput +//! @{ +//! Output structure for advertiser (CMD_BLE_ADV*) + +struct __RFC_STRUCT rfc_bleAdvOutput_s { + uint16_t nTxAdvInd; //!< Number of ADV*_IND packets completely transmitted + uint8_t nTxScanRsp; //!< Number of SCAN_RSP packets transmitted + uint8_t nRxScanReq; //!< Number of SCAN_REQ packets received OK and not ignored + uint8_t nRxConnectReq; //!< Number of CONNECT_REQ packets received OK and not ignored + uint8_t __dummy0; + uint16_t nRxNok; //!< Number of packets received with CRC error + uint16_t nRxIgnored; //!< Number of packets received with CRC OK, but ignored + uint8_t nRxBufFull; //!< Number of packets received that did not fit in Rx queue + int8_t lastRssi; //!< The RSSI of the last received packet + ratmr_t timeStamp; //!< Time stamp of the last received packet +}; + +//! @} + +//! \addtogroup bleScannerOutput +//! @{ +//! Output structure for scanner (CMD_BLE_SCANNER) + +struct __RFC_STRUCT rfc_bleScannerOutput_s { + uint16_t nTxScanReq; //!< Number of transmitted SCAN_REQ packets + uint16_t nBackedOffScanReq; //!< Number of SCAN_REQ packets not sent due to backoff procedure + uint16_t nRxAdvOk; //!< Number of ADV*_IND packets received with CRC OK and not ignored + uint16_t nRxAdvIgnored; //!< Number of ADV*_IND packets received with CRC OK, but ignored + uint16_t nRxAdvNok; //!< Number of ADV*_IND packets received with CRC error + uint16_t nRxScanRspOk; //!< Number of SCAN_RSP packets received with CRC OK and not ignored + uint16_t nRxScanRspIgnored; //!< Number of SCAN_RSP packets received with CRC OK, but ignored + uint16_t nRxScanRspNok; //!< Number of SCAN_RSP packets received with CRC error + uint8_t nRxAdvBufFull; //!< Number of ADV*_IND packets received that did not fit in Rx queue + uint8_t nRxScanRspBufFull; //!< Number of SCAN_RSP packets received that did not fit in Rx queue + int8_t lastRssi; //!< The RSSI of the last received packet + uint8_t __dummy0; + ratmr_t timeStamp; //!< Time stamp of the last successfully received ADV*_IND packet that was not ignored +}; + +//! @} + +//! \addtogroup bleInitiatorOutput +//! @{ +//! Output structure for initiator (CMD_BLE_INITIATOR) + +struct __RFC_STRUCT rfc_bleInitiatorOutput_s { + uint8_t nTxConnectReq; //!< Number of transmitted CONNECT_REQ packets + uint8_t nRxAdvOk; //!< Number of ADV*_IND packets received with CRC OK and not ignored + uint16_t nRxAdvIgnored; //!< Number of ADV*_IND packets received with CRC OK, but ignored + uint16_t nRxAdvNok; //!< Number of ADV*_IND packets received with CRC error + uint8_t nRxAdvBufFull; //!< Number of ADV*_IND packets received that did not fit in Rx queue + int8_t lastRssi; //!< The RSSI of the last received packet + ratmr_t timeStamp; //!< Time stamp of the received ADV*_IND packet that caused transmission of CONNECT_REQ +}; + +//! @} + +//! \addtogroup bleGenericRxOutput +//! @{ +//! Output structure for generic Rx (CMD_BLE_GENERIC_RX) + +struct __RFC_STRUCT rfc_bleGenericRxOutput_s { + uint16_t nRxOk; //!< Number of packets received with CRC OK + uint16_t nRxNok; //!< Number of packets received with CRC error + uint16_t nRxBufFull; //!< Number of packets that have been received and discarded due to lack of buffer space + int8_t lastRssi; //!< The RSSI of the last received packet + uint8_t __dummy0; + ratmr_t timeStamp; //!< Time stamp of the last received packet +}; + +//! @} + +//! \addtogroup bleTxTestOutput +//! @{ +//! Output structure for Tx test (CMD_BLE_TX_TEST) + +struct __RFC_STRUCT rfc_bleTxTestOutput_s { + uint16_t nTx; //!< Number of packets transmitted +}; + +//! @} + +//! \addtogroup bleWhiteListEntry +//! @{ +//! White list entry structure + +struct __RFC_STRUCT rfc_bleWhiteListEntry_s { + uint8_t size; //!< Number of while list entries. Used in the first entry of the list only + struct { + uint8_t bEnable:1; //!< 1 if the entry is in use, 0 if the entry is not in use + uint8_t addrType:1; //!< The type address in the entry – public (0) or random (1) + uint8_t bWlIgn:1; //!< \brief 1 if the entry is to be ignored by a scanner, 0 otherwise. Used to mask out + //!< entries that have already been scanned and reported. + } conf; + uint16_t address; //!< Least significant 16 bits of the address contained in the entry + uint32_t addressHi; //!< Most significant 32 bits of the address contained in the entry +}; + +//! @} + +//! \addtogroup bleRxStatus +//! @{ +//! Receive status byte that may be appended to message in receive buffer + +struct __RFC_STRUCT rfc_bleRxStatus_s { + struct { + uint8_t channel:6; //!< \brief The channel on which the packet was received, provided channel is in the range + //!< 0–39; otherwise 0x3F + uint8_t bIgnore:1; //!< 1 if the packet is marked as ignored, 0 otherwise + uint8_t bCrcErr:1; //!< 1 if the packet was received with CRC error, 0 otherwise + } status; +}; + +//! @} + +//! @} +//! @} +#endif diff --git a/cpu/cc26xx/dev/rfc-api/ble_cmd_field.h b/cpu/cc26xx/dev/rfc-api/ble_cmd_field.h new file mode 100755 index 000000000..307e67dc6 --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/ble_cmd_field.h @@ -0,0 +1,623 @@ +/****************************************************************************** +* Filename: ble_cmd_field.h +* Revised: $ $ +* Revision: $ $ +* +* Description: CC26xx/CC13xx API for Bluetooth Low Energy commands +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef __BLE_CMD_FIELD_H +#define __BLE_CMD_FIELD_H + +#include +#include "mailbox.h" +#include "common_cmd.h" + +#define _POSITION_bleRadioOp_channel 14 +#define _TYPE_bleRadioOp_channel uint8_t +#define _POSITION_bleRadioOp_whitening 15 +#define _TYPE_bleRadioOp_whitening uint8_t +#define _BITPOS_bleRadioOp_whitening_init 0 +#define _NBITS_bleRadioOp_whitening_init 7 +#define _BITPOS_bleRadioOp_whitening_bOverride 7 +#define _NBITS_bleRadioOp_whitening_bOverride 1 +#define _POSITION_bleRadioOp_pParams 16 +#define _TYPE_bleRadioOp_pParams uint8_t* +#define _POSITION_bleRadioOp_pOutput 20 +#define _TYPE_bleRadioOp_pOutput uint8_t* +#define _SIZEOF_bleRadioOp 24 + +#define _SIZEOF_CMD_BLE_SLAVE 24 + +#define _SIZEOF_CMD_BLE_MASTER 24 + +#define _SIZEOF_CMD_BLE_ADV 24 + +#define _SIZEOF_CMD_BLE_ADV_DIR 24 + +#define _SIZEOF_CMD_BLE_ADV_NC 24 + +#define _SIZEOF_CMD_BLE_ADV_SCAN 24 + +#define _SIZEOF_CMD_BLE_SCANNER 24 + +#define _SIZEOF_CMD_BLE_INITIATOR 24 + +#define _SIZEOF_CMD_BLE_GENERIC_RX 24 + +#define _SIZEOF_CMD_BLE_TX_TEST 24 + +#define _POSITION_CMD_BLE_ADV_PAYLOAD_payloadType 2 +#define _TYPE_CMD_BLE_ADV_PAYLOAD_payloadType uint8_t +#define _POSITION_CMD_BLE_ADV_PAYLOAD_newLen 3 +#define _TYPE_CMD_BLE_ADV_PAYLOAD_newLen uint8_t +#define _POSITION_CMD_BLE_ADV_PAYLOAD_pNewData 4 +#define _TYPE_CMD_BLE_ADV_PAYLOAD_pNewData uint8_t* +#define _POSITION_CMD_BLE_ADV_PAYLOAD_pParams 8 +#define _TYPE_CMD_BLE_ADV_PAYLOAD_pParams uint8_t* +#define _SIZEOF_CMD_BLE_ADV_PAYLOAD 12 + +#define _POSITION_bleMasterSlavePar_pRxQ 0 +#define _TYPE_bleMasterSlavePar_pRxQ dataQueue_t* +#define _POSITION_bleMasterSlavePar_pTxQ 4 +#define _TYPE_bleMasterSlavePar_pTxQ dataQueue_t* +#define _POSITION_bleMasterSlavePar_rxConfig 8 +#define _TYPE_bleMasterSlavePar_rxConfig uint8_t +#define _BITPOS_bleMasterSlavePar_rxConfig_bAutoFlushIgnored 0 +#define _NBITS_bleMasterSlavePar_rxConfig_bAutoFlushIgnored 1 +#define _BITPOS_bleMasterSlavePar_rxConfig_bAutoFlushCrcErr 1 +#define _NBITS_bleMasterSlavePar_rxConfig_bAutoFlushCrcErr 1 +#define _BITPOS_bleMasterSlavePar_rxConfig_bAutoFlushEmpty 2 +#define _NBITS_bleMasterSlavePar_rxConfig_bAutoFlushEmpty 1 +#define _BITPOS_bleMasterSlavePar_rxConfig_bIncludeLenByte 3 +#define _NBITS_bleMasterSlavePar_rxConfig_bIncludeLenByte 1 +#define _BITPOS_bleMasterSlavePar_rxConfig_bIncludeCrc 4 +#define _NBITS_bleMasterSlavePar_rxConfig_bIncludeCrc 1 +#define _BITPOS_bleMasterSlavePar_rxConfig_bAppendRssi 5 +#define _NBITS_bleMasterSlavePar_rxConfig_bAppendRssi 1 +#define _BITPOS_bleMasterSlavePar_rxConfig_bAppendStatus 6 +#define _NBITS_bleMasterSlavePar_rxConfig_bAppendStatus 1 +#define _BITPOS_bleMasterSlavePar_rxConfig_bAppendTimestamp 7 +#define _NBITS_bleMasterSlavePar_rxConfig_bAppendTimestamp 1 +#define _POSITION_bleMasterSlavePar_seqStat 9 +#define _TYPE_bleMasterSlavePar_seqStat uint8_t +#define _BITPOS_bleMasterSlavePar_seqStat_lastRxSn 0 +#define _NBITS_bleMasterSlavePar_seqStat_lastRxSn 1 +#define _BITPOS_bleMasterSlavePar_seqStat_lastTxSn 1 +#define _NBITS_bleMasterSlavePar_seqStat_lastTxSn 1 +#define _BITPOS_bleMasterSlavePar_seqStat_nextTxSn 2 +#define _NBITS_bleMasterSlavePar_seqStat_nextTxSn 1 +#define _BITPOS_bleMasterSlavePar_seqStat_bFirstPkt 3 +#define _NBITS_bleMasterSlavePar_seqStat_bFirstPkt 1 +#define _BITPOS_bleMasterSlavePar_seqStat_bAutoEmpty 4 +#define _NBITS_bleMasterSlavePar_seqStat_bAutoEmpty 1 +#define _BITPOS_bleMasterSlavePar_seqStat_bLlCtrlTx 5 +#define _NBITS_bleMasterSlavePar_seqStat_bLlCtrlTx 1 +#define _BITPOS_bleMasterSlavePar_seqStat_bLlCtrlAckRx 6 +#define _NBITS_bleMasterSlavePar_seqStat_bLlCtrlAckRx 1 +#define _BITPOS_bleMasterSlavePar_seqStat_bLlCtrlAckPending 7 +#define _NBITS_bleMasterSlavePar_seqStat_bLlCtrlAckPending 1 +#define _POSITION_bleMasterSlavePar_maxNack 10 +#define _TYPE_bleMasterSlavePar_maxNack uint8_t +#define _POSITION_bleMasterSlavePar_maxPkt 11 +#define _TYPE_bleMasterSlavePar_maxPkt uint8_t +#define _POSITION_bleMasterSlavePar_accessAddress 12 +#define _TYPE_bleMasterSlavePar_accessAddress uint32_t +#define _POSITION_bleMasterSlavePar_crcInit0 16 +#define _TYPE_bleMasterSlavePar_crcInit0 uint8_t +#define _POSITION_bleMasterSlavePar_crcInit1 17 +#define _TYPE_bleMasterSlavePar_crcInit1 uint8_t +#define _POSITION_bleMasterSlavePar_crcInit2 18 +#define _TYPE_bleMasterSlavePar_crcInit2 uint8_t +#define _POSITION_bleMasterSlavePar_crcInit 16 +#define _TYPE_bleMasterSlavePar_crcInit uint32_t +#define _SIZEOF_bleMasterSlavePar 20 + +#define _POSITION_bleMasterPar_endTrigger 19 +#define _TYPE_bleMasterPar_endTrigger uint8_t +#define _BITPOS_bleMasterPar_endTrigger_triggerType 0 +#define _NBITS_bleMasterPar_endTrigger_triggerType 4 +#define _BITPOS_bleMasterPar_endTrigger_bEnaCmd 4 +#define _NBITS_bleMasterPar_endTrigger_bEnaCmd 1 +#define _BITPOS_bleMasterPar_endTrigger_triggerNo 5 +#define _NBITS_bleMasterPar_endTrigger_triggerNo 2 +#define _BITPOS_bleMasterPar_endTrigger_pastTrig 7 +#define _NBITS_bleMasterPar_endTrigger_pastTrig 1 +#define _POSITION_bleMasterPar_endTime 20 +#define _TYPE_bleMasterPar_endTime ratmr_t +#define _SIZEOF_bleMasterPar 24 + +#define _POSITION_bleSlavePar_timeoutTrigger 19 +#define _TYPE_bleSlavePar_timeoutTrigger uint8_t +#define _BITPOS_bleSlavePar_timeoutTrigger_triggerType 0 +#define _NBITS_bleSlavePar_timeoutTrigger_triggerType 4 +#define _BITPOS_bleSlavePar_timeoutTrigger_bEnaCmd 4 +#define _NBITS_bleSlavePar_timeoutTrigger_bEnaCmd 1 +#define _BITPOS_bleSlavePar_timeoutTrigger_triggerNo 5 +#define _NBITS_bleSlavePar_timeoutTrigger_triggerNo 2 +#define _BITPOS_bleSlavePar_timeoutTrigger_pastTrig 7 +#define _NBITS_bleSlavePar_timeoutTrigger_pastTrig 1 +#define _POSITION_bleSlavePar_timeoutTime 20 +#define _TYPE_bleSlavePar_timeoutTime ratmr_t +#define _POSITION_bleSlavePar_endTrigger 27 +#define _TYPE_bleSlavePar_endTrigger uint8_t +#define _BITPOS_bleSlavePar_endTrigger_triggerType 0 +#define _NBITS_bleSlavePar_endTrigger_triggerType 4 +#define _BITPOS_bleSlavePar_endTrigger_bEnaCmd 4 +#define _NBITS_bleSlavePar_endTrigger_bEnaCmd 1 +#define _BITPOS_bleSlavePar_endTrigger_triggerNo 5 +#define _NBITS_bleSlavePar_endTrigger_triggerNo 2 +#define _BITPOS_bleSlavePar_endTrigger_pastTrig 7 +#define _NBITS_bleSlavePar_endTrigger_pastTrig 1 +#define _POSITION_bleSlavePar_endTime 28 +#define _TYPE_bleSlavePar_endTime ratmr_t +#define _SIZEOF_bleSlavePar 32 + +#define _POSITION_bleAdvPar_pRxQ 0 +#define _TYPE_bleAdvPar_pRxQ dataQueue_t* +#define _POSITION_bleAdvPar_rxConfig 4 +#define _TYPE_bleAdvPar_rxConfig uint8_t +#define _BITPOS_bleAdvPar_rxConfig_bAutoFlushIgnored 0 +#define _NBITS_bleAdvPar_rxConfig_bAutoFlushIgnored 1 +#define _BITPOS_bleAdvPar_rxConfig_bAutoFlushCrcErr 1 +#define _NBITS_bleAdvPar_rxConfig_bAutoFlushCrcErr 1 +#define _BITPOS_bleAdvPar_rxConfig_bAutoFlushEmpty 2 +#define _NBITS_bleAdvPar_rxConfig_bAutoFlushEmpty 1 +#define _BITPOS_bleAdvPar_rxConfig_bIncludeLenByte 3 +#define _NBITS_bleAdvPar_rxConfig_bIncludeLenByte 1 +#define _BITPOS_bleAdvPar_rxConfig_bIncludeCrc 4 +#define _NBITS_bleAdvPar_rxConfig_bIncludeCrc 1 +#define _BITPOS_bleAdvPar_rxConfig_bAppendRssi 5 +#define _NBITS_bleAdvPar_rxConfig_bAppendRssi 1 +#define _BITPOS_bleAdvPar_rxConfig_bAppendStatus 6 +#define _NBITS_bleAdvPar_rxConfig_bAppendStatus 1 +#define _BITPOS_bleAdvPar_rxConfig_bAppendTimestamp 7 +#define _NBITS_bleAdvPar_rxConfig_bAppendTimestamp 1 +#define _POSITION_bleAdvPar_advConfig 5 +#define _TYPE_bleAdvPar_advConfig uint8_t +#define _BITPOS_bleAdvPar_advConfig_advFilterPolicy 0 +#define _NBITS_bleAdvPar_advConfig_advFilterPolicy 2 +#define _BITPOS_bleAdvPar_advConfig_deviceAddrType 2 +#define _NBITS_bleAdvPar_advConfig_deviceAddrType 1 +#define _BITPOS_bleAdvPar_advConfig_peerAddrType 3 +#define _NBITS_bleAdvPar_advConfig_peerAddrType 1 +#define _BITPOS_bleAdvPar_advConfig_bStrictLenFilter 4 +#define _NBITS_bleAdvPar_advConfig_bStrictLenFilter 1 +#define _POSITION_bleAdvPar_advLen 6 +#define _TYPE_bleAdvPar_advLen uint8_t +#define _POSITION_bleAdvPar_scanRspLen 7 +#define _TYPE_bleAdvPar_scanRspLen uint8_t +#define _POSITION_bleAdvPar_pAdvData 8 +#define _TYPE_bleAdvPar_pAdvData uint8_t* +#define _POSITION_bleAdvPar_pScanRspData 12 +#define _TYPE_bleAdvPar_pScanRspData uint8_t* +#define _POSITION_bleAdvPar_pDeviceAddress 16 +#define _TYPE_bleAdvPar_pDeviceAddress uint16_t* +#define _POSITION_bleAdvPar_pWhiteList 20 +#define _TYPE_bleAdvPar_pWhiteList uint32_t* +#define _POSITION_bleAdvPar_endTrigger 27 +#define _TYPE_bleAdvPar_endTrigger uint8_t +#define _BITPOS_bleAdvPar_endTrigger_triggerType 0 +#define _NBITS_bleAdvPar_endTrigger_triggerType 4 +#define _BITPOS_bleAdvPar_endTrigger_bEnaCmd 4 +#define _NBITS_bleAdvPar_endTrigger_bEnaCmd 1 +#define _BITPOS_bleAdvPar_endTrigger_triggerNo 5 +#define _NBITS_bleAdvPar_endTrigger_triggerNo 2 +#define _BITPOS_bleAdvPar_endTrigger_pastTrig 7 +#define _NBITS_bleAdvPar_endTrigger_pastTrig 1 +#define _POSITION_bleAdvPar_endTime 28 +#define _TYPE_bleAdvPar_endTime ratmr_t +#define _SIZEOF_bleAdvPar 32 + +#define _POSITION_bleScannerPar_pRxQ 0 +#define _TYPE_bleScannerPar_pRxQ dataQueue_t* +#define _POSITION_bleScannerPar_rxConfig 4 +#define _TYPE_bleScannerPar_rxConfig uint8_t +#define _BITPOS_bleScannerPar_rxConfig_bAutoFlushIgnored 0 +#define _NBITS_bleScannerPar_rxConfig_bAutoFlushIgnored 1 +#define _BITPOS_bleScannerPar_rxConfig_bAutoFlushCrcErr 1 +#define _NBITS_bleScannerPar_rxConfig_bAutoFlushCrcErr 1 +#define _BITPOS_bleScannerPar_rxConfig_bAutoFlushEmpty 2 +#define _NBITS_bleScannerPar_rxConfig_bAutoFlushEmpty 1 +#define _BITPOS_bleScannerPar_rxConfig_bIncludeLenByte 3 +#define _NBITS_bleScannerPar_rxConfig_bIncludeLenByte 1 +#define _BITPOS_bleScannerPar_rxConfig_bIncludeCrc 4 +#define _NBITS_bleScannerPar_rxConfig_bIncludeCrc 1 +#define _BITPOS_bleScannerPar_rxConfig_bAppendRssi 5 +#define _NBITS_bleScannerPar_rxConfig_bAppendRssi 1 +#define _BITPOS_bleScannerPar_rxConfig_bAppendStatus 6 +#define _NBITS_bleScannerPar_rxConfig_bAppendStatus 1 +#define _BITPOS_bleScannerPar_rxConfig_bAppendTimestamp 7 +#define _NBITS_bleScannerPar_rxConfig_bAppendTimestamp 1 +#define _POSITION_bleScannerPar_scanConfig 5 +#define _TYPE_bleScannerPar_scanConfig uint8_t +#define _BITPOS_bleScannerPar_scanConfig_scanFilterPolicy 0 +#define _NBITS_bleScannerPar_scanConfig_scanFilterPolicy 1 +#define _BITPOS_bleScannerPar_scanConfig_bActiveScan 1 +#define _NBITS_bleScannerPar_scanConfig_bActiveScan 1 +#define _BITPOS_bleScannerPar_scanConfig_deviceAddrType 2 +#define _NBITS_bleScannerPar_scanConfig_deviceAddrType 1 +#define _BITPOS_bleScannerPar_scanConfig_bStrictLenFilter 4 +#define _NBITS_bleScannerPar_scanConfig_bStrictLenFilter 1 +#define _BITPOS_bleScannerPar_scanConfig_bAutoWlIgnore 5 +#define _NBITS_bleScannerPar_scanConfig_bAutoWlIgnore 1 +#define _BITPOS_bleScannerPar_scanConfig_bEndOnRpt 6 +#define _NBITS_bleScannerPar_scanConfig_bEndOnRpt 1 +#define _POSITION_bleScannerPar_randomState 6 +#define _TYPE_bleScannerPar_randomState uint16_t +#define _POSITION_bleScannerPar_backoffCount 8 +#define _TYPE_bleScannerPar_backoffCount uint16_t +#define _POSITION_bleScannerPar_backoffPar 10 +#define _TYPE_bleScannerPar_backoffPar uint8_t +#define _BITPOS_bleScannerPar_backoffPar_logUpperLimit 0 +#define _NBITS_bleScannerPar_backoffPar_logUpperLimit 4 +#define _BITPOS_bleScannerPar_backoffPar_bLastSucceeded 4 +#define _NBITS_bleScannerPar_backoffPar_bLastSucceeded 1 +#define _BITPOS_bleScannerPar_backoffPar_bLastFailed 5 +#define _NBITS_bleScannerPar_backoffPar_bLastFailed 1 +#define _POSITION_bleScannerPar_scanReqLen 11 +#define _TYPE_bleScannerPar_scanReqLen uint8_t +#define _POSITION_bleScannerPar_pScanReqData 12 +#define _TYPE_bleScannerPar_pScanReqData uint8_t* +#define _POSITION_bleScannerPar_pDeviceAddress 16 +#define _TYPE_bleScannerPar_pDeviceAddress uint16_t* +#define _POSITION_bleScannerPar_pWhiteList 20 +#define _TYPE_bleScannerPar_pWhiteList uint32_t* +#define _POSITION_bleScannerPar_timeoutTrigger 26 +#define _TYPE_bleScannerPar_timeoutTrigger uint8_t +#define _BITPOS_bleScannerPar_timeoutTrigger_triggerType 0 +#define _NBITS_bleScannerPar_timeoutTrigger_triggerType 4 +#define _BITPOS_bleScannerPar_timeoutTrigger_bEnaCmd 4 +#define _NBITS_bleScannerPar_timeoutTrigger_bEnaCmd 1 +#define _BITPOS_bleScannerPar_timeoutTrigger_triggerNo 5 +#define _NBITS_bleScannerPar_timeoutTrigger_triggerNo 2 +#define _BITPOS_bleScannerPar_timeoutTrigger_pastTrig 7 +#define _NBITS_bleScannerPar_timeoutTrigger_pastTrig 1 +#define _POSITION_bleScannerPar_endTrigger 27 +#define _TYPE_bleScannerPar_endTrigger uint8_t +#define _BITPOS_bleScannerPar_endTrigger_triggerType 0 +#define _NBITS_bleScannerPar_endTrigger_triggerType 4 +#define _BITPOS_bleScannerPar_endTrigger_bEnaCmd 4 +#define _NBITS_bleScannerPar_endTrigger_bEnaCmd 1 +#define _BITPOS_bleScannerPar_endTrigger_triggerNo 5 +#define _NBITS_bleScannerPar_endTrigger_triggerNo 2 +#define _BITPOS_bleScannerPar_endTrigger_pastTrig 7 +#define _NBITS_bleScannerPar_endTrigger_pastTrig 1 +#define _POSITION_bleScannerPar_timeoutTime 28 +#define _TYPE_bleScannerPar_timeoutTime ratmr_t +#define _POSITION_bleScannerPar_endTime 32 +#define _TYPE_bleScannerPar_endTime ratmr_t +#define _SIZEOF_bleScannerPar 36 + +#define _POSITION_bleInitiatorPar_pRxQ 0 +#define _TYPE_bleInitiatorPar_pRxQ dataQueue_t* +#define _POSITION_bleInitiatorPar_rxConfig 4 +#define _TYPE_bleInitiatorPar_rxConfig uint8_t +#define _BITPOS_bleInitiatorPar_rxConfig_bAutoFlushIgnored 0 +#define _NBITS_bleInitiatorPar_rxConfig_bAutoFlushIgnored 1 +#define _BITPOS_bleInitiatorPar_rxConfig_bAutoFlushCrcErr 1 +#define _NBITS_bleInitiatorPar_rxConfig_bAutoFlushCrcErr 1 +#define _BITPOS_bleInitiatorPar_rxConfig_bAutoFlushEmpty 2 +#define _NBITS_bleInitiatorPar_rxConfig_bAutoFlushEmpty 1 +#define _BITPOS_bleInitiatorPar_rxConfig_bIncludeLenByte 3 +#define _NBITS_bleInitiatorPar_rxConfig_bIncludeLenByte 1 +#define _BITPOS_bleInitiatorPar_rxConfig_bIncludeCrc 4 +#define _NBITS_bleInitiatorPar_rxConfig_bIncludeCrc 1 +#define _BITPOS_bleInitiatorPar_rxConfig_bAppendRssi 5 +#define _NBITS_bleInitiatorPar_rxConfig_bAppendRssi 1 +#define _BITPOS_bleInitiatorPar_rxConfig_bAppendStatus 6 +#define _NBITS_bleInitiatorPar_rxConfig_bAppendStatus 1 +#define _BITPOS_bleInitiatorPar_rxConfig_bAppendTimestamp 7 +#define _NBITS_bleInitiatorPar_rxConfig_bAppendTimestamp 1 +#define _POSITION_bleInitiatorPar_initConfig 5 +#define _TYPE_bleInitiatorPar_initConfig uint8_t +#define _BITPOS_bleInitiatorPar_initConfig_bUseWhiteList 0 +#define _NBITS_bleInitiatorPar_initConfig_bUseWhiteList 1 +#define _BITPOS_bleInitiatorPar_initConfig_bDynamicWinOffset 1 +#define _NBITS_bleInitiatorPar_initConfig_bDynamicWinOffset 1 +#define _BITPOS_bleInitiatorPar_initConfig_deviceAddrType 2 +#define _NBITS_bleInitiatorPar_initConfig_deviceAddrType 1 +#define _BITPOS_bleInitiatorPar_initConfig_peerAddrType 3 +#define _NBITS_bleInitiatorPar_initConfig_peerAddrType 1 +#define _BITPOS_bleInitiatorPar_initConfig_bStrictLenFilter 4 +#define _NBITS_bleInitiatorPar_initConfig_bStrictLenFilter 1 +#define _POSITION_bleInitiatorPar_connectReqLen 7 +#define _TYPE_bleInitiatorPar_connectReqLen uint8_t +#define _POSITION_bleInitiatorPar_pConnectReqData 8 +#define _TYPE_bleInitiatorPar_pConnectReqData uint8_t* +#define _POSITION_bleInitiatorPar_pDeviceAddress 12 +#define _TYPE_bleInitiatorPar_pDeviceAddress uint16_t* +#define _POSITION_bleInitiatorPar_pWhiteList 16 +#define _TYPE_bleInitiatorPar_pWhiteList uint32_t* +#define _POSITION_bleInitiatorPar_connectTime 20 +#define _TYPE_bleInitiatorPar_connectTime ratmr_t +#define _POSITION_bleInitiatorPar_timeoutTrigger 26 +#define _TYPE_bleInitiatorPar_timeoutTrigger uint8_t +#define _BITPOS_bleInitiatorPar_timeoutTrigger_triggerType 0 +#define _NBITS_bleInitiatorPar_timeoutTrigger_triggerType 4 +#define _BITPOS_bleInitiatorPar_timeoutTrigger_bEnaCmd 4 +#define _NBITS_bleInitiatorPar_timeoutTrigger_bEnaCmd 1 +#define _BITPOS_bleInitiatorPar_timeoutTrigger_triggerNo 5 +#define _NBITS_bleInitiatorPar_timeoutTrigger_triggerNo 2 +#define _BITPOS_bleInitiatorPar_timeoutTrigger_pastTrig 7 +#define _NBITS_bleInitiatorPar_timeoutTrigger_pastTrig 1 +#define _POSITION_bleInitiatorPar_endTrigger 27 +#define _TYPE_bleInitiatorPar_endTrigger uint8_t +#define _BITPOS_bleInitiatorPar_endTrigger_triggerType 0 +#define _NBITS_bleInitiatorPar_endTrigger_triggerType 4 +#define _BITPOS_bleInitiatorPar_endTrigger_bEnaCmd 4 +#define _NBITS_bleInitiatorPar_endTrigger_bEnaCmd 1 +#define _BITPOS_bleInitiatorPar_endTrigger_triggerNo 5 +#define _NBITS_bleInitiatorPar_endTrigger_triggerNo 2 +#define _BITPOS_bleInitiatorPar_endTrigger_pastTrig 7 +#define _NBITS_bleInitiatorPar_endTrigger_pastTrig 1 +#define _POSITION_bleInitiatorPar_timeoutTime 28 +#define _TYPE_bleInitiatorPar_timeoutTime ratmr_t +#define _POSITION_bleInitiatorPar_endTime 32 +#define _TYPE_bleInitiatorPar_endTime ratmr_t +#define _SIZEOF_bleInitiatorPar 36 + +#define _POSITION_bleGenericRxPar_pRxQ 0 +#define _TYPE_bleGenericRxPar_pRxQ dataQueue_t* +#define _POSITION_bleGenericRxPar_rxConfig 4 +#define _TYPE_bleGenericRxPar_rxConfig uint8_t +#define _BITPOS_bleGenericRxPar_rxConfig_bAutoFlushIgnored 0 +#define _NBITS_bleGenericRxPar_rxConfig_bAutoFlushIgnored 1 +#define _BITPOS_bleGenericRxPar_rxConfig_bAutoFlushCrcErr 1 +#define _NBITS_bleGenericRxPar_rxConfig_bAutoFlushCrcErr 1 +#define _BITPOS_bleGenericRxPar_rxConfig_bAutoFlushEmpty 2 +#define _NBITS_bleGenericRxPar_rxConfig_bAutoFlushEmpty 1 +#define _BITPOS_bleGenericRxPar_rxConfig_bIncludeLenByte 3 +#define _NBITS_bleGenericRxPar_rxConfig_bIncludeLenByte 1 +#define _BITPOS_bleGenericRxPar_rxConfig_bIncludeCrc 4 +#define _NBITS_bleGenericRxPar_rxConfig_bIncludeCrc 1 +#define _BITPOS_bleGenericRxPar_rxConfig_bAppendRssi 5 +#define _NBITS_bleGenericRxPar_rxConfig_bAppendRssi 1 +#define _BITPOS_bleGenericRxPar_rxConfig_bAppendStatus 6 +#define _NBITS_bleGenericRxPar_rxConfig_bAppendStatus 1 +#define _BITPOS_bleGenericRxPar_rxConfig_bAppendTimestamp 7 +#define _NBITS_bleGenericRxPar_rxConfig_bAppendTimestamp 1 +#define _POSITION_bleGenericRxPar_bRepeat 5 +#define _TYPE_bleGenericRxPar_bRepeat uint8_t +#define _POSITION_bleGenericRxPar_accessAddress 8 +#define _TYPE_bleGenericRxPar_accessAddress uint32_t +#define _POSITION_bleGenericRxPar_crcInit0 12 +#define _TYPE_bleGenericRxPar_crcInit0 uint8_t +#define _POSITION_bleGenericRxPar_crcInit1 13 +#define _TYPE_bleGenericRxPar_crcInit1 uint8_t +#define _POSITION_bleGenericRxPar_crcInit2 14 +#define _TYPE_bleGenericRxPar_crcInit2 uint8_t +#define _POSITION_bleGenericRxPar_crcInit 12 +#define _TYPE_bleGenericRxPar_crcInit uint32_t +#define _POSITION_bleGenericRxPar_endTrigger 15 +#define _TYPE_bleGenericRxPar_endTrigger uint8_t +#define _BITPOS_bleGenericRxPar_endTrigger_triggerType 0 +#define _NBITS_bleGenericRxPar_endTrigger_triggerType 4 +#define _BITPOS_bleGenericRxPar_endTrigger_bEnaCmd 4 +#define _NBITS_bleGenericRxPar_endTrigger_bEnaCmd 1 +#define _BITPOS_bleGenericRxPar_endTrigger_triggerNo 5 +#define _NBITS_bleGenericRxPar_endTrigger_triggerNo 2 +#define _BITPOS_bleGenericRxPar_endTrigger_pastTrig 7 +#define _NBITS_bleGenericRxPar_endTrigger_pastTrig 1 +#define _POSITION_bleGenericRxPar_endTime 16 +#define _TYPE_bleGenericRxPar_endTime ratmr_t +#define _SIZEOF_bleGenericRxPar 20 + +#define _POSITION_bleTxTestPar_numPackets 0 +#define _TYPE_bleTxTestPar_numPackets uint16_t +#define _POSITION_bleTxTestPar_payloadLength 2 +#define _TYPE_bleTxTestPar_payloadLength uint8_t +#define _POSITION_bleTxTestPar_packetType 3 +#define _TYPE_bleTxTestPar_packetType uint8_t +#define _POSITION_bleTxTestPar_period 4 +#define _TYPE_bleTxTestPar_period ratmr_t +#define _POSITION_bleTxTestPar_config 8 +#define _TYPE_bleTxTestPar_config uint8_t +#define _BITPOS_bleTxTestPar_config_bOverrideDefault 0 +#define _NBITS_bleTxTestPar_config_bOverrideDefault 1 +#define _BITPOS_bleTxTestPar_config_bUsePrbs9 1 +#define _NBITS_bleTxTestPar_config_bUsePrbs9 1 +#define _BITPOS_bleTxTestPar_config_bUsePrbs15 2 +#define _NBITS_bleTxTestPar_config_bUsePrbs15 1 +#define _POSITION_bleTxTestPar_byteVal 9 +#define _TYPE_bleTxTestPar_byteVal uint8_t +#define _POSITION_bleTxTestPar_endTrigger 11 +#define _TYPE_bleTxTestPar_endTrigger uint8_t +#define _BITPOS_bleTxTestPar_endTrigger_triggerType 0 +#define _NBITS_bleTxTestPar_endTrigger_triggerType 4 +#define _BITPOS_bleTxTestPar_endTrigger_bEnaCmd 4 +#define _NBITS_bleTxTestPar_endTrigger_bEnaCmd 1 +#define _BITPOS_bleTxTestPar_endTrigger_triggerNo 5 +#define _NBITS_bleTxTestPar_endTrigger_triggerNo 2 +#define _BITPOS_bleTxTestPar_endTrigger_pastTrig 7 +#define _NBITS_bleTxTestPar_endTrigger_pastTrig 1 +#define _POSITION_bleTxTestPar_endTime 12 +#define _TYPE_bleTxTestPar_endTime ratmr_t +#define _SIZEOF_bleTxTestPar 16 + +#define _POSITION_bleMasterSlaveOutput_nTx 0 +#define _TYPE_bleMasterSlaveOutput_nTx uint8_t +#define _POSITION_bleMasterSlaveOutput_nTxAck 1 +#define _TYPE_bleMasterSlaveOutput_nTxAck uint8_t +#define _POSITION_bleMasterSlaveOutput_nTxCtrl 2 +#define _TYPE_bleMasterSlaveOutput_nTxCtrl uint8_t +#define _POSITION_bleMasterSlaveOutput_nTxCtrlAck 3 +#define _TYPE_bleMasterSlaveOutput_nTxCtrlAck uint8_t +#define _POSITION_bleMasterSlaveOutput_nTxCtrlAckAck 4 +#define _TYPE_bleMasterSlaveOutput_nTxCtrlAckAck uint8_t +#define _POSITION_bleMasterSlaveOutput_nTxRetrans 5 +#define _TYPE_bleMasterSlaveOutput_nTxRetrans uint8_t +#define _POSITION_bleMasterSlaveOutput_nTxEntryDone 6 +#define _TYPE_bleMasterSlaveOutput_nTxEntryDone uint8_t +#define _POSITION_bleMasterSlaveOutput_nRxOk 7 +#define _TYPE_bleMasterSlaveOutput_nRxOk uint8_t +#define _POSITION_bleMasterSlaveOutput_nRxCtrl 8 +#define _TYPE_bleMasterSlaveOutput_nRxCtrl uint8_t +#define _POSITION_bleMasterSlaveOutput_nRxCtrlAck 9 +#define _TYPE_bleMasterSlaveOutput_nRxCtrlAck uint8_t +#define _POSITION_bleMasterSlaveOutput_nRxNok 10 +#define _TYPE_bleMasterSlaveOutput_nRxNok uint8_t +#define _POSITION_bleMasterSlaveOutput_nRxIgnored 11 +#define _TYPE_bleMasterSlaveOutput_nRxIgnored uint8_t +#define _POSITION_bleMasterSlaveOutput_nRxEmpty 12 +#define _TYPE_bleMasterSlaveOutput_nRxEmpty uint8_t +#define _POSITION_bleMasterSlaveOutput_nRxBufFull 13 +#define _TYPE_bleMasterSlaveOutput_nRxBufFull uint8_t +#define _POSITION_bleMasterSlaveOutput_lastRssi 14 +#define _TYPE_bleMasterSlaveOutput_lastRssi int8_t +#define _POSITION_bleMasterSlaveOutput_pktStatus 15 +#define _TYPE_bleMasterSlaveOutput_pktStatus uint8_t +#define _BITPOS_bleMasterSlaveOutput_pktStatus_bTimeStampValid 0 +#define _NBITS_bleMasterSlaveOutput_pktStatus_bTimeStampValid 1 +#define _BITPOS_bleMasterSlaveOutput_pktStatus_bLastCrcErr 1 +#define _NBITS_bleMasterSlaveOutput_pktStatus_bLastCrcErr 1 +#define _BITPOS_bleMasterSlaveOutput_pktStatus_bLastIgnored 2 +#define _NBITS_bleMasterSlaveOutput_pktStatus_bLastIgnored 1 +#define _BITPOS_bleMasterSlaveOutput_pktStatus_bLastEmpty 3 +#define _NBITS_bleMasterSlaveOutput_pktStatus_bLastEmpty 1 +#define _BITPOS_bleMasterSlaveOutput_pktStatus_bLastCtrl 4 +#define _NBITS_bleMasterSlaveOutput_pktStatus_bLastCtrl 1 +#define _BITPOS_bleMasterSlaveOutput_pktStatus_bLastMd 5 +#define _NBITS_bleMasterSlaveOutput_pktStatus_bLastMd 1 +#define _BITPOS_bleMasterSlaveOutput_pktStatus_bLastAck 6 +#define _NBITS_bleMasterSlaveOutput_pktStatus_bLastAck 1 +#define _POSITION_bleMasterSlaveOutput_timeStamp 16 +#define _TYPE_bleMasterSlaveOutput_timeStamp ratmr_t +#define _SIZEOF_bleMasterSlaveOutput 20 + +#define _POSITION_bleAdvOutput_nTxAdvInd 0 +#define _TYPE_bleAdvOutput_nTxAdvInd uint16_t +#define _POSITION_bleAdvOutput_nTxScanRsp 2 +#define _TYPE_bleAdvOutput_nTxScanRsp uint8_t +#define _POSITION_bleAdvOutput_nRxScanReq 3 +#define _TYPE_bleAdvOutput_nRxScanReq uint8_t +#define _POSITION_bleAdvOutput_nRxConnectReq 4 +#define _TYPE_bleAdvOutput_nRxConnectReq uint8_t +#define _POSITION_bleAdvOutput_nRxNok 6 +#define _TYPE_bleAdvOutput_nRxNok uint16_t +#define _POSITION_bleAdvOutput_nRxIgnored 8 +#define _TYPE_bleAdvOutput_nRxIgnored uint16_t +#define _POSITION_bleAdvOutput_nRxBufFull 10 +#define _TYPE_bleAdvOutput_nRxBufFull uint8_t +#define _POSITION_bleAdvOutput_lastRssi 11 +#define _TYPE_bleAdvOutput_lastRssi int8_t +#define _POSITION_bleAdvOutput_timeStamp 12 +#define _TYPE_bleAdvOutput_timeStamp ratmr_t +#define _SIZEOF_bleAdvOutput 16 + +#define _POSITION_bleScannerOutput_nTxScanReq 0 +#define _TYPE_bleScannerOutput_nTxScanReq uint16_t +#define _POSITION_bleScannerOutput_nBackedOffScanReq 2 +#define _TYPE_bleScannerOutput_nBackedOffScanReq uint16_t +#define _POSITION_bleScannerOutput_nRxAdvOk 4 +#define _TYPE_bleScannerOutput_nRxAdvOk uint16_t +#define _POSITION_bleScannerOutput_nRxAdvIgnored 6 +#define _TYPE_bleScannerOutput_nRxAdvIgnored uint16_t +#define _POSITION_bleScannerOutput_nRxAdvNok 8 +#define _TYPE_bleScannerOutput_nRxAdvNok uint16_t +#define _POSITION_bleScannerOutput_nRxScanRspOk 10 +#define _TYPE_bleScannerOutput_nRxScanRspOk uint16_t +#define _POSITION_bleScannerOutput_nRxScanRspIgnored 12 +#define _TYPE_bleScannerOutput_nRxScanRspIgnored uint16_t +#define _POSITION_bleScannerOutput_nRxScanRspNok 14 +#define _TYPE_bleScannerOutput_nRxScanRspNok uint16_t +#define _POSITION_bleScannerOutput_nRxAdvBufFull 16 +#define _TYPE_bleScannerOutput_nRxAdvBufFull uint8_t +#define _POSITION_bleScannerOutput_nRxScanRspBufFull 17 +#define _TYPE_bleScannerOutput_nRxScanRspBufFull uint8_t +#define _POSITION_bleScannerOutput_lastRssi 18 +#define _TYPE_bleScannerOutput_lastRssi int8_t +#define _POSITION_bleScannerOutput_timeStamp 20 +#define _TYPE_bleScannerOutput_timeStamp ratmr_t +#define _SIZEOF_bleScannerOutput 24 + +#define _POSITION_bleInitiatorOutput_nTxConnectReq 0 +#define _TYPE_bleInitiatorOutput_nTxConnectReq uint8_t +#define _POSITION_bleInitiatorOutput_nRxAdvOk 1 +#define _TYPE_bleInitiatorOutput_nRxAdvOk uint8_t +#define _POSITION_bleInitiatorOutput_nRxAdvIgnored 2 +#define _TYPE_bleInitiatorOutput_nRxAdvIgnored uint16_t +#define _POSITION_bleInitiatorOutput_nRxAdvNok 4 +#define _TYPE_bleInitiatorOutput_nRxAdvNok uint16_t +#define _POSITION_bleInitiatorOutput_nRxAdvBufFull 6 +#define _TYPE_bleInitiatorOutput_nRxAdvBufFull uint8_t +#define _POSITION_bleInitiatorOutput_lastRssi 7 +#define _TYPE_bleInitiatorOutput_lastRssi int8_t +#define _POSITION_bleInitiatorOutput_timeStamp 8 +#define _TYPE_bleInitiatorOutput_timeStamp ratmr_t +#define _SIZEOF_bleInitiatorOutput 12 + +#define _POSITION_bleGenericRxOutput_nRxOk 0 +#define _TYPE_bleGenericRxOutput_nRxOk uint16_t +#define _POSITION_bleGenericRxOutput_nRxNok 2 +#define _TYPE_bleGenericRxOutput_nRxNok uint16_t +#define _POSITION_bleGenericRxOutput_nRxBufFull 4 +#define _TYPE_bleGenericRxOutput_nRxBufFull uint16_t +#define _POSITION_bleGenericRxOutput_lastRssi 6 +#define _TYPE_bleGenericRxOutput_lastRssi int8_t +#define _POSITION_bleGenericRxOutput_timeStamp 8 +#define _TYPE_bleGenericRxOutput_timeStamp ratmr_t +#define _SIZEOF_bleGenericRxOutput 12 + +#define _POSITION_bleTxTestOutput_nTx 0 +#define _TYPE_bleTxTestOutput_nTx uint16_t +#define _SIZEOF_bleTxTestOutput 2 + +#define _POSITION_bleWhiteListEntry_size 0 +#define _TYPE_bleWhiteListEntry_size uint8_t +#define _POSITION_bleWhiteListEntry_conf 1 +#define _TYPE_bleWhiteListEntry_conf uint8_t +#define _BITPOS_bleWhiteListEntry_conf_bEnable 0 +#define _NBITS_bleWhiteListEntry_conf_bEnable 1 +#define _BITPOS_bleWhiteListEntry_conf_addrType 1 +#define _NBITS_bleWhiteListEntry_conf_addrType 1 +#define _BITPOS_bleWhiteListEntry_conf_bWlIgn 2 +#define _NBITS_bleWhiteListEntry_conf_bWlIgn 1 +#define _POSITION_bleWhiteListEntry_address 2 +#define _TYPE_bleWhiteListEntry_address uint16_t +#define _POSITION_bleWhiteListEntry_addressHi 4 +#define _TYPE_bleWhiteListEntry_addressHi uint32_t +#define _SIZEOF_bleWhiteListEntry 8 + +#define _POSITION_bleRxStatus_status 0 +#define _TYPE_bleRxStatus_status uint8_t +#define _BITPOS_bleRxStatus_status_channel 0 +#define _NBITS_bleRxStatus_status_channel 6 +#define _BITPOS_bleRxStatus_status_bIgnore 6 +#define _NBITS_bleRxStatus_status_bIgnore 1 +#define _BITPOS_bleRxStatus_status_bCrcErr 7 +#define _NBITS_bleRxStatus_status_bCrcErr 1 +#define _SIZEOF_bleRxStatus 1 + +#endif diff --git a/cpu/cc26xx/dev/rfc-api/ble_mailbox.h b/cpu/cc26xx/dev/rfc-api/ble_mailbox.h new file mode 100644 index 000000000..607a92f5d --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/ble_mailbox.h @@ -0,0 +1,119 @@ +/****************************************************************************** +* Filename: ble_mailbox.h +* Revised: $ $ +* Revision: $ $ +* +* Description: Definitions for BLE interface +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef _BLE_MAILBOX_H +#define _BLE_MAILBOX_H + +#include "mailbox.h" + +/// \name CPE interrupt definitions for BLE +/// Interrupt masks for the CPE interrupt in RDBELL. These are new names for interrupts in mailbox.h, +/// used for compartibility with previous versions with separate interrupt numbers. +///@{ +#define IRQN_BLE_TX_DONE IRQN_TX_DONE +#define IRQN_BLE_TX_ACK IRQN_TX_ACK +#define IRQN_BLE_TX_CTRL IRQN_TX_CTRL +#define IRQN_BLE_TX_CTRL_ACK IRQN_TX_CTRL_ACK +#define IRQN_BLE_TX_CTRL_ACK_ACK IRQN_TX_CTRL_ACK_ACK +#define IRQN_BLE_TX_RETRANS IRQN_TX_RETRANS +#define IRQN_BLE_TX_ENTRY_DONE IRQN_TX_ENTRY_DONE +#define IRQN_BLE_TX_BUFFER_CHANGED IRQN_TX_BUFFER_CHANGED +#define IRQN_BLE_RX_OK IRQN_RX_OK +#define IRQN_BLE_RX_NOK IRQN_RX_NOK +#define IRQN_BLE_RX_IGNORED IRQN_RX_IGNORED +#define IRQN_BLE_RX_EMPTY IRQN_RX_EMPTY +#define IRQN_BLE_RX_CTRL IRQN_RX_CTRL +#define IRQN_BLE_RX_CTRL_ACK IRQN_RX_CTRL_ACK +#define IRQN_BLE_RX_BUF_FULL IRQN_RX_BUF_FULL +#define IRQN_BLE_RX_ENTRY_DONE IRQN_RX_ENTRY_DONE + +#define IRQ_BLE_TX_DONE (1U << IRQN_BLE_TX_DONE) +#define IRQ_BLE_TX_ACK (1U << IRQN_BLE_TX_ACK) +#define IRQ_BLE_TX_CTRL (1U << IRQN_BLE_TX_CTRL) +#define IRQ_BLE_TX_CTRL_ACK (1U << IRQN_BLE_TX_CTRL_ACK) +#define IRQ_BLE_TX_CTRL_ACK_ACK (1U << IRQN_BLE_TX_CTRL_ACK_ACK) +#define IRQ_BLE_TX_RETRANS (1U << IRQN_BLE_TX_RETRANS) +#define IRQ_BLE_TX_ENTRY_DONE (1U << IRQN_BLE_TX_ENTRY_DONE) +#define IRQ_BLE_TX_BUFFER_CHANGED (1U << IRQN_BLE_TX_BUFFER_CHANGED) +#define IRQ_BLE_RX_OK (1U << IRQN_BLE_RX_OK) +#define IRQ_BLE_RX_NOK (1U << IRQN_BLE_RX_NOK) +#define IRQ_BLE_RX_IGNORED (1U << IRQN_BLE_RX_IGNORED) +#define IRQ_BLE_RX_EMPTY (1U << IRQN_BLE_RX_EMPTY) +#define IRQ_BLE_RX_CTRL (1U << IRQN_BLE_RX_CTRL) +#define IRQ_BLE_RX_CTRL_ACK (1U << IRQN_BLE_RX_CTRL_ACK) +#define IRQ_BLE_RX_BUF_FULL (1U << IRQN_BLE_RX_BUF_FULL) +#define IRQ_BLE_RX_ENTRY_DONE (1U << IRQN_BLE_RX_ENTRY_DONE) +///@} + + + +/// \name Radio operation status +/// Radio operation status format: +/// Bits 15:12: Protocol +/// 0001: BLE +/// Bits 11:10: Type +/// 00: Not finished +/// 01: Done successfully +/// 10: Done with error +/// Bits 9:0: Identifier + +/// \name Operation finished normally +///@{ +#define BLE_DONE_OK 0x1400 ///< Operation ended normally +#define BLE_DONE_RXTIMEOUT 0x1401 ///< Timeout of first Rx of slave operation or end of scan window +#define BLE_DONE_NOSYNC 0x1402 ///< Timeout of subsequent Rx +#define BLE_DONE_RXERR 0x1403 ///< Operation ended because of receive error (CRC or other) +#define BLE_DONE_CONNECT 0x1404 ///< CONNECT_REQ received or transmitted +#define BLE_DONE_MAXNACK 0x1405 ///< Maximum number of retransmissions exceeded +#define BLE_DONE_ENDED 0x1406 ///< Operation stopped after end trigger +#define BLE_DONE_ABORT 0x1407 ///< Operation aborted by command +#define BLE_DONE_STOPPED 0x1408 ///< Operation stopped after stop command +///@} +/// \name Operation finished with error +///@{ +#define BLE_ERROR_PAR 0x1800 ///< Illegal parameter +#define BLE_ERROR_RXBUF 0x1801 ///< No available Rx buffer (Advertiser, Scanner, Initiator) +#define BLE_ERROR_NO_SETUP 0x1802 ///< Operation using Rx or Tx attemted when not in BLE mode +#define BLE_ERROR_NO_FS 0x1803 ///< Operation using Rx or Tx attemted without frequency synth configured +#define BLE_ERROR_SYNTH_PROG 0x1804 ///< Synthesizer programming failed to complete on time +#define BLE_ERROR_RXOVF 0x1805 ///< Receiver overflowed during operation +#define BLE_ERROR_TXUNF 0x1806 ///< Transmitter underflowed during operation +///@} +///@} + +#endif diff --git a/cpu/cc26xx/dev/rfc-api/common_cmd.h b/cpu/cc26xx/dev/rfc-api/common_cmd.h new file mode 100644 index 000000000..bae0a0200 --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/common_cmd.h @@ -0,0 +1,1043 @@ +/****************************************************************************** +* Filename: common_cmd.h +* Revised: $ $ +* Revision: $ $ +* +* Description: CC26xx API for common/generic commands +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef __COMMON_CMD_H +#define __COMMON_CMD_H + +#ifndef __RFC_STRUCT +#ifdef __GNUC__ +#define __RFC_STRUCT __attribute__ ((aligned (4))) +#else +#define __RFC_STRUCT +#endif +#endif + +//! \addtogroup rfc +//! @{ + +//! \addtogroup common_cmd +//! @{ + +#include +#include "mailbox.h" + +typedef struct __RFC_STRUCT rfc_CMD_FG_SCH_IMM_s rfc_CMD_FG_SCH_IMM_t; +typedef struct __RFC_STRUCT rfc_CMD_WRITE_FWPAR_s rfc_CMD_WRITE_FWPAR_t; +typedef struct __RFC_STRUCT rfc_CMD_TX_TEST_s rfc_CMD_TX_TEST_t; +typedef struct __RFC_STRUCT rfc_CMD_RX_TEST_s rfc_CMD_RX_TEST_t; +typedef struct __RFC_STRUCT rfc_CMD_FS_POWERDOWN_s rfc_CMD_FS_POWERDOWN_t; +typedef struct __RFC_STRUCT rfc_CMD_DISARM_RAT_CH_s rfc_CMD_DISARM_RAT_CH_t; +typedef struct __RFC_STRUCT rfc_CMD_SCH_IMM_s rfc_CMD_SCH_IMM_t; +typedef struct __RFC_STRUCT rfc_CMD_ANALOG_POWERDOWN_s rfc_CMD_ANALOG_POWERDOWN_t; +typedef struct __RFC_STRUCT rfc_CMD_SET_RAT_CMP_s rfc_CMD_SET_RAT_CMP_t; +typedef struct __RFC_STRUCT rfc_CMD_FS_OFF_s rfc_CMD_FS_OFF_t; +typedef struct __RFC_STRUCT rfc_CMD_ENABLE_DBG_s rfc_CMD_ENABLE_DBG_t; +typedef struct __RFC_STRUCT rfc_CMD_CLEAR_RX_s rfc_CMD_CLEAR_RX_t; +typedef struct __RFC_STRUCT rfc_CMD_FS_s rfc_CMD_FS_t; +typedef struct __RFC_STRUCT rfc_CMD_FG_COUNT_BRANCH_s rfc_CMD_FG_COUNT_BRANCH_t; +typedef struct __RFC_STRUCT rfc_CMD_GET_FW_INFO_s rfc_CMD_GET_FW_INFO_t; +typedef struct __RFC_STRUCT rfc_CMD_TOPSM_COPY_s rfc_CMD_TOPSM_COPY_t; +typedef struct __RFC_STRUCT rfc_CMD_USER_FUN_s rfc_CMD_USER_FUN_t; +typedef struct __RFC_STRUCT rfc_command_s rfc_command_t; +typedef struct __RFC_STRUCT rfc_CMD_WRITE_ADI0REG_s rfc_CMD_WRITE_ADI0REG_t; +typedef struct __RFC_STRUCT rfc_CMD_FS_POWERUP_s rfc_CMD_FS_POWERUP_t; +typedef struct __RFC_STRUCT rfc_CMD_SYNC_STOP_RAT_s rfc_CMD_SYNC_STOP_RAT_t; +typedef struct __RFC_STRUCT rfc_CMD_ADD_DATA_ENTRY_s rfc_CMD_ADD_DATA_ENTRY_t; +typedef struct __RFC_STRUCT rfc_CMD_FG_COUNT_s rfc_CMD_FG_COUNT_t; +typedef struct __RFC_STRUCT rfc_CMD_MEMCPY_s rfc_CMD_MEMCPY_t; +typedef struct __RFC_STRUCT rfc_CMD_SET_RAT_CPT_s rfc_CMD_SET_RAT_CPT_t; +typedef struct __RFC_STRUCT rfc_CMD_DISABLE_DBG_s rfc_CMD_DISABLE_DBG_t; +typedef struct __RFC_STRUCT rfc_CMD_SYNC_START_RAT_s rfc_CMD_SYNC_START_RAT_t; +typedef struct __RFC_STRUCT rfc_CMD_COUNT_s rfc_CMD_COUNT_t; +typedef struct __RFC_STRUCT rfc_CMD_PATTERN_CHECK_s rfc_CMD_PATTERN_CHECK_t; +typedef struct __RFC_STRUCT rfc_CMD_MODIFY_RFREG_s rfc_CMD_MODIFY_RFREG_t; +typedef struct __RFC_STRUCT rfc_CMD_REMOVE_PENDING_ENTRIES_s rfc_CMD_REMOVE_PENDING_ENTRIES_t; +typedef struct __RFC_STRUCT rfc_CMD_UPDATE_RADIO_SETUP_s rfc_CMD_UPDATE_RADIO_SETUP_t; +typedef struct __RFC_STRUCT rfc_CMD_NOP_s rfc_CMD_NOP_t; +typedef struct __RFC_STRUCT rfc_CMD_STOP_s rfc_CMD_STOP_t; +typedef struct __RFC_STRUCT rfc_CMD_TRIGGER_s rfc_CMD_TRIGGER_t; +typedef struct __RFC_STRUCT rfc_CMD_SET_TRIM_s rfc_CMD_SET_TRIM_t; +typedef struct __RFC_STRUCT rfc_CMD_UPDATE_BAW_FREQ_s rfc_CMD_UPDATE_BAW_FREQ_t; +typedef struct __RFC_STRUCT rfc_CMD_READ_FWPAR_s rfc_CMD_READ_FWPAR_t; +typedef struct __RFC_STRUCT rfc_CMD_REMOVE_DATA_ENTRY_s rfc_CMD_REMOVE_DATA_ENTRY_t; +typedef struct __RFC_STRUCT rfc_CMD_UPDATE_FS_s rfc_CMD_UPDATE_FS_t; +typedef struct __RFC_STRUCT rfc_CMD_ARM_RAT_CH_s rfc_CMD_ARM_RAT_CH_t; +typedef struct __RFC_STRUCT rfc_CMD_WRITE_RFREG_s rfc_CMD_WRITE_RFREG_t; +typedef struct __RFC_STRUCT rfc_CMD_SET_TX_SHAPE_s rfc_CMD_SET_TX_SHAPE_t; +typedef struct __RFC_STRUCT rfc_CMD_READ_ADI1REG_s rfc_CMD_READ_ADI1REG_t; +typedef struct __RFC_STRUCT rfc_CMD_WRITE_ADDR_s rfc_CMD_WRITE_ADDR_t; +typedef struct __RFC_STRUCT rfc_CMD_PING_s rfc_CMD_PING_t; +typedef struct __RFC_STRUCT rfc_CMD_SET_RAT_OUTPUT_s rfc_CMD_SET_RAT_OUTPUT_t; +typedef struct __RFC_STRUCT rfc_CMD_DISABLE_RAT_CH_s rfc_CMD_DISABLE_RAT_CH_t; +typedef struct __RFC_STRUCT rfc_CMD_GET_RSSI_s rfc_CMD_GET_RSSI_t; +typedef struct __RFC_STRUCT rfc_CMD_MEMSET_s rfc_CMD_MEMSET_t; +typedef struct __RFC_STRUCT rfc_CMD_COUNT_BRANCH_s rfc_CMD_COUNT_BRANCH_t; +typedef struct __RFC_STRUCT rfc_CMD_ABORT_s rfc_CMD_ABORT_t; +typedef struct __RFC_STRUCT rfc_CMD_TX_s rfc_CMD_TX_t; +typedef struct __RFC_STRUCT rfc_radioOp_s rfc_radioOp_t; +typedef struct __RFC_STRUCT rfc_CMD_FORCE_CLK_ENA_s rfc_CMD_FORCE_CLK_ENA_t; +typedef struct __RFC_STRUCT rfc_CMD_START_RAT_s rfc_CMD_START_RAT_t; +typedef struct __RFC_STRUCT rfc_CMD_READ_RFREG_s rfc_CMD_READ_RFREG_t; +typedef struct __RFC_STRUCT rfc_CMD_RX_s rfc_CMD_RX_t; +typedef struct __RFC_STRUCT rfc_CMD_FG_PATTERN_CHECK_s rfc_CMD_FG_PATTERN_CHECK_t; +typedef struct __RFC_STRUCT rfc_CMD_SET_TX_POWER_s rfc_CMD_SET_TX_POWER_t; +typedef struct __RFC_STRUCT rfc_CMD_BUS_REQUEST_s rfc_CMD_BUS_REQUEST_t; +typedef struct __RFC_STRUCT rfc_CMD_READ_TRIM_s rfc_CMD_READ_TRIM_t; +typedef struct __RFC_STRUCT rfc_CMD_READ_ADI0REG_s rfc_CMD_READ_ADI0REG_t; +typedef struct __RFC_STRUCT rfc_CMD_WRITE_ADI1REG_s rfc_CMD_WRITE_ADI1REG_t; +typedef struct __RFC_STRUCT rfc_CMD_RADIO_SETUP_s rfc_CMD_RADIO_SETUP_t; +typedef struct __RFC_STRUCT rfc_CMD_READ_FS_CAL_s rfc_CMD_READ_FS_CAL_t; +typedef struct __RFC_STRUCT rfc_CMD_FG_NOP_s rfc_CMD_FG_NOP_t; +typedef struct __RFC_STRUCT rfc_CMD_FLUSH_QUEUE_s rfc_CMD_FLUSH_QUEUE_t; + +//! \addtogroup command +//! @{ +struct __RFC_STRUCT rfc_command_s { + uint16_t commandNo; //!< The command ID number +}; + +//! @} + +//! \addtogroup radioOp +//! @{ +//! Common definition for radio operation commands + +struct __RFC_STRUCT rfc_radioOp_s { + uint16_t commandNo; //!< The command ID number + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; +}; + +//! @} + +//! \addtogroup CMD_NOP +//! @{ +#define CMD_NOP 0x0801 +struct __RFC_STRUCT rfc_CMD_NOP_s { + uint16_t commandNo; //!< The command ID number 0x0801 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; +}; + +//! @} + +//! \addtogroup CMD_RADIO_SETUP +//! @{ +#define CMD_RADIO_SETUP 0x0802 +struct __RFC_STRUCT rfc_CMD_RADIO_SETUP_s { + uint16_t commandNo; //!< The command ID number 0x0802 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t mode; //!< \brief The main mode to use
+ //!< 0x00: BLE
+ //!< 0x01: IEEE 802.15.4
+ //!< 0x02: 2 Mbps GFSK
+ //!< 0x05: 5 Mbps coded 8-FSK
+ //!< 0x06: ANT
+ //!< 0xFF: Keep existing mode; update overrides only
+ //!< Others: Reserved + uint8_t __dummy0; + struct { + uint16_t frontEndMode:3; //!< \brief 0x00: Differential mode
+ //!< 0x01: Single-ended mode RFP
+ //!< 0x02: Single-ended mode RFN
+ //!< 0x03: Antenna diversity (start RFP)
+ //!< 0x04: Antenna diversity (start RFN)
+ //!< 0x05 Single-ended mode RFP with external frontend control on RF pins
+ //!< 0x06 Single-ended mode RFN with external frontend control on RF pins
+ //!< Others: Reserved + uint16_t biasMode:1; //!< \brief 0: Internal bias
+ //!< 1: External bias + uint16_t bNoAdi0Setup:1; //!< \brief 0: Program ADI 0 with default values
+ //!< 1: Do not program ADI 0 + uint16_t bNoAdi0Trim:1; //!< \brief 0: Apply trim values to ADI 0
+ //!< 1: Use default values for ADI 0 + uint16_t bNoAdi0Ovr:1; //!< \brief 0: Apply ADI 0 overrides
+ //!< 1: Ignore ADI 0 overrides + uint16_t bNoAdi1Setup:1; //!< \brief 0: Program ADI 1 with default values
+ //!< 1: Do not program ADI 1 + uint16_t bNoAdi1Trim:1; //!< \brief 0: Apply trim values to ADI 1
+ //!< 1: Use default values for ADI 1 + uint16_t bNoAdi1Ovr:1; //!< \brief 0: Apply ADI 1 overrides
+ //!< 1: Ignore ADI 1 overrides + uint16_t bNoFsPowerUp:1; //!< \brief 0: Power up frequency synth
+ //!< 1: Do not power up frequency synth + } config; //!< Configuration options + struct { + uint16_t IB:6; //!< Value to write to the PA power control field at 25 °C + uint16_t GC:2; //!< Value to write to the gain control of the 1st stage of the PA + uint16_t tempCoeff:8; //!< Temperature coefficient for IB. 0: No temperature compensation + } txPower; //!< Transmit power + uint32_t* pRegOverride; //!< \brief Pointer to a list of hardware and configuration registers to override. If NULL, no + //!< override is used. +}; + +//! @} + +//! \addtogroup CMD_FS +//! @{ +#define CMD_FS 0x0803 +struct __RFC_STRUCT rfc_CMD_FS_s { + uint16_t commandNo; //!< The command ID number 0x0803 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t frequency; //!< The frequency in MHz to tune to + uint16_t fractFreq; //!< Fractional part of the frequency to tune to + struct { + uint8_t bTxMode:1; //!< \brief 0: Start synth in Rx mode
+ //!< 1: Start synth in Tx mode + uint8_t refFreq:6; //!< Reserved + } synthConf; + struct { + uint8_t bOverrideCalib:1; //!< \brief 0: Use standard calibration settings (ignore calibration settings given in command)
+ //!< 1: Override calibration settings + uint8_t bSkipTdcCalib:1; //!< \brief 0: Perform TDC calibration
+ //!< 1: Skip TDC calibration + uint8_t bSkipCoarseCalib:1; //!< \brief 0: Perform coarse calibration
+ //!< 1: Skip coarse calibration + uint8_t bSkipMidCalib:1; //!< \brief 0: Perform mid calibration
+ //!< 1: Skip mid calibration + uint8_t coarsePrecal:4; //!< \brief Coarse pre-calibration value to use when bOverrideCalib and + //!< bSkipCoarseCalib are both 1 + } calibConf; + uint8_t midPrecal; //!< Mid pre-calibration value to use when bOverrideCalib and bSkipCoarseCalib are both 1 + uint8_t ktPrecal; //!< KT pre-calibration value to use when bOverrideCalib and bSkipCoarseCalib are both 1 + uint16_t tdcPrecal; //!< TDC pre-calibration value to use when bOverrideCalib and bSkipCoarseCalib are both 1 +}; + +//! @} + +//! \addtogroup CMD_FS_OFF +//! @{ +#define CMD_FS_OFF 0x0804 +struct __RFC_STRUCT rfc_CMD_FS_OFF_s { + uint16_t commandNo; //!< The command ID number 0x0804 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; +}; + +//! @} + +//! \addtogroup CMD_RX +//! @{ +#define CMD_RX 0x0805 +struct __RFC_STRUCT rfc_CMD_RX_s { + uint16_t commandNo; //!< The command ID number 0x0805 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + struct { + uint16_t endianness:1; //!< \brief 0: Least significant bit first
+ //!< 1: Most significant bit first + uint16_t numHdrBits:6; //!< Number of bits in the header + uint16_t bFsOff:1; //!< \brief 0: Keep frequency synth on after command
+ //!< 1: Turn frequency synth off after command + uint16_t bUseCrc:1; //!< \brief 0: No CRC
+ //!< 1: The last bytes of the packet are a CRC + uint16_t bCrcIncSw:1; //!< \brief 0: Do not include sync word in CRC calculation
+ //!< 1: Include sync word in CRC calculation + uint16_t bCrcIncHdr:1; //!< \brief 0: Do not include header in CRC calculation
+ //!< 1: Include header in CRC calculation + uint16_t bReportCrc:1; //!< \brief 0: Do not write CRC to receive buffer
+ //!< 1: Write received CRC to receive buffer + uint16_t endType:1; //!< \brief 0: Packet is received to the end if end trigger happens after sync is obtained
+ //!< 1: Packet reception is stopped if end trigger happens + uint16_t bDualSw:1; //!< \brief 0: Single sync word
+ //!< 1: Dual sync word. + } pktConfig; + uint32_t syncWord; //!< Sync word to receive + uint32_t syncWord2; //!< Secondary sync word to receive if pktConfig.bDualSw = 1 + struct { + uint16_t numLenBits:4; //!< Number of bits in the length field + uint16_t lenFieldPos:5; //!< Bit position of the first bit in the length field + uint16_t lenOffset:7; //!< Signed number to add to the received length field + } lenConfig; + uint16_t maxLen; //!< Maximum number of bytes in the received packet (including header, excluding CRC) + uint8_t* pRecPkt; //!< Pointer to buffer for received packet. NULL: Do not store the contents. + ratmr_t endTime; //!< Time to end the operation + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger classifier for ending the operation + int8_t rssi; //!< RSSI of received packet + uint16_t recLen; //!< Number of bytes written to receive buffer + ratmr_t timeStamp; //!< Time stamp of received packet + uint16_t nRxOk; //!< Counter of number of received packets with CRC OK and first sync word + uint16_t nRxNok; //!< Counter of number of received packets with CRC error and first sync word + uint16_t nRx2Ok; //!< \brief Counter of number of received packets with CRC OK and second sync word; may safely be + //!< omitted if pktConfig.bDualSw is 0 + uint16_t nRx2Nok; //!< \brief Counter of number of received packets with CRC error and second sync word; may safely be + //!< omitted if pktConfig.bDualSw is 0 +}; + +//! @} + +//! \addtogroup CMD_TX +//! @{ +#define CMD_TX 0x0806 +struct __RFC_STRUCT rfc_CMD_TX_s { + uint16_t commandNo; //!< The command ID number 0x0806 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + struct { + uint16_t endianness:1; //!< \brief 0: Least significant bit first
+ //!< 1: Most significant bit first + uint16_t numHdrBits:6; //!< Number of bits in the header + uint16_t bFsOff:1; //!< \brief 0: Keep frequency synth on after command
+ //!< 1: Turn frequency synth off after command + uint16_t bUseCrc:1; //!< \brief 0: No CRC
+ //!< 1: Append a CRC to the packet + uint16_t bCrcIncSw:1; //!< \brief 0: Do not include sync word in CRC calculation
+ //!< 1: Include sync word in CRC calculation + uint16_t bCrcIncHdr:1; //!< \brief 0: Do not include header in CRC calculation
+ //!< 1: Include header in CRC calculation + } pktConfig; + uint32_t syncWord; //!< Sync word to transmit + uint8_t* pTxPkt; //!< Pointer to buffer for transmitted packet. + uint16_t pktLen; //!< Number of bytes in the transmitted packet +}; + +//! @} + +//! \addtogroup CMD_RX_TEST +//! @{ +#define CMD_RX_TEST 0x0807 +struct __RFC_STRUCT rfc_CMD_RX_TEST_s { + uint16_t commandNo; //!< The command ID number 0x0807 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + struct { + uint8_t bEnaFifo:1; //!< \brief 0: Do not enable FIFO in modem, so that received data is not available
+ //!< 1: Enable FIFO in modem – the data must be read out by the application + uint8_t bFsOff:1; //!< \brief 0: Keep frequency synth on after command
+ //!< 1: Turn frequency synth off after command + uint8_t bNoSync:1; //!< \brief 0: Run sync search as normal for the configured mode
+ //!< 1: Write correlation thresholds to the maximum value to avoid getting sync + } config; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger classifier for ending the operation + uint32_t syncWord; //!< Sync word to use for receiver + ratmr_t endTime; //!< Time to end the operation +}; + +//! @} + +//! \addtogroup CMD_TX_TEST +//! @{ +#define CMD_TX_TEST 0x0808 +struct __RFC_STRUCT rfc_CMD_TX_TEST_s { + uint16_t commandNo; //!< The command ID number 0x0808 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + struct { + uint8_t bUseCw:1; //!< \brief 0: Send modulated signal
+ //!< 1: Send continuous wave + uint8_t bFsOff:1; //!< \brief 0: Keep frequency synth on after command
+ //!< 1: Turn frequency synth off after command + uint8_t whitenMode:2; //!< \brief 0: No whitening
+ //!< 1: Default whitening
+ //!< 2: PRBS-15
+ //!< 3: PRBS-32 + } config; + uint8_t __dummy0; + uint16_t txWord; //!< Value to send to the modem before whitening + uint8_t __dummy1; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger classifier for ending the operation + uint32_t syncWord; //!< Sync word to use for transmitter + ratmr_t endTime; //!< Time to end the operation +}; + +//! @} + +//! \addtogroup CMD_SYNC_STOP_RAT +//! @{ +#define CMD_SYNC_STOP_RAT 0x0809 +struct __RFC_STRUCT rfc_CMD_SYNC_STOP_RAT_s { + uint16_t commandNo; //!< The command ID number 0x0809 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t __dummy0; + ratmr_t rat0; //!< \brief The returned RAT timer value corresponding to the value the RAT would have had when the + //!< RTC was zero +}; + +//! @} + +//! \addtogroup CMD_SYNC_START_RAT +//! @{ +#define CMD_SYNC_START_RAT 0x080A +struct __RFC_STRUCT rfc_CMD_SYNC_START_RAT_s { + uint16_t commandNo; //!< The command ID number 0x080A + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t __dummy0; + ratmr_t rat0; //!< \brief The desired RAT timer value corresponding to the value the RAT would have had when the + //!< RTC was zero. This parameter is returned by CMD_SYNC_STOP_RAT +}; + +//! @} + +//! \addtogroup CMD_COUNT +//! @{ +#define CMD_COUNT 0x080B +struct __RFC_STRUCT rfc_CMD_COUNT_s { + uint16_t commandNo; //!< The command ID number 0x080B + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t counter; //!< \brief Counter. On start, the radio CPU decrements the value, and the end status of the operation + //!< differs if the result is zero +}; + +//! @} + +//! \addtogroup CMD_FS_POWERUP +//! @{ +#define CMD_FS_POWERUP 0x080C +struct __RFC_STRUCT rfc_CMD_FS_POWERUP_s { + uint16_t commandNo; //!< The command ID number 0x080C + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t __dummy0; + uint32_t* pRegOverride; //!< Pointer to a list of hardware and configuration registers to override. If NULL, no override is used. +}; + +//! @} + +//! \addtogroup CMD_FS_POWERDOWN +//! @{ +#define CMD_FS_POWERDOWN 0x080D +struct __RFC_STRUCT rfc_CMD_FS_POWERDOWN_s { + uint16_t commandNo; //!< The command ID number 0x080D + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; +}; + +//! @} + +//! \addtogroup CMD_SCH_IMM +//! @{ +#define CMD_SCH_IMM 0x0810 +struct __RFC_STRUCT rfc_CMD_SCH_IMM_s { + uint16_t commandNo; //!< The command ID number 0x0810 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t __dummy0; + uint32_t cmdrVal; //!< Value as would be written to CMDR + uint32_t cmdstaVal; //!< Value as would be returned in CMDSTA +}; + +//! @} + +//! \addtogroup CMD_COUNT_BRANCH +//! @{ +#define CMD_COUNT_BRANCH 0x0812 +struct __RFC_STRUCT rfc_CMD_COUNT_BRANCH_s { + uint16_t commandNo; //!< The command ID number 0x0812 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t counter; //!< \brief Counter. On start, the radio CPU decrements the value, and the end status of the operation + //!< differs if the result is zero + rfc_radioOp_t *pNextOpIfOk; //!< Pointer to next operation if counter did not expire +}; + +//! @} + +//! \addtogroup CMD_PATTERN_CHECK +//! @{ +#define CMD_PATTERN_CHECK 0x0813 +struct __RFC_STRUCT rfc_CMD_PATTERN_CHECK_s { + uint16_t commandNo; //!< The command ID number 0x0813 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + struct { + uint16_t operation:2; //!< \brief Operation to perform
+ //!< 0: True if value == compareVal
+ //!< 1: True if value < compareVal
+ //!< 2: True if value > compareVal
+ //!< 3: Reserved + uint16_t bByteRev:1; //!< \brief If 1, interchange the four bytes of the value, so that they are read + //!< most-significant-byte-first. + uint16_t bBitRev:1; //!< If 1, perform bit reversal of the value + uint16_t signExtend:5; //!< \brief 0: Treat value and compareVal as unsigned
+ //!< 1–31: Treat value and compareVal as signed, where the value + //!< gives the number of the most significant bit in the signed number. + uint16_t bRxVal:1; //!< \brief 0: Use pValue as a pointer
+ //!< 1: Use pValue as a signed offset to the start of the last + //!< committed Rx entry element + } patternOpt; //!< Options for comparison + rfc_radioOp_t *pNextOpIfOk; //!< Pointer to next operation if comparison result was true + uint8_t* pValue; //!< Pointer to read from, or offset from last Rx entry if patternOpt.bRxVal == 1 + uint32_t mask; //!< Bit mask to apply before comparison + uint32_t compareVal; //!< Value to compare to +}; + +//! @} + +//! \addtogroup CMD_ABORT +//! @{ +#define CMD_ABORT 0x0401 +struct __RFC_STRUCT rfc_CMD_ABORT_s { + uint16_t commandNo; //!< The command ID number 0x0401 +}; + +//! @} + +//! \addtogroup CMD_STOP +//! @{ +#define CMD_STOP 0x0402 +struct __RFC_STRUCT rfc_CMD_STOP_s { + uint16_t commandNo; //!< The command ID number 0x0402 +}; + +//! @} + +//! \addtogroup CMD_GET_RSSI +//! @{ +#define CMD_GET_RSSI 0x0403 +struct __RFC_STRUCT rfc_CMD_GET_RSSI_s { + uint16_t commandNo; //!< The command ID number 0x0403 +}; + +//! @} + +//! \addtogroup CMD_UPDATE_RADIO_SETUP +//! @{ +#define CMD_UPDATE_RADIO_SETUP 0x0001 +struct __RFC_STRUCT rfc_CMD_UPDATE_RADIO_SETUP_s { + uint16_t commandNo; //!< The command ID number 0x0001 + uint16_t __dummy0; + uint32_t* pRegOverride; //!< Pointer to a list of hardware and configuration registers to override +}; + +//! @} + +//! \addtogroup CMD_TRIGGER +//! @{ +#define CMD_TRIGGER 0x0404 +struct __RFC_STRUCT rfc_CMD_TRIGGER_s { + uint16_t commandNo; //!< The command ID number 0x0404 + uint8_t triggerNo; //!< Command trigger number +}; + +//! @} + +//! \addtogroup CMD_GET_FW_INFO +//! @{ +#define CMD_GET_FW_INFO 0x0002 +struct __RFC_STRUCT rfc_CMD_GET_FW_INFO_s { + uint16_t commandNo; //!< The command ID number 0x0002 + uint16_t versionNo; //!< Firmware version number + uint16_t startOffset; //!< The start of free RAM + uint16_t freeRamSz; //!< The size of free RAM + uint16_t availRatCh; //!< Bitmap of available RAT channels +}; + +//! @} + +//! \addtogroup CMD_START_RAT +//! @{ +#define CMD_START_RAT 0x0405 +struct __RFC_STRUCT rfc_CMD_START_RAT_s { + uint16_t commandNo; //!< The command ID number 0x0405 +}; + +//! @} + +//! \addtogroup CMD_PING +//! @{ +#define CMD_PING 0x0406 +struct __RFC_STRUCT rfc_CMD_PING_s { + uint16_t commandNo; //!< The command ID number 0x0406 +}; + +//! @} + +//! \addtogroup CMD_ADD_DATA_ENTRY +//! @{ +#define CMD_ADD_DATA_ENTRY 0x0005 +struct __RFC_STRUCT rfc_CMD_ADD_DATA_ENTRY_s { + uint16_t commandNo; //!< The command ID number 0x0005 + uint16_t __dummy0; + dataQueue_t* pQueue; //!< Pointer to the queue structure to which the entry will be added + uint8_t* pEntry; //!< Pointer to the entry +}; + +//! @} + +//! \addtogroup CMD_REMOVE_DATA_ENTRY +//! @{ +#define CMD_REMOVE_DATA_ENTRY 0x0006 +struct __RFC_STRUCT rfc_CMD_REMOVE_DATA_ENTRY_s { + uint16_t commandNo; //!< The command ID number 0x0006 + uint16_t __dummy0; + dataQueue_t* pQueue; //!< Pointer to the queue structure from which the entry will be removed + uint8_t* pEntry; //!< Pointer to the entry that was removed +}; + +//! @} + +//! \addtogroup CMD_FLUSH_QUEUE +//! @{ +#define CMD_FLUSH_QUEUE 0x0007 +struct __RFC_STRUCT rfc_CMD_FLUSH_QUEUE_s { + uint16_t commandNo; //!< The command ID number 0x0007 + uint16_t __dummy0; + dataQueue_t* pQueue; //!< Pointer to the queue structure to be flushed + uint8_t* pFirstEntry; //!< Pointer to the first entry that was removed +}; + +//! @} + +//! \addtogroup CMD_CLEAR_RX +//! @{ +#define CMD_CLEAR_RX 0x0008 +struct __RFC_STRUCT rfc_CMD_CLEAR_RX_s { + uint16_t commandNo; //!< The command ID number 0x0008 + uint16_t __dummy0; + dataQueue_t* pQueue; //!< Pointer to the queue structure to be cleared +}; + +//! @} + +//! \addtogroup CMD_REMOVE_PENDING_ENTRIES +//! @{ +#define CMD_REMOVE_PENDING_ENTRIES 0x0009 +struct __RFC_STRUCT rfc_CMD_REMOVE_PENDING_ENTRIES_s { + uint16_t commandNo; //!< The command ID number 0x0009 + uint16_t __dummy0; + dataQueue_t* pQueue; //!< Pointer to the queue structure to be flushed + uint8_t* pFirstEntry; //!< Pointer to the first entry that was removed +}; + +//! @} + +//! \addtogroup CMD_SET_RAT_CMP +//! @{ +#define CMD_SET_RAT_CMP 0x000A +struct __RFC_STRUCT rfc_CMD_SET_RAT_CMP_s { + uint16_t commandNo; //!< The command ID number 0x000A + uint8_t ratCh; //!< The radio timer channel number + uint8_t __dummy0; + ratmr_t compareTime; //!< The time at which the compare occurs +}; + +//! @} + +//! \addtogroup CMD_SET_RAT_CPT +//! @{ +#define CMD_SET_RAT_CPT 0x0603 +struct __RFC_STRUCT rfc_CMD_SET_RAT_CPT_s { + uint16_t commandNo; //!< The command ID number 0x0603 + struct { + uint16_t :3; + uint16_t inputSrc:5; //!< Input source indicator + uint16_t ratCh:4; //!< The radio timer channel number + uint16_t bRepeated:1; //!< \brief 0: Single capture mode
+ //!< 1: Repeated capture mode + uint16_t inputMode:2; //!< \brief Input mode:
+ //!< 0: Capture on rising edge
+ //!< 1: Capture on falling edge
+ //!< 2: Capture on both edges
+ //!< 3: Reserved + } config; +}; + +//! @} + +//! \addtogroup CMD_DISABLE_RAT_CH +//! @{ +#define CMD_DISABLE_RAT_CH 0x0408 +struct __RFC_STRUCT rfc_CMD_DISABLE_RAT_CH_s { + uint16_t commandNo; //!< The command ID number 0x0408 + uint8_t ratCh; //!< The radio timer channel number +}; + +//! @} + +//! \addtogroup CMD_SET_RAT_OUTPUT +//! @{ +#define CMD_SET_RAT_OUTPUT 0x0604 +struct __RFC_STRUCT rfc_CMD_SET_RAT_OUTPUT_s { + uint16_t commandNo; //!< The command ID number 0x0604 + struct { + uint16_t :2; + uint16_t outputSel:3; //!< Output event indicator + uint16_t outputMode:3; //!< \brief 0: Set output line low as default; and pulse on event. Duration of pulse is one RF Core clock period (ca. 41.67 ns).
+ //!< 1: Set output line high on event
+ //!< 2: Set output line low on event
+ //!< 3: Toggle (invert) output line state on event
+ //!< 4: Immediately set output line to low (does not change upon event)
+ //!< 5: Immediately set output line to high (does not change upon event)
+ //!< Others: Reserved + uint16_t ratCh:4; //!< The radio timer channel number + } config; +}; + +//! @} + +//! \addtogroup CMD_ARM_RAT_CH +//! @{ +#define CMD_ARM_RAT_CH 0x0409 +struct __RFC_STRUCT rfc_CMD_ARM_RAT_CH_s { + uint16_t commandNo; //!< The command ID number 0x0409 + uint8_t ratCh; //!< The radio timer channel number +}; + +//! @} + +//! \addtogroup CMD_DISARM_RAT_CH +//! @{ +#define CMD_DISARM_RAT_CH 0x040A +struct __RFC_STRUCT rfc_CMD_DISARM_RAT_CH_s { + uint16_t commandNo; //!< The command ID number 0x040A + uint8_t ratCh; //!< The radio timer channel number +}; + +//! @} + +//! \addtogroup CMD_SET_TX_POWER +//! @{ +#define CMD_SET_TX_POWER 0x0010 +struct __RFC_STRUCT rfc_CMD_SET_TX_POWER_s { + uint16_t commandNo; //!< The command ID number 0x0010 + struct { + uint16_t IB:6; //!< Value to write to the PA power control field at 25 °C + uint16_t GC:2; //!< Value to write to the gain control of the 1st stage of the PA + uint16_t tempCoeff:8; //!< Temperature coefficient for IB. 0: No temperature compensation + } txPower; //!< New Tx power setting +}; + +//! @} + +//! \addtogroup CMD_UPDATE_FS +//! @{ +#define CMD_UPDATE_FS 0x0011 +struct __RFC_STRUCT rfc_CMD_UPDATE_FS_s { + uint16_t commandNo; //!< The command ID number 0x0011 + uint16_t frequency; //!< The frequency in MHz to tune to + uint16_t fractFreq; //!< Fractional part of the frequency to tune to +}; + +//! @} + +//! \addtogroup CMD_BUS_REQUEST +//! @{ +#define CMD_BUS_REQUEST 0x040E +struct __RFC_STRUCT rfc_CMD_BUS_REQUEST_s { + uint16_t commandNo; //!< The command ID number 0x040E + uint8_t bSysBusNeeded; //!< \brief 0: System bus may sleep
+ //!< 1: System bus access needed +}; + +//! @} + +//! @} +//! @} +#endif diff --git a/cpu/cc26xx/dev/rfc-api/common_cmd_field.h b/cpu/cc26xx/dev/rfc-api/common_cmd_field.h new file mode 100755 index 000000000..d9e9431f6 --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/common_cmd_field.h @@ -0,0 +1,448 @@ +/****************************************************************************** +* Filename: common_cmd_field.h +* Revised: $ $ +* Revision: $ $ +* +* Description: CC26xx API for common/generic commands +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef __COMMON_CMD_FIELD_H +#define __COMMON_CMD_FIELD_H + +#include +#include "mailbox.h" + +#define _POSITION_command_commandNo 0 +#define _TYPE_command_commandNo uint16_t +#define _SIZEOF_command 2 + +#define _POSITION_radioOp_commandNo 0 +#define _TYPE_radioOp_commandNo uint16_t +#define _POSITION_radioOp_status 2 +#define _TYPE_radioOp_status uint16_t +#define _POSITION_radioOp_pNextOp 4 +#define _TYPE_radioOp_pNextOp uint8_t* +#define _POSITION_radioOp_startTime 8 +#define _TYPE_radioOp_startTime ratmr_t +#define _POSITION_radioOp_startTrigger 12 +#define _TYPE_radioOp_startTrigger uint8_t +#define _BITPOS_radioOp_startTrigger_triggerType 0 +#define _NBITS_radioOp_startTrigger_triggerType 4 +#define _BITPOS_radioOp_startTrigger_bEnaCmd 4 +#define _NBITS_radioOp_startTrigger_bEnaCmd 1 +#define _BITPOS_radioOp_startTrigger_triggerNo 5 +#define _NBITS_radioOp_startTrigger_triggerNo 2 +#define _BITPOS_radioOp_startTrigger_pastTrig 7 +#define _NBITS_radioOp_startTrigger_pastTrig 1 +#define _POSITION_radioOp_condition 13 +#define _TYPE_radioOp_condition uint8_t +#define _BITPOS_radioOp_condition_rule 0 +#define _NBITS_radioOp_condition_rule 4 +#define _BITPOS_radioOp_condition_nSkip 4 +#define _NBITS_radioOp_condition_nSkip 4 +#define _SIZEOF_radioOp 14 + +#define _SIZEOF_CMD_NOP 14 + +#define _POSITION_CMD_RADIO_SETUP_mode 14 +#define _TYPE_CMD_RADIO_SETUP_mode uint8_t +#define _POSITION_CMD_RADIO_SETUP_config 16 +#define _TYPE_CMD_RADIO_SETUP_config uint16_t +#define _BITPOS_CMD_RADIO_SETUP_config_frontEndMode 0 +#define _NBITS_CMD_RADIO_SETUP_config_frontEndMode 3 +#define _BITPOS_CMD_RADIO_SETUP_config_biasMode 3 +#define _NBITS_CMD_RADIO_SETUP_config_biasMode 1 +#define _BITPOS_CMD_RADIO_SETUP_config_bNoAdi0Setup 4 +#define _NBITS_CMD_RADIO_SETUP_config_bNoAdi0Setup 1 +#define _BITPOS_CMD_RADIO_SETUP_config_bNoAdi0Trim 5 +#define _NBITS_CMD_RADIO_SETUP_config_bNoAdi0Trim 1 +#define _BITPOS_CMD_RADIO_SETUP_config_bNoAdi0Ovr 6 +#define _NBITS_CMD_RADIO_SETUP_config_bNoAdi0Ovr 1 +#define _BITPOS_CMD_RADIO_SETUP_config_bNoAdi1Setup 7 +#define _NBITS_CMD_RADIO_SETUP_config_bNoAdi1Setup 1 +#define _BITPOS_CMD_RADIO_SETUP_config_bNoAdi1Trim 8 +#define _NBITS_CMD_RADIO_SETUP_config_bNoAdi1Trim 1 +#define _BITPOS_CMD_RADIO_SETUP_config_bNoAdi1Ovr 9 +#define _NBITS_CMD_RADIO_SETUP_config_bNoAdi1Ovr 1 +#define _BITPOS_CMD_RADIO_SETUP_config_bNoFsPowerUp 10 +#define _NBITS_CMD_RADIO_SETUP_config_bNoFsPowerUp 1 +#define _POSITION_CMD_RADIO_SETUP_txPower 18 +#define _TYPE_CMD_RADIO_SETUP_txPower uint16_t +#define _BITPOS_CMD_RADIO_SETUP_txPower_IB 0 +#define _NBITS_CMD_RADIO_SETUP_txPower_IB 6 +#define _BITPOS_CMD_RADIO_SETUP_txPower_GC 6 +#define _NBITS_CMD_RADIO_SETUP_txPower_GC 2 +#define _BITPOS_CMD_RADIO_SETUP_txPower_tempCoeff 8 +#define _NBITS_CMD_RADIO_SETUP_txPower_tempCoeff 8 +#define _POSITION_CMD_RADIO_SETUP_pRegOverride 20 +#define _TYPE_CMD_RADIO_SETUP_pRegOverride uint32_t* +#define _SIZEOF_CMD_RADIO_SETUP 24 + +#define _POSITION_CMD_FS_frequency 14 +#define _TYPE_CMD_FS_frequency uint16_t +#define _POSITION_CMD_FS_fractFreq 16 +#define _TYPE_CMD_FS_fractFreq uint16_t +#define _POSITION_CMD_FS_synthConf 18 +#define _TYPE_CMD_FS_synthConf uint8_t +#define _BITPOS_CMD_FS_synthConf_bTxMode 0 +#define _NBITS_CMD_FS_synthConf_bTxMode 1 +#define _BITPOS_CMD_FS_synthConf_refFreq 1 +#define _NBITS_CMD_FS_synthConf_refFreq 6 +#define _POSITION_CMD_FS_calibConf 19 +#define _TYPE_CMD_FS_calibConf uint8_t +#define _BITPOS_CMD_FS_calibConf_bOverrideCalib 0 +#define _NBITS_CMD_FS_calibConf_bOverrideCalib 1 +#define _BITPOS_CMD_FS_calibConf_bSkipTdcCalib 1 +#define _NBITS_CMD_FS_calibConf_bSkipTdcCalib 1 +#define _BITPOS_CMD_FS_calibConf_bSkipCoarseCalib 2 +#define _NBITS_CMD_FS_calibConf_bSkipCoarseCalib 1 +#define _BITPOS_CMD_FS_calibConf_bSkipMidCalib 3 +#define _NBITS_CMD_FS_calibConf_bSkipMidCalib 1 +#define _BITPOS_CMD_FS_calibConf_coarsePrecal 4 +#define _NBITS_CMD_FS_calibConf_coarsePrecal 4 +#define _POSITION_CMD_FS_midPrecal 20 +#define _TYPE_CMD_FS_midPrecal uint8_t +#define _POSITION_CMD_FS_ktPrecal 21 +#define _TYPE_CMD_FS_ktPrecal uint8_t +#define _POSITION_CMD_FS_tdcPrecal 22 +#define _TYPE_CMD_FS_tdcPrecal uint16_t +#define _SIZEOF_CMD_FS 24 + +#define _SIZEOF_CMD_FS_OFF 14 + +#define _POSITION_CMD_RX_pktConfig 14 +#define _TYPE_CMD_RX_pktConfig uint16_t +#define _BITPOS_CMD_RX_pktConfig_endianness 0 +#define _NBITS_CMD_RX_pktConfig_endianness 1 +#define _BITPOS_CMD_RX_pktConfig_numHdrBits 1 +#define _NBITS_CMD_RX_pktConfig_numHdrBits 6 +#define _BITPOS_CMD_RX_pktConfig_bFsOff 7 +#define _NBITS_CMD_RX_pktConfig_bFsOff 1 +#define _BITPOS_CMD_RX_pktConfig_bUseCrc 8 +#define _NBITS_CMD_RX_pktConfig_bUseCrc 1 +#define _BITPOS_CMD_RX_pktConfig_bCrcIncSw 9 +#define _NBITS_CMD_RX_pktConfig_bCrcIncSw 1 +#define _BITPOS_CMD_RX_pktConfig_bCrcIncHdr 10 +#define _NBITS_CMD_RX_pktConfig_bCrcIncHdr 1 +#define _BITPOS_CMD_RX_pktConfig_bReportCrc 11 +#define _NBITS_CMD_RX_pktConfig_bReportCrc 1 +#define _BITPOS_CMD_RX_pktConfig_endType 12 +#define _NBITS_CMD_RX_pktConfig_endType 1 +#define _BITPOS_CMD_RX_pktConfig_bDualSw 13 +#define _NBITS_CMD_RX_pktConfig_bDualSw 1 +#define _POSITION_CMD_RX_syncWord 16 +#define _TYPE_CMD_RX_syncWord uint32_t +#define _POSITION_CMD_RX_syncWord2 20 +#define _TYPE_CMD_RX_syncWord2 uint32_t +#define _POSITION_CMD_RX_lenConfig 24 +#define _TYPE_CMD_RX_lenConfig uint16_t +#define _BITPOS_CMD_RX_lenConfig_numLenBits 0 +#define _NBITS_CMD_RX_lenConfig_numLenBits 4 +#define _BITPOS_CMD_RX_lenConfig_lenFieldPos 4 +#define _NBITS_CMD_RX_lenConfig_lenFieldPos 5 +#define _BITPOS_CMD_RX_lenConfig_lenOffset 9 +#define _NBITS_CMD_RX_lenConfig_lenOffset 7 +#define _POSITION_CMD_RX_maxLen 26 +#define _TYPE_CMD_RX_maxLen uint16_t +#define _POSITION_CMD_RX_pRecPkt 28 +#define _TYPE_CMD_RX_pRecPkt uint8_t* +#define _POSITION_CMD_RX_endTime 32 +#define _TYPE_CMD_RX_endTime ratmr_t +#define _POSITION_CMD_RX_endTrigger 36 +#define _TYPE_CMD_RX_endTrigger uint8_t +#define _BITPOS_CMD_RX_endTrigger_triggerType 0 +#define _NBITS_CMD_RX_endTrigger_triggerType 4 +#define _BITPOS_CMD_RX_endTrigger_bEnaCmd 4 +#define _NBITS_CMD_RX_endTrigger_bEnaCmd 1 +#define _BITPOS_CMD_RX_endTrigger_triggerNo 5 +#define _NBITS_CMD_RX_endTrigger_triggerNo 2 +#define _BITPOS_CMD_RX_endTrigger_pastTrig 7 +#define _NBITS_CMD_RX_endTrigger_pastTrig 1 +#define _POSITION_CMD_RX_rssi 37 +#define _TYPE_CMD_RX_rssi int8_t +#define _POSITION_CMD_RX_recLen 38 +#define _TYPE_CMD_RX_recLen uint16_t +#define _POSITION_CMD_RX_timeStamp 40 +#define _TYPE_CMD_RX_timeStamp ratmr_t +#define _POSITION_CMD_RX_nRxOk 44 +#define _TYPE_CMD_RX_nRxOk uint16_t +#define _POSITION_CMD_RX_nRxNok 46 +#define _TYPE_CMD_RX_nRxNok uint16_t +#define _POSITION_CMD_RX_nRx2Ok 48 +#define _TYPE_CMD_RX_nRx2Ok uint16_t +#define _POSITION_CMD_RX_nRx2Nok 50 +#define _TYPE_CMD_RX_nRx2Nok uint16_t +#define _SIZEOF_CMD_RX 52 + +#define _POSITION_CMD_TX_pktConfig 14 +#define _TYPE_CMD_TX_pktConfig uint16_t +#define _BITPOS_CMD_TX_pktConfig_endianness 0 +#define _NBITS_CMD_TX_pktConfig_endianness 1 +#define _BITPOS_CMD_TX_pktConfig_numHdrBits 1 +#define _NBITS_CMD_TX_pktConfig_numHdrBits 6 +#define _BITPOS_CMD_TX_pktConfig_bFsOff 7 +#define _NBITS_CMD_TX_pktConfig_bFsOff 1 +#define _BITPOS_CMD_TX_pktConfig_bUseCrc 8 +#define _NBITS_CMD_TX_pktConfig_bUseCrc 1 +#define _BITPOS_CMD_TX_pktConfig_bCrcIncSw 9 +#define _NBITS_CMD_TX_pktConfig_bCrcIncSw 1 +#define _BITPOS_CMD_TX_pktConfig_bCrcIncHdr 10 +#define _NBITS_CMD_TX_pktConfig_bCrcIncHdr 1 +#define _POSITION_CMD_TX_syncWord 16 +#define _TYPE_CMD_TX_syncWord uint32_t +#define _POSITION_CMD_TX_pTxPkt 20 +#define _TYPE_CMD_TX_pTxPkt uint8_t* +#define _POSITION_CMD_TX_pktLen 24 +#define _TYPE_CMD_TX_pktLen uint16_t +#define _SIZEOF_CMD_TX 26 + +#define _POSITION_CMD_RX_TEST_config 14 +#define _TYPE_CMD_RX_TEST_config uint8_t +#define _BITPOS_CMD_RX_TEST_config_bEnaFifo 0 +#define _NBITS_CMD_RX_TEST_config_bEnaFifo 1 +#define _BITPOS_CMD_RX_TEST_config_bFsOff 1 +#define _NBITS_CMD_RX_TEST_config_bFsOff 1 +#define _BITPOS_CMD_RX_TEST_config_bNoSync 2 +#define _NBITS_CMD_RX_TEST_config_bNoSync 1 +#define _POSITION_CMD_RX_TEST_endTrigger 15 +#define _TYPE_CMD_RX_TEST_endTrigger uint8_t +#define _BITPOS_CMD_RX_TEST_endTrigger_triggerType 0 +#define _NBITS_CMD_RX_TEST_endTrigger_triggerType 4 +#define _BITPOS_CMD_RX_TEST_endTrigger_bEnaCmd 4 +#define _NBITS_CMD_RX_TEST_endTrigger_bEnaCmd 1 +#define _BITPOS_CMD_RX_TEST_endTrigger_triggerNo 5 +#define _NBITS_CMD_RX_TEST_endTrigger_triggerNo 2 +#define _BITPOS_CMD_RX_TEST_endTrigger_pastTrig 7 +#define _NBITS_CMD_RX_TEST_endTrigger_pastTrig 1 +#define _POSITION_CMD_RX_TEST_syncWord 16 +#define _TYPE_CMD_RX_TEST_syncWord uint32_t +#define _POSITION_CMD_RX_TEST_endTime 20 +#define _TYPE_CMD_RX_TEST_endTime ratmr_t +#define _SIZEOF_CMD_RX_TEST 24 + +#define _POSITION_CMD_TX_TEST_config 14 +#define _TYPE_CMD_TX_TEST_config uint8_t +#define _BITPOS_CMD_TX_TEST_config_bUseCw 0 +#define _NBITS_CMD_TX_TEST_config_bUseCw 1 +#define _BITPOS_CMD_TX_TEST_config_bFsOff 1 +#define _NBITS_CMD_TX_TEST_config_bFsOff 1 +#define _BITPOS_CMD_TX_TEST_config_whitenMode 2 +#define _NBITS_CMD_TX_TEST_config_whitenMode 2 +#define _POSITION_CMD_TX_TEST_txWord 16 +#define _TYPE_CMD_TX_TEST_txWord uint16_t +#define _POSITION_CMD_TX_TEST_endTrigger 19 +#define _TYPE_CMD_TX_TEST_endTrigger uint8_t +#define _BITPOS_CMD_TX_TEST_endTrigger_triggerType 0 +#define _NBITS_CMD_TX_TEST_endTrigger_triggerType 4 +#define _BITPOS_CMD_TX_TEST_endTrigger_bEnaCmd 4 +#define _NBITS_CMD_TX_TEST_endTrigger_bEnaCmd 1 +#define _BITPOS_CMD_TX_TEST_endTrigger_triggerNo 5 +#define _NBITS_CMD_TX_TEST_endTrigger_triggerNo 2 +#define _BITPOS_CMD_TX_TEST_endTrigger_pastTrig 7 +#define _NBITS_CMD_TX_TEST_endTrigger_pastTrig 1 +#define _POSITION_CMD_TX_TEST_syncWord 20 +#define _TYPE_CMD_TX_TEST_syncWord uint32_t +#define _POSITION_CMD_TX_TEST_endTime 24 +#define _TYPE_CMD_TX_TEST_endTime ratmr_t +#define _SIZEOF_CMD_TX_TEST 28 + +#define _POSITION_CMD_SYNC_STOP_RAT_rat0 16 +#define _TYPE_CMD_SYNC_STOP_RAT_rat0 ratmr_t +#define _SIZEOF_CMD_SYNC_STOP_RAT 20 + +#define _POSITION_CMD_SYNC_START_RAT_rat0 16 +#define _TYPE_CMD_SYNC_START_RAT_rat0 ratmr_t +#define _SIZEOF_CMD_SYNC_START_RAT 20 + +#define _POSITION_CMD_COUNT_counter 14 +#define _TYPE_CMD_COUNT_counter uint16_t +#define _SIZEOF_CMD_COUNT 16 + +#define _POSITION_CMD_FS_POWERUP_pRegOverride 16 +#define _TYPE_CMD_FS_POWERUP_pRegOverride uint32_t* +#define _SIZEOF_CMD_FS_POWERUP 20 + +#define _SIZEOF_CMD_FS_POWERDOWN 14 + +#define _POSITION_CMD_SCH_IMM_cmdrVal 16 +#define _TYPE_CMD_SCH_IMM_cmdrVal uint32_t +#define _POSITION_CMD_SCH_IMM_cmdstaVal 20 +#define _TYPE_CMD_SCH_IMM_cmdstaVal uint32_t +#define _SIZEOF_CMD_SCH_IMM 24 + +#define _POSITION_CMD_COUNT_BRANCH_counter 14 +#define _TYPE_CMD_COUNT_BRANCH_counter uint16_t +#define _POSITION_CMD_COUNT_BRANCH_pNextOpIfOk 16 +#define _TYPE_CMD_COUNT_BRANCH_pNextOpIfOk uint8_t* +#define _SIZEOF_CMD_COUNT_BRANCH 20 + +#define _POSITION_CMD_PATTERN_CHECK_patternOpt 14 +#define _TYPE_CMD_PATTERN_CHECK_patternOpt uint16_t +#define _BITPOS_CMD_PATTERN_CHECK_patternOpt_operation 0 +#define _NBITS_CMD_PATTERN_CHECK_patternOpt_operation 2 +#define _BITPOS_CMD_PATTERN_CHECK_patternOpt_bByteRev 2 +#define _NBITS_CMD_PATTERN_CHECK_patternOpt_bByteRev 1 +#define _BITPOS_CMD_PATTERN_CHECK_patternOpt_bBitRev 3 +#define _NBITS_CMD_PATTERN_CHECK_patternOpt_bBitRev 1 +#define _BITPOS_CMD_PATTERN_CHECK_patternOpt_signExtend 4 +#define _NBITS_CMD_PATTERN_CHECK_patternOpt_signExtend 5 +#define _BITPOS_CMD_PATTERN_CHECK_patternOpt_bRxVal 9 +#define _NBITS_CMD_PATTERN_CHECK_patternOpt_bRxVal 1 +#define _POSITION_CMD_PATTERN_CHECK_pNextOpIfOk 16 +#define _TYPE_CMD_PATTERN_CHECK_pNextOpIfOk uint8_t* +#define _POSITION_CMD_PATTERN_CHECK_pValue 20 +#define _TYPE_CMD_PATTERN_CHECK_pValue uint8_t* +#define _POSITION_CMD_PATTERN_CHECK_mask 24 +#define _TYPE_CMD_PATTERN_CHECK_mask uint32_t +#define _POSITION_CMD_PATTERN_CHECK_compareVal 28 +#define _TYPE_CMD_PATTERN_CHECK_compareVal uint32_t +#define _SIZEOF_CMD_PATTERN_CHECK 32 + +#define _SIZEOF_CMD_ABORT 2 + +#define _SIZEOF_CMD_STOP 2 + +#define _SIZEOF_CMD_GET_RSSI 2 + +#define _POSITION_CMD_UPDATE_RADIO_SETUP_pRegOverride 4 +#define _TYPE_CMD_UPDATE_RADIO_SETUP_pRegOverride uint32_t* +#define _SIZEOF_CMD_UPDATE_RADIO_SETUP 8 + +#define _POSITION_CMD_TRIGGER_triggerNo 2 +#define _TYPE_CMD_TRIGGER_triggerNo uint8_t +#define _SIZEOF_CMD_TRIGGER 3 + +#define _POSITION_CMD_GET_FW_INFO_versionNo 2 +#define _TYPE_CMD_GET_FW_INFO_versionNo uint16_t +#define _POSITION_CMD_GET_FW_INFO_startOffset 4 +#define _TYPE_CMD_GET_FW_INFO_startOffset uint16_t +#define _POSITION_CMD_GET_FW_INFO_freeRamSz 6 +#define _TYPE_CMD_GET_FW_INFO_freeRamSz uint16_t +#define _POSITION_CMD_GET_FW_INFO_availRatCh 8 +#define _TYPE_CMD_GET_FW_INFO_availRatCh uint16_t +#define _SIZEOF_CMD_GET_FW_INFO 10 + +#define _SIZEOF_CMD_START_RAT 2 + +#define _SIZEOF_CMD_PING 2 + +#define _POSITION_CMD_ADD_DATA_ENTRY_pQueue 4 +#define _TYPE_CMD_ADD_DATA_ENTRY_pQueue dataQueue_t* +#define _POSITION_CMD_ADD_DATA_ENTRY_pEntry 8 +#define _TYPE_CMD_ADD_DATA_ENTRY_pEntry uint8_t* +#define _SIZEOF_CMD_ADD_DATA_ENTRY 12 + +#define _POSITION_CMD_REMOVE_DATA_ENTRY_pQueue 4 +#define _TYPE_CMD_REMOVE_DATA_ENTRY_pQueue dataQueue_t* +#define _POSITION_CMD_REMOVE_DATA_ENTRY_pEntry 8 +#define _TYPE_CMD_REMOVE_DATA_ENTRY_pEntry uint8_t* +#define _SIZEOF_CMD_REMOVE_DATA_ENTRY 12 + +#define _POSITION_CMD_FLUSH_QUEUE_pQueue 4 +#define _TYPE_CMD_FLUSH_QUEUE_pQueue dataQueue_t* +#define _POSITION_CMD_FLUSH_QUEUE_pFirstEntry 8 +#define _TYPE_CMD_FLUSH_QUEUE_pFirstEntry uint8_t* +#define _SIZEOF_CMD_FLUSH_QUEUE 12 + +#define _POSITION_CMD_CLEAR_RX_pQueue 4 +#define _TYPE_CMD_CLEAR_RX_pQueue dataQueue_t* +#define _SIZEOF_CMD_CLEAR_RX 8 + +#define _POSITION_CMD_REMOVE_PENDING_ENTRIES_pQueue 4 +#define _TYPE_CMD_REMOVE_PENDING_ENTRIES_pQueue dataQueue_t* +#define _POSITION_CMD_REMOVE_PENDING_ENTRIES_pFirstEntry 8 +#define _TYPE_CMD_REMOVE_PENDING_ENTRIES_pFirstEntry uint8_t* +#define _SIZEOF_CMD_REMOVE_PENDING_ENTRIES 12 + +#define _POSITION_CMD_SET_RAT_CMP_ratCh 2 +#define _TYPE_CMD_SET_RAT_CMP_ratCh uint8_t +#define _POSITION_CMD_SET_RAT_CMP_compareTime 4 +#define _TYPE_CMD_SET_RAT_CMP_compareTime ratmr_t +#define _SIZEOF_CMD_SET_RAT_CMP 8 + +#define _POSITION_CMD_SET_RAT_CPT_config 2 +#define _TYPE_CMD_SET_RAT_CPT_config uint16_t +#define _BITPOS_CMD_SET_RAT_CPT_config_inputSrc 3 +#define _NBITS_CMD_SET_RAT_CPT_config_inputSrc 5 +#define _BITPOS_CMD_SET_RAT_CPT_config_ratCh 8 +#define _NBITS_CMD_SET_RAT_CPT_config_ratCh 4 +#define _BITPOS_CMD_SET_RAT_CPT_config_bRepeated 12 +#define _NBITS_CMD_SET_RAT_CPT_config_bRepeated 1 +#define _BITPOS_CMD_SET_RAT_CPT_config_inputMode 13 +#define _NBITS_CMD_SET_RAT_CPT_config_inputMode 2 +#define _SIZEOF_CMD_SET_RAT_CPT 4 + +#define _POSITION_CMD_DISABLE_RAT_CH_ratCh 2 +#define _TYPE_CMD_DISABLE_RAT_CH_ratCh uint8_t +#define _SIZEOF_CMD_DISABLE_RAT_CH 3 + +#define _POSITION_CMD_SET_RAT_OUTPUT_config 2 +#define _TYPE_CMD_SET_RAT_OUTPUT_config uint16_t +#define _BITPOS_CMD_SET_RAT_OUTPUT_config_outputSel 2 +#define _NBITS_CMD_SET_RAT_OUTPUT_config_outputSel 3 +#define _BITPOS_CMD_SET_RAT_OUTPUT_config_outputMode 5 +#define _NBITS_CMD_SET_RAT_OUTPUT_config_outputMode 3 +#define _BITPOS_CMD_SET_RAT_OUTPUT_config_ratCh 8 +#define _NBITS_CMD_SET_RAT_OUTPUT_config_ratCh 4 +#define _SIZEOF_CMD_SET_RAT_OUTPUT 4 + +#define _POSITION_CMD_ARM_RAT_CH_ratCh 2 +#define _TYPE_CMD_ARM_RAT_CH_ratCh uint8_t +#define _SIZEOF_CMD_ARM_RAT_CH 3 + +#define _POSITION_CMD_DISARM_RAT_CH_ratCh 2 +#define _TYPE_CMD_DISARM_RAT_CH_ratCh uint8_t +#define _SIZEOF_CMD_DISARM_RAT_CH 3 + +#define _POSITION_CMD_SET_TX_POWER_txPower 2 +#define _TYPE_CMD_SET_TX_POWER_txPower uint16_t +#define _BITPOS_CMD_SET_TX_POWER_txPower_IB 0 +#define _NBITS_CMD_SET_TX_POWER_txPower_IB 6 +#define _BITPOS_CMD_SET_TX_POWER_txPower_GC 6 +#define _NBITS_CMD_SET_TX_POWER_txPower_GC 2 +#define _BITPOS_CMD_SET_TX_POWER_txPower_tempCoeff 8 +#define _NBITS_CMD_SET_TX_POWER_txPower_tempCoeff 8 +#define _SIZEOF_CMD_SET_TX_POWER 4 + +#define _POSITION_CMD_UPDATE_FS_frequency 2 +#define _TYPE_CMD_UPDATE_FS_frequency uint16_t +#define _POSITION_CMD_UPDATE_FS_fractFreq 4 +#define _TYPE_CMD_UPDATE_FS_fractFreq uint16_t +#define _SIZEOF_CMD_UPDATE_FS 6 + +#define _POSITION_CMD_BUS_REQUEST_bSysBusNeeded 2 +#define _TYPE_CMD_BUS_REQUEST_bSysBusNeeded uint8_t +#define _SIZEOF_CMD_BUS_REQUEST 3 + +#endif diff --git a/cpu/cc26xx/dev/rfc-api/data_entry.h b/cpu/cc26xx/dev/rfc-api/data_entry.h new file mode 100644 index 000000000..91c1826de --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/data_entry.h @@ -0,0 +1,91 @@ +/* + * 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. + */ +/*---------------------------------------------------------------------------*/ +#ifndef __DATA_ENTRY_H +#define __DATA_ENTRY_H + +#include +#include "mailbox.h" + +typedef struct rfc_dataEntry_s rfc_dataEntry_t; + +#define _POSITION_dataEntry_pNextEntry 0 +#define _TYPE_dataEntry_pNextEntry uint8_t* +#define _POSITION_dataEntry_status 4 +#define _TYPE_dataEntry_status uint8_t +#define _POSITION_dataEntry_config 5 +#define _TYPE_dataEntry_config uint8_t +#define _BITPOS_dataEntry_config_type 0 +#define _NBITS_dataEntry_config_type 2 +#define _BITPOS_dataEntry_config_lenSz 2 +#define _NBITS_dataEntry_config_lenSz 2 +#define _BITPOS_dataEntry_config_irqIntv 4 +#define _NBITS_dataEntry_config_irqIntv 4 +#define _POSITION_dataEntry_length 6 +#define _TYPE_dataEntry_length uint16_t +#define _POSITION_dataEntry_data 8 +#define _TYPE_dataEntry_data uint8_t +#define _POSITION_dataEntry_pData 8 +#define _TYPE_dataEntry_pData uint8_t* +#define _POSITION_dataEntry_numElements 8 +#define _TYPE_dataEntry_numElements uint16_t +#define _POSITION_dataEntry_pktStatus 8 +#define _TYPE_dataEntry_pktStatus uint16_t +#define _BITPOS_dataEntry_pktStatus_numElements 0 +#define _NBITS_dataEntry_pktStatus_numElements 13 +#define _BITPOS_dataEntry_pktStatus_bEntryOpen 13 +#define _NBITS_dataEntry_pktStatus_bEntryOpen 1 +#define _BITPOS_dataEntry_pktStatus_bFirstCont 14 +#define _NBITS_dataEntry_pktStatus_bFirstCont 1 +#define _BITPOS_dataEntry_pktStatus_bLastCont 15 +#define _NBITS_dataEntry_pktStatus_bLastCont 1 +#define _POSITION_dataEntry_nextIndex 10 +#define _TYPE_dataEntry_nextIndex uint16_t +#define _POSITION_dataEntry_rxData 12 +#define _TYPE_dataEntry_rxData uint8_t +#define _LAST_POSITION_dataEntry 12 +#define _LAST_TYPE_dataEntry uint8_t + +struct rfc_dataEntry_s { + uint8_t* pNextEntry; + uint8_t status; + struct { + uint8_t type:2; + uint8_t lenSz:2; + uint8_t irqIntv:4; + } config; + uint16_t length; + uint8_t data; + uint8_t __dummy0; + uint16_t nextIndex; + uint8_t rxData; +}; + +#endif diff --git a/cpu/cc26xx/dev/rfc-api/ieee_cmd.h b/cpu/cc26xx/dev/rfc-api/ieee_cmd.h new file mode 100644 index 000000000..e06207053 --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/ieee_cmd.h @@ -0,0 +1,614 @@ +/****************************************************************************** +* Filename: ieee_cmd.h +* Revised: $ $ +* Revision: $ $ +* +* Description: CC26xx/CC13xx API for IEEE 802.15.4 commands +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef __IEEE_CMD_H +#define __IEEE_CMD_H + +#ifndef __RFC_STRUCT +#ifdef __GNUC__ +#define __RFC_STRUCT __attribute__ ((aligned (4))) +#else +#define __RFC_STRUCT +#endif +#endif + +//! \addtogroup rfc +//! @{ + +//! \addtogroup ieee_cmd +//! @{ + +#include +#include "mailbox.h" +#include "common_cmd.h" + +typedef struct __RFC_STRUCT rfc_CMD_IEEE_RX_s rfc_CMD_IEEE_RX_t; +typedef struct __RFC_STRUCT rfc_shortAddrEntry_s rfc_shortAddrEntry_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_CSMA_s rfc_CMD_IEEE_CSMA_t; +typedef struct __RFC_STRUCT rfc_ieeeAuxSecCtrl_s rfc_ieeeAuxSecCtrl_t; +typedef struct __RFC_STRUCT rfc_ieeeRxCorrCrc_s rfc_ieeeRxCorrCrc_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_RX_ACK_s rfc_CMD_IEEE_RX_ACK_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_ABORT_BG_s rfc_CMD_IEEE_ABORT_BG_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_ED_SCAN_s rfc_CMD_IEEE_ED_SCAN_t; +typedef struct __RFC_STRUCT rfc_ieeeMacHdr_s rfc_ieeeMacHdr_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_ABORT_FG_s rfc_CMD_IEEE_ABORT_FG_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_CCA_REQ_s rfc_CMD_IEEE_CCA_REQ_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_SETUP_s rfc_CMD_IEEE_SETUP_t; +typedef struct __RFC_STRUCT rfc_ieeeRxOutput_s rfc_ieeeRxOutput_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_MOD_SRC_MATCH_s rfc_CMD_IEEE_MOD_SRC_MATCH_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_STOP_FG_s rfc_CMD_IEEE_STOP_FG_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_TX_s rfc_CMD_IEEE_TX_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_MOD_FILT_s rfc_CMD_IEEE_MOD_FILT_t; +typedef struct __RFC_STRUCT rfc_CMD_IEEE_MOD_CCA_s rfc_CMD_IEEE_MOD_CCA_t; + +//! \addtogroup CMD_IEEE_RX +//! @{ +#define CMD_IEEE_RX 0x2801 +struct __RFC_STRUCT rfc_CMD_IEEE_RX_s { + uint16_t commandNo; //!< The command ID number 0x2801 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to tune to in the start of the operation
+ //!< 0: Use existing channel
+ //!< 11–26: Use as IEEE 802.15.4 channel, i.e. frequency is (2405 + 5 × (channel - 11)) MHz
+ //!< 60–207: Frequency is (2300 + channel) MHz
+ //!< Others: Reserved + struct { + uint8_t bAutoFlushCrc:1; //!< If 1, automatically remove packets with CRC error from Rx queue + uint8_t bAutoFlushIgn:1; //!< If 1, automatically remove packets that can be ignored according to frame filtering from Rx queue + uint8_t bIncludePhyHdr:1; //!< If 1, include the received PHY header field in the stored packet; otherwise discard it + uint8_t bIncludeCrc:1; //!< If 1, include the received CRC field in the stored packet; otherwise discard it + uint8_t bAppendRssi:1; //!< If 1, append an RSSI byte to the packet in the Rx queue + uint8_t bAppendCorrCrc:1; //!< If 1, append a correlation value and CRC result byte to the packet in the Rx queue + uint8_t bAppendSrcInd:1; //!< If 1, append an index from the source matching algorithm + uint8_t bAppendTimestamp:1; //!< If 1, append a timestamp to the packet in the Rx queue + } rxConfig; + dataQueue_t* pRxQ; //!< Pointer to receive queue + rfc_ieeeRxOutput_t *pOutput; //!< Pointer to output structure (NULL: Do not store results) + struct { + uint16_t frameFiltEn:1; //!< \brief 0: Disable frame filtering
+ //!< 1: Enable frame filtering + uint16_t frameFiltStop:1; //!< \brief 0: Receive all packets to the end
+ //!< 1: Stop receiving frame once frame filtering has caused the frame to be rejected. + uint16_t autoAckEn:1; //!< \brief 0: Disable auto ACK
+ //!< 1: Enable auto ACK. + uint16_t slottedAckEn:1; //!< \brief 0: Non-slotted ACK
+ //!< 1: Slotted ACK. + uint16_t autoPendEn:1; //!< \brief 0: Auto-pend disabled
+ //!< 1: Auto-pend enabled + uint16_t defaultPend:1; //!< The value of the pending data bit in auto ACK packets that are not subject to auto-pend + uint16_t bPendDataReqOnly:1; //!< \brief 0: Use auto-pend for any packet
+ //!< 1: Use auto-pend for data request packets only + uint16_t bPanCoord:1; //!< \brief 0: Device is not PAN coordinator
+ //!< 1: Device is PAN coordinator + uint16_t maxFrameVersion:2; //!< Reject frames where the frame version field in the FCF is greater than this value + uint16_t fcfReservedMask:3; //!< Value to be AND-ed with the reserved part of the FCF; frame rejected if result is non-zero + uint16_t modifyFtFilter:2; //!< \brief Treatment of MSB of frame type field before frame-type filtering:
+ //!< 0: No modification
+ //!< 1: Invert MSB
+ //!< 2: Set MSB to 0
+ //!< 3: Set MSB to 1 + uint16_t bStrictLenFilter:1; //!< \brief 0: Accept acknowledgement frames of any length >= 5
+ //!< 1: Accept only acknowledgement frames of length 5 + } frameFiltOpt; //!< Frame filtering options + struct { + uint8_t bAcceptFt0Beacon:1; //!< \brief Treatment of frames with frame type 000 (beacon):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt1Data:1; //!< \brief Treatment of frames with frame type 001 (data):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt2Ack:1; //!< \brief Treatment of frames with frame type 010 (ACK):
+ //!< 0: Reject, unless running ACK receive command
+ //!< 1: Always accept + uint8_t bAcceptFt3MacCmd:1; //!< \brief Treatment of frames with frame type 011 (MAC command):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt4Reserved:1; //!< \brief Treatment of frames with frame type 100 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt5Reserved:1; //!< \brief Treatment of frames with frame type 101 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt6Reserved:1; //!< \brief Treatment of frames with frame type 110 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt7Reserved:1; //!< \brief Treatment of frames with frame type 111 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + } frameTypes; //!< Frame types to receive in frame filtering + struct { + uint8_t ccaEnEnergy:1; //!< Enable energy scan as CCA source + uint8_t ccaEnCorr:1; //!< Enable correlator based carrier sense as CCA source + uint8_t ccaEnSync:1; //!< Enable sync found based carrier sense as CCA source + uint8_t ccaCorrOp:1; //!< \brief Operator to use between energy based and correlator based CCA
+ //!< 0: Report busy channel if either ccaEnergy or ccaCorr are busy
+ //!< 1: Report busy channel if both ccaEnergy and ccaCorr are busy + uint8_t ccaSyncOp:1; //!< \brief Operator to use between sync found based CCA and the others
+ //!< 0: Always report busy channel if ccaSync is busy
+ //!< 1: Always report idle channel if ccaSync is idle + uint8_t ccaCorrThr:2; //!< Threshold for number of correlation peaks in correlator based carrier sense + } ccaOpt; //!< CCA options + int8_t ccaRssiThr; //!< RSSI threshold for CCA + uint8_t __dummy0; + uint8_t numExtEntries; //!< Number of extended address entries + uint8_t numShortEntries; //!< Number of short address entries + uint32_t* pExtEntryList; //!< Pointer to list of extended address entries + rfc_shortAddrEntry_t *pShortEntryList;//!< Pointer to list of short address entries + uint64_t localExtAddr; //!< The extended address of the local device + uint16_t localShortAddr; //!< The short address of the local device + uint16_t localPanID; //!< The PAN ID of the local device + uint16_t __dummy1; + uint8_t __dummy2; + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the Rx operation + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the Rx + //!< operation +}; + +//! @} + +//! \addtogroup CMD_IEEE_ED_SCAN +//! @{ +#define CMD_IEEE_ED_SCAN 0x2802 +struct __RFC_STRUCT rfc_CMD_IEEE_ED_SCAN_s { + uint16_t commandNo; //!< The command ID number 0x2802 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t channel; //!< \brief Channel to tune to in the start of the operation
+ //!< 0: Use existing channel
+ //!< 11–26: Use as IEEE 802.15.4 channel, i.e. frequency is (2405 + 5 × (channel - 11)) MHz
+ //!< 60–207: Frequency is (2300 + channel) MHz
+ //!< Others: Reserved + struct { + uint8_t ccaEnEnergy:1; //!< Enable energy scan as CCA source + uint8_t ccaEnCorr:1; //!< Enable correlator based carrier sense as CCA source + uint8_t ccaEnSync:1; //!< Enable sync found based carrier sense as CCA source + uint8_t ccaCorrOp:1; //!< \brief Operator to use between energy based and correlator based CCA
+ //!< 0: Report busy channel if either ccaEnergy or ccaCorr are busy
+ //!< 1: Report busy channel if both ccaEnergy and ccaCorr are busy + uint8_t ccaSyncOp:1; //!< \brief Operator to use between sync found based CCA and the others
+ //!< 0: Always report busy channel if ccaSync is busy
+ //!< 1: Always report idle channel if ccaSync is idle + uint8_t ccaCorrThr:2; //!< Threshold for number of correlation peaks in correlator based carrier sense + } ccaOpt; //!< CCA options + int8_t ccaRssiThr; //!< RSSI threshold for CCA + uint8_t __dummy0; + int8_t maxRssi; //!< The maximum RSSI recorded during the ED scan + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the Rx operation + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the Rx + //!< operation +}; + +//! @} + +//! \addtogroup CMD_IEEE_TX +//! @{ +#define CMD_IEEE_TX 0x2C01 +struct __RFC_STRUCT rfc_CMD_IEEE_TX_s { + uint16_t commandNo; //!< The command ID number 0x2C01 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + struct { + uint8_t bIncludePhyHdr:1; //!< \brief 0: Find PHY header automatically
+ //!< 1: Insert PHY header from the buffer + uint8_t bIncludeCrc:1; //!< \brief 0: Append automatically calculated CRC
+ //!< 1: Insert FCS (CRC) from the buffer + uint8_t :1; + uint8_t payloadLenMsb:5; //!< \brief Most significant bits of payload length. Should only be non-zero to create long + //!< non-standard packets for test purposes + } txOpt; + uint8_t payloadLen; //!< Number of bytes in the payload + uint8_t* pPayload; //!< Pointer to payload buffer of size payloadLen + ratmr_t timeStamp; //!< Time stamp of transmitted frame +}; + +//! @} + +//! \addtogroup CMD_IEEE_CSMA +//! @{ +#define CMD_IEEE_CSMA 0x2C02 +struct __RFC_STRUCT rfc_CMD_IEEE_CSMA_s { + uint16_t commandNo; //!< The command ID number 0x2C02 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint16_t randomState; //!< The state of the pseudo-random generator + uint8_t macMaxBE; //!< The IEEE 802.15.4 MAC parameter macMaxBE + uint8_t macMaxCSMABackoffs; //!< The IEEE 802.15.4 MAC parameter macMaxCSMABackoffs + struct { + uint8_t initCW:5; //!< The initialization value for the CW parameter + uint8_t bSlotted:1; //!< \brief 0: non-slotted CSMA
+ //!< 1: slotted CSMA + uint8_t rxOffMode:2; //!< \brief 0: RX stays on during CSMA backoffs
+ //!< 1: The CSMA-CA algorithm will suspend the receiver if no frame is being received
+ //!< 2: The CSMA-CA algorithm will suspend the receiver if no frame is being received, + //!< or after finishing it (including auto ACK) otherwise
+ //!< 3: The CSMA-CA algorithm will suspend the receiver immediately during back-offs + } csmaConfig; + uint8_t NB; //!< The NB parameter from the IEEE 802.15.4 CSMA-CA algorithm + uint8_t BE; //!< The BE parameter from the IEEE 802.15.4 CSMA-CA algorithm + uint8_t remainingPeriods; //!< The number of remaining periods from a paused backoff countdown + int8_t lastRssi; //!< RSSI measured at the last CCA operation + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to end the CSMA-CA operation + ratmr_t lastTimeStamp; //!< Time of the last CCA operation + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to end the + //!< CSMA-CA operation +}; + +//! @} + +//! \addtogroup CMD_IEEE_RX_ACK +//! @{ +#define CMD_IEEE_RX_ACK 0x2C03 +struct __RFC_STRUCT rfc_CMD_IEEE_RX_ACK_s { + uint16_t commandNo; //!< The command ID number 0x2C03 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; + uint8_t seqNo; //!< Sequence number to expect + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } endTrigger; //!< Trigger that causes the device to give up acknowledgement reception + ratmr_t endTime; //!< \brief Time used together with endTrigger that causes the device to give up + //!< acknowledgement reception +}; + +//! @} + +//! \addtogroup CMD_IEEE_ABORT_BG +//! @{ +#define CMD_IEEE_ABORT_BG 0x2C04 +struct __RFC_STRUCT rfc_CMD_IEEE_ABORT_BG_s { + uint16_t commandNo; //!< The command ID number 0x2C04 + uint16_t status; //!< \brief An integer telling the status of the command. This value is + //!< updated by the radio CPU during operation and may be read by the + //!< system CPU at any time. + rfc_radioOp_t *pNextOp; //!< Pointer to the next operation to run after this operation is done + ratmr_t startTime; //!< Absolute or relative start time (depending on the value of startTrigger) + struct { + uint8_t triggerType:4; //!< The type of trigger + uint8_t bEnaCmd:1; //!< \brief 0: No alternative trigger command
+ //!< 1: CMD_TRIGGER can be used as an alternative trigger + uint8_t triggerNo:2; //!< The trigger number of the CMD_TRIGGER command that triggers this action + uint8_t pastTrig:1; //!< \brief 0: A trigger in the past is never triggered, or for start of commands, give an error
+ //!< 1: A trigger in the past is triggered as soon as possible + } startTrigger; //!< Identification of the trigger that starts the operation + struct { + uint8_t rule:4; //!< Condition for running next command: Rule for how to proceed + uint8_t nSkip:4; //!< Number of skips if the rule involves skipping + } condition; +}; + +//! @} + +//! \addtogroup CMD_IEEE_MOD_CCA +//! @{ +#define CMD_IEEE_MOD_CCA 0x2001 +struct __RFC_STRUCT rfc_CMD_IEEE_MOD_CCA_s { + uint16_t commandNo; //!< The command ID number 0x2001 + struct { + uint8_t ccaEnEnergy:1; //!< Enable energy scan as CCA source + uint8_t ccaEnCorr:1; //!< Enable correlator based carrier sense as CCA source + uint8_t ccaEnSync:1; //!< Enable sync found based carrier sense as CCA source + uint8_t ccaCorrOp:1; //!< \brief Operator to use between energy based and correlator based CCA
+ //!< 0: Report busy channel if either ccaEnergy or ccaCorr are busy
+ //!< 1: Report busy channel if both ccaEnergy and ccaCorr are busy + uint8_t ccaSyncOp:1; //!< \brief Operator to use between sync found based CCA and the others
+ //!< 0: Always report busy channel if ccaSync is busy
+ //!< 1: Always report idle channel if ccaSync is idle + uint8_t ccaCorrThr:2; //!< Threshold for number of correlation peaks in correlator based carrier sense + } newCcaOpt; //!< New value of ccaOpt for the running background level operation + int8_t newCcaRssiThr; //!< New value of ccaRssiThr for the running background level operation +}; + +//! @} + +//! \addtogroup CMD_IEEE_MOD_FILT +//! @{ +#define CMD_IEEE_MOD_FILT 0x2002 +struct __RFC_STRUCT rfc_CMD_IEEE_MOD_FILT_s { + uint16_t commandNo; //!< The command ID number 0x2002 + struct { + uint16_t frameFiltEn:1; //!< \brief 0: Disable frame filtering
+ //!< 1: Enable frame filtering + uint16_t frameFiltStop:1; //!< \brief 0: Receive all packets to the end
+ //!< 1: Stop receiving frame once frame filtering has caused the frame to be rejected. + uint16_t autoAckEn:1; //!< \brief 0: Disable auto ACK
+ //!< 1: Enable auto ACK. + uint16_t slottedAckEn:1; //!< \brief 0: Non-slotted ACK
+ //!< 1: Slotted ACK. + uint16_t autoPendEn:1; //!< \brief 0: Auto-pend disabled
+ //!< 1: Auto-pend enabled + uint16_t defaultPend:1; //!< The value of the pending data bit in auto ACK packets that are not subject to auto-pend + uint16_t bPendDataReqOnly:1; //!< \brief 0: Use auto-pend for any packet
+ //!< 1: Use auto-pend for data request packets only + uint16_t bPanCoord:1; //!< \brief 0: Device is not PAN coordinator
+ //!< 1: Device is PAN coordinator + uint16_t maxFrameVersion:2; //!< Reject frames where the frame version field in the FCF is greater than this value + uint16_t fcfReservedMask:3; //!< Value to be AND-ed with the reserved part of the FCF; frame rejected if result is non-zero + uint16_t modifyFtFilter:2; //!< \brief Treatment of MSB of frame type field before frame-type filtering:
+ //!< 0: No modification
+ //!< 1: Invert MSB
+ //!< 2: Set MSB to 0
+ //!< 3: Set MSB to 1 + uint16_t bStrictLenFilter:1; //!< \brief 0: Accept acknowledgement frames of any length >= 5
+ //!< 1: Accept only acknowledgement frames of length 5 + } newFrameFiltOpt; //!< New value of frameFiltOpt for the running background level operation + struct { + uint8_t bAcceptFt0Beacon:1; //!< \brief Treatment of frames with frame type 000 (beacon):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt1Data:1; //!< \brief Treatment of frames with frame type 001 (data):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt2Ack:1; //!< \brief Treatment of frames with frame type 010 (ACK):
+ //!< 0: Reject, unless running ACK receive command
+ //!< 1: Always accept + uint8_t bAcceptFt3MacCmd:1; //!< \brief Treatment of frames with frame type 011 (MAC command):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt4Reserved:1; //!< \brief Treatment of frames with frame type 100 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt5Reserved:1; //!< \brief Treatment of frames with frame type 101 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt6Reserved:1; //!< \brief Treatment of frames with frame type 110 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + uint8_t bAcceptFt7Reserved:1; //!< \brief Treatment of frames with frame type 111 (reserved):
+ //!< 0: Reject
+ //!< 1: Accept + } newFrameTypes; //!< New value of frameTypes for the running background level operation +}; + +//! @} + +//! \addtogroup CMD_IEEE_MOD_SRC_MATCH +//! @{ +#define CMD_IEEE_MOD_SRC_MATCH 0x2003 +struct __RFC_STRUCT rfc_CMD_IEEE_MOD_SRC_MATCH_s { + uint16_t commandNo; //!< The command ID number 0x2003 + struct { + uint8_t bEnable:1; //!< \brief 0: Disable entry
+ //!< 1: Enable entry + uint8_t srcPend:1; //!< New value of the pending bit for the entry + uint8_t entryType:1; //!< \brief 0: Extended address
+ //!< 1: Short address + } options; + uint8_t entryNo; //!< Index of entry to enable or disable +}; + +//! @} + +//! \addtogroup CMD_IEEE_ABORT_FG +//! @{ +#define CMD_IEEE_ABORT_FG 0x2401 +struct __RFC_STRUCT rfc_CMD_IEEE_ABORT_FG_s { + uint16_t commandNo; //!< The command ID number 0x2401 +}; + +//! @} + +//! \addtogroup CMD_IEEE_STOP_FG +//! @{ +#define CMD_IEEE_STOP_FG 0x2402 +struct __RFC_STRUCT rfc_CMD_IEEE_STOP_FG_s { + uint16_t commandNo; //!< The command ID number 0x2402 +}; + +//! @} + +//! \addtogroup CMD_IEEE_CCA_REQ +//! @{ +#define CMD_IEEE_CCA_REQ 0x2403 +struct __RFC_STRUCT rfc_CMD_IEEE_CCA_REQ_s { + uint16_t commandNo; //!< The command ID number 0x2403 + int8_t currentRssi; //!< The RSSI currently observed on the channel + int8_t maxRssi; //!< The maximum RSSI observed on the channel since Rx was started + struct { + uint8_t ccaState:2; //!< \brief Value of the current CCA state
+ //!< 0: Idle
+ //!< 1: Busy
+ //!< 2: Invalid + uint8_t ccaEnergy:2; //!< \brief Value of the current energy detect CCA state
+ //!< 0: Idle
+ //!< 1: Busy
+ //!< 2: Invalid + uint8_t ccaCorr:2; //!< \brief Value of the current correlator based carrier sense CCA state
+ //!< 0: Idle
+ //!< 1: Busy
+ //!< 2: Invalid + uint8_t ccaSync:1; //!< \brief Value of the current sync found based carrier sense CCA state
+ //!< 0: Idle
+ //!< 1: Busy + } ccaInfo; +}; + +//! @} + +//! \addtogroup ieeeRxOutput +//! @{ +//! Output structure for CMD_IEEE_RX + +struct __RFC_STRUCT rfc_ieeeRxOutput_s { + uint8_t nTxAck; //!< Total number of transmitted ACK frames + uint8_t nRxBeacon; //!< Number of received beacon frames + uint8_t nRxData; //!< Number of received data frames + uint8_t nRxAck; //!< Number of received acknowledgement frames + uint8_t nRxMacCmd; //!< Number of received MAC command frames + uint8_t nRxReserved; //!< Number of received frames with reserved frame type + uint8_t nRxNok; //!< Number of received frames with CRC error + uint8_t nRxIgnored; //!< Number of frames received that are to be ignored + uint8_t nRxBufFull; //!< Number of received frames discarded because the Rx buffer was full + int8_t lastRssi; //!< RSSI of last received frame + int8_t maxRssi; //!< Highest RSSI observed in the operation + uint8_t __dummy0; + ratmr_t beaconTimeStamp; //!< Time stamp of last received beacon frame +}; + +//! @} + +//! \addtogroup shortAddrEntry +//! @{ +//! Structure for short address entries + +struct __RFC_STRUCT rfc_shortAddrEntry_s { + uint16_t shortAddr; //!< Short address + uint16_t panId; //!< PAN ID +}; + +//! @} + +//! \addtogroup ieeeRxCorrCrc +//! @{ +//! Receive status byte that may be appended to message in receive buffer + +struct __RFC_STRUCT rfc_ieeeRxCorrCrc_s { + struct { + uint8_t corr:6; //!< The correlation value + uint8_t bIgnore:1; //!< 1 if the packet should be rejected by frame filtering, 0 otherwise + uint8_t bCrcErr:1; //!< 1 if the packet was received with CRC error, 0 otherwise + } status; +}; + +//! @} + +//! @} +//! @} +#endif diff --git a/cpu/cc26xx/dev/rfc-api/ieee_cmd_field.h b/cpu/cc26xx/dev/rfc-api/ieee_cmd_field.h new file mode 100755 index 000000000..149940f79 --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/ieee_cmd_field.h @@ -0,0 +1,403 @@ +/****************************************************************************** +* Filename: ieee_cmd_field.h +* Revised: $ $ +* Revision: $ $ +* +* Description: CC26xx/CC13xx API for IEEE 802.15.4 commands +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef __IEEE_CMD_FIELD_H +#define __IEEE_CMD_FIELD_H + +#include +#include "mailbox.h" +#include "common_cmd.h" + +#define _POSITION_CMD_IEEE_RX_channel 14 +#define _TYPE_CMD_IEEE_RX_channel uint8_t +#define _POSITION_CMD_IEEE_RX_rxConfig 15 +#define _TYPE_CMD_IEEE_RX_rxConfig uint8_t +#define _BITPOS_CMD_IEEE_RX_rxConfig_bAutoFlushCrc 0 +#define _NBITS_CMD_IEEE_RX_rxConfig_bAutoFlushCrc 1 +#define _BITPOS_CMD_IEEE_RX_rxConfig_bAutoFlushIgn 1 +#define _NBITS_CMD_IEEE_RX_rxConfig_bAutoFlushIgn 1 +#define _BITPOS_CMD_IEEE_RX_rxConfig_bIncludePhyHdr 2 +#define _NBITS_CMD_IEEE_RX_rxConfig_bIncludePhyHdr 1 +#define _BITPOS_CMD_IEEE_RX_rxConfig_bIncludeCrc 3 +#define _NBITS_CMD_IEEE_RX_rxConfig_bIncludeCrc 1 +#define _BITPOS_CMD_IEEE_RX_rxConfig_bAppendRssi 4 +#define _NBITS_CMD_IEEE_RX_rxConfig_bAppendRssi 1 +#define _BITPOS_CMD_IEEE_RX_rxConfig_bAppendCorrCrc 5 +#define _NBITS_CMD_IEEE_RX_rxConfig_bAppendCorrCrc 1 +#define _BITPOS_CMD_IEEE_RX_rxConfig_bAppendSrcInd 6 +#define _NBITS_CMD_IEEE_RX_rxConfig_bAppendSrcInd 1 +#define _BITPOS_CMD_IEEE_RX_rxConfig_bAppendTimestamp 7 +#define _NBITS_CMD_IEEE_RX_rxConfig_bAppendTimestamp 1 +#define _POSITION_CMD_IEEE_RX_pRxQ 16 +#define _TYPE_CMD_IEEE_RX_pRxQ dataQueue_t* +#define _POSITION_CMD_IEEE_RX_pOutput 20 +#define _TYPE_CMD_IEEE_RX_pOutput uint8_t* +#define _POSITION_CMD_IEEE_RX_frameFiltOpt 24 +#define _TYPE_CMD_IEEE_RX_frameFiltOpt uint16_t +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_frameFiltEn 0 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_frameFiltEn 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_frameFiltStop 1 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_frameFiltStop 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_autoAckEn 2 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_autoAckEn 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_slottedAckEn 3 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_slottedAckEn 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_autoPendEn 4 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_autoPendEn 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_defaultPend 5 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_defaultPend 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_bPendDataReqOnly 6 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_bPendDataReqOnly 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_bPanCoord 7 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_bPanCoord 1 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_maxFrameVersion 8 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_maxFrameVersion 2 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_fcfReservedMask 10 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_fcfReservedMask 3 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_modifyFtFilter 13 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_modifyFtFilter 2 +#define _BITPOS_CMD_IEEE_RX_frameFiltOpt_bStrictLenFilter 15 +#define _NBITS_CMD_IEEE_RX_frameFiltOpt_bStrictLenFilter 1 +#define _POSITION_CMD_IEEE_RX_frameTypes 26 +#define _TYPE_CMD_IEEE_RX_frameTypes uint8_t +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt0Beacon 0 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt0Beacon 1 +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt1Data 1 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt1Data 1 +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt2Ack 2 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt2Ack 1 +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt3MacCmd 3 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt3MacCmd 1 +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt4Reserved 4 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt4Reserved 1 +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt5Reserved 5 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt5Reserved 1 +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt6Reserved 6 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt6Reserved 1 +#define _BITPOS_CMD_IEEE_RX_frameTypes_bAcceptFt7Reserved 7 +#define _NBITS_CMD_IEEE_RX_frameTypes_bAcceptFt7Reserved 1 +#define _POSITION_CMD_IEEE_RX_ccaOpt 27 +#define _TYPE_CMD_IEEE_RX_ccaOpt uint8_t +#define _BITPOS_CMD_IEEE_RX_ccaOpt_ccaEnEnergy 0 +#define _NBITS_CMD_IEEE_RX_ccaOpt_ccaEnEnergy 1 +#define _BITPOS_CMD_IEEE_RX_ccaOpt_ccaEnCorr 1 +#define _NBITS_CMD_IEEE_RX_ccaOpt_ccaEnCorr 1 +#define _BITPOS_CMD_IEEE_RX_ccaOpt_ccaEnSync 2 +#define _NBITS_CMD_IEEE_RX_ccaOpt_ccaEnSync 1 +#define _BITPOS_CMD_IEEE_RX_ccaOpt_ccaCorrOp 3 +#define _NBITS_CMD_IEEE_RX_ccaOpt_ccaCorrOp 1 +#define _BITPOS_CMD_IEEE_RX_ccaOpt_ccaSyncOp 4 +#define _NBITS_CMD_IEEE_RX_ccaOpt_ccaSyncOp 1 +#define _BITPOS_CMD_IEEE_RX_ccaOpt_ccaCorrThr 5 +#define _NBITS_CMD_IEEE_RX_ccaOpt_ccaCorrThr 2 +#define _POSITION_CMD_IEEE_RX_ccaRssiThr 28 +#define _TYPE_CMD_IEEE_RX_ccaRssiThr int8_t +#define _POSITION_CMD_IEEE_RX_numExtEntries 30 +#define _TYPE_CMD_IEEE_RX_numExtEntries uint8_t +#define _POSITION_CMD_IEEE_RX_numShortEntries 31 +#define _TYPE_CMD_IEEE_RX_numShortEntries uint8_t +#define _POSITION_CMD_IEEE_RX_pExtEntryList 32 +#define _TYPE_CMD_IEEE_RX_pExtEntryList uint32_t* +#define _POSITION_CMD_IEEE_RX_pShortEntryList 36 +#define _TYPE_CMD_IEEE_RX_pShortEntryList uint32_t* +#define _POSITION_CMD_IEEE_RX_localExtAddr 40 +#define _TYPE_CMD_IEEE_RX_localExtAddr uint64_t +#define _POSITION_CMD_IEEE_RX_localShortAddr 48 +#define _TYPE_CMD_IEEE_RX_localShortAddr uint16_t +#define _POSITION_CMD_IEEE_RX_localPanID 50 +#define _TYPE_CMD_IEEE_RX_localPanID uint16_t +#define _POSITION_CMD_IEEE_RX_endTrigger 55 +#define _TYPE_CMD_IEEE_RX_endTrigger uint8_t +#define _BITPOS_CMD_IEEE_RX_endTrigger_triggerType 0 +#define _NBITS_CMD_IEEE_RX_endTrigger_triggerType 4 +#define _BITPOS_CMD_IEEE_RX_endTrigger_bEnaCmd 4 +#define _NBITS_CMD_IEEE_RX_endTrigger_bEnaCmd 1 +#define _BITPOS_CMD_IEEE_RX_endTrigger_triggerNo 5 +#define _NBITS_CMD_IEEE_RX_endTrigger_triggerNo 2 +#define _BITPOS_CMD_IEEE_RX_endTrigger_pastTrig 7 +#define _NBITS_CMD_IEEE_RX_endTrigger_pastTrig 1 +#define _POSITION_CMD_IEEE_RX_endTime 56 +#define _TYPE_CMD_IEEE_RX_endTime ratmr_t +#define _SIZEOF_CMD_IEEE_RX 60 + +#define _POSITION_CMD_IEEE_ED_SCAN_channel 14 +#define _TYPE_CMD_IEEE_ED_SCAN_channel uint8_t +#define _POSITION_CMD_IEEE_ED_SCAN_ccaOpt 15 +#define _TYPE_CMD_IEEE_ED_SCAN_ccaOpt uint8_t +#define _BITPOS_CMD_IEEE_ED_SCAN_ccaOpt_ccaEnEnergy 0 +#define _NBITS_CMD_IEEE_ED_SCAN_ccaOpt_ccaEnEnergy 1 +#define _BITPOS_CMD_IEEE_ED_SCAN_ccaOpt_ccaEnCorr 1 +#define _NBITS_CMD_IEEE_ED_SCAN_ccaOpt_ccaEnCorr 1 +#define _BITPOS_CMD_IEEE_ED_SCAN_ccaOpt_ccaEnSync 2 +#define _NBITS_CMD_IEEE_ED_SCAN_ccaOpt_ccaEnSync 1 +#define _BITPOS_CMD_IEEE_ED_SCAN_ccaOpt_ccaCorrOp 3 +#define _NBITS_CMD_IEEE_ED_SCAN_ccaOpt_ccaCorrOp 1 +#define _BITPOS_CMD_IEEE_ED_SCAN_ccaOpt_ccaSyncOp 4 +#define _NBITS_CMD_IEEE_ED_SCAN_ccaOpt_ccaSyncOp 1 +#define _BITPOS_CMD_IEEE_ED_SCAN_ccaOpt_ccaCorrThr 5 +#define _NBITS_CMD_IEEE_ED_SCAN_ccaOpt_ccaCorrThr 2 +#define _POSITION_CMD_IEEE_ED_SCAN_ccaRssiThr 16 +#define _TYPE_CMD_IEEE_ED_SCAN_ccaRssiThr int8_t +#define _POSITION_CMD_IEEE_ED_SCAN_maxRssi 18 +#define _TYPE_CMD_IEEE_ED_SCAN_maxRssi int8_t +#define _POSITION_CMD_IEEE_ED_SCAN_endTrigger 19 +#define _TYPE_CMD_IEEE_ED_SCAN_endTrigger uint8_t +#define _BITPOS_CMD_IEEE_ED_SCAN_endTrigger_triggerType 0 +#define _NBITS_CMD_IEEE_ED_SCAN_endTrigger_triggerType 4 +#define _BITPOS_CMD_IEEE_ED_SCAN_endTrigger_bEnaCmd 4 +#define _NBITS_CMD_IEEE_ED_SCAN_endTrigger_bEnaCmd 1 +#define _BITPOS_CMD_IEEE_ED_SCAN_endTrigger_triggerNo 5 +#define _NBITS_CMD_IEEE_ED_SCAN_endTrigger_triggerNo 2 +#define _BITPOS_CMD_IEEE_ED_SCAN_endTrigger_pastTrig 7 +#define _NBITS_CMD_IEEE_ED_SCAN_endTrigger_pastTrig 1 +#define _POSITION_CMD_IEEE_ED_SCAN_endTime 20 +#define _TYPE_CMD_IEEE_ED_SCAN_endTime ratmr_t +#define _SIZEOF_CMD_IEEE_ED_SCAN 24 + +#define _POSITION_CMD_IEEE_TX_txOpt 14 +#define _TYPE_CMD_IEEE_TX_txOpt uint8_t +#define _BITPOS_CMD_IEEE_TX_txOpt_bIncludePhyHdr 0 +#define _NBITS_CMD_IEEE_TX_txOpt_bIncludePhyHdr 1 +#define _BITPOS_CMD_IEEE_TX_txOpt_bIncludeCrc 1 +#define _NBITS_CMD_IEEE_TX_txOpt_bIncludeCrc 1 +#define _BITPOS_CMD_IEEE_TX_txOpt_payloadLenMsb 3 +#define _NBITS_CMD_IEEE_TX_txOpt_payloadLenMsb 5 +#define _POSITION_CMD_IEEE_TX_payloadLen 15 +#define _TYPE_CMD_IEEE_TX_payloadLen uint8_t +#define _POSITION_CMD_IEEE_TX_pPayload 16 +#define _TYPE_CMD_IEEE_TX_pPayload uint8_t* +#define _POSITION_CMD_IEEE_TX_timeStamp 20 +#define _TYPE_CMD_IEEE_TX_timeStamp ratmr_t +#define _SIZEOF_CMD_IEEE_TX 24 + +#define _POSITION_CMD_IEEE_CSMA_randomState 14 +#define _TYPE_CMD_IEEE_CSMA_randomState uint16_t +#define _POSITION_CMD_IEEE_CSMA_macMaxBE 16 +#define _TYPE_CMD_IEEE_CSMA_macMaxBE uint8_t +#define _POSITION_CMD_IEEE_CSMA_macMaxCSMABackoffs 17 +#define _TYPE_CMD_IEEE_CSMA_macMaxCSMABackoffs uint8_t +#define _POSITION_CMD_IEEE_CSMA_csmaConfig 18 +#define _TYPE_CMD_IEEE_CSMA_csmaConfig uint8_t +#define _BITPOS_CMD_IEEE_CSMA_csmaConfig_initCW 0 +#define _NBITS_CMD_IEEE_CSMA_csmaConfig_initCW 5 +#define _BITPOS_CMD_IEEE_CSMA_csmaConfig_bSlotted 5 +#define _NBITS_CMD_IEEE_CSMA_csmaConfig_bSlotted 1 +#define _BITPOS_CMD_IEEE_CSMA_csmaConfig_rxOffMode 6 +#define _NBITS_CMD_IEEE_CSMA_csmaConfig_rxOffMode 2 +#define _POSITION_CMD_IEEE_CSMA_NB 19 +#define _TYPE_CMD_IEEE_CSMA_NB uint8_t +#define _POSITION_CMD_IEEE_CSMA_BE 20 +#define _TYPE_CMD_IEEE_CSMA_BE uint8_t +#define _POSITION_CMD_IEEE_CSMA_remainingPeriods 21 +#define _TYPE_CMD_IEEE_CSMA_remainingPeriods uint8_t +#define _POSITION_CMD_IEEE_CSMA_lastRssi 22 +#define _TYPE_CMD_IEEE_CSMA_lastRssi int8_t +#define _POSITION_CMD_IEEE_CSMA_endTrigger 23 +#define _TYPE_CMD_IEEE_CSMA_endTrigger uint8_t +#define _BITPOS_CMD_IEEE_CSMA_endTrigger_triggerType 0 +#define _NBITS_CMD_IEEE_CSMA_endTrigger_triggerType 4 +#define _BITPOS_CMD_IEEE_CSMA_endTrigger_bEnaCmd 4 +#define _NBITS_CMD_IEEE_CSMA_endTrigger_bEnaCmd 1 +#define _BITPOS_CMD_IEEE_CSMA_endTrigger_triggerNo 5 +#define _NBITS_CMD_IEEE_CSMA_endTrigger_triggerNo 2 +#define _BITPOS_CMD_IEEE_CSMA_endTrigger_pastTrig 7 +#define _NBITS_CMD_IEEE_CSMA_endTrigger_pastTrig 1 +#define _POSITION_CMD_IEEE_CSMA_lastTimeStamp 24 +#define _TYPE_CMD_IEEE_CSMA_lastTimeStamp ratmr_t +#define _POSITION_CMD_IEEE_CSMA_endTime 28 +#define _TYPE_CMD_IEEE_CSMA_endTime ratmr_t +#define _SIZEOF_CMD_IEEE_CSMA 32 + +#define _POSITION_CMD_IEEE_RX_ACK_seqNo 14 +#define _TYPE_CMD_IEEE_RX_ACK_seqNo uint8_t +#define _POSITION_CMD_IEEE_RX_ACK_endTrigger 15 +#define _TYPE_CMD_IEEE_RX_ACK_endTrigger uint8_t +#define _BITPOS_CMD_IEEE_RX_ACK_endTrigger_triggerType 0 +#define _NBITS_CMD_IEEE_RX_ACK_endTrigger_triggerType 4 +#define _BITPOS_CMD_IEEE_RX_ACK_endTrigger_bEnaCmd 4 +#define _NBITS_CMD_IEEE_RX_ACK_endTrigger_bEnaCmd 1 +#define _BITPOS_CMD_IEEE_RX_ACK_endTrigger_triggerNo 5 +#define _NBITS_CMD_IEEE_RX_ACK_endTrigger_triggerNo 2 +#define _BITPOS_CMD_IEEE_RX_ACK_endTrigger_pastTrig 7 +#define _NBITS_CMD_IEEE_RX_ACK_endTrigger_pastTrig 1 +#define _POSITION_CMD_IEEE_RX_ACK_endTime 16 +#define _TYPE_CMD_IEEE_RX_ACK_endTime ratmr_t +#define _SIZEOF_CMD_IEEE_RX_ACK 20 + +#define _SIZEOF_CMD_IEEE_ABORT_BG 14 + +#define _POSITION_CMD_IEEE_MOD_CCA_newCcaOpt 2 +#define _TYPE_CMD_IEEE_MOD_CCA_newCcaOpt uint8_t +#define _BITPOS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaEnEnergy 0 +#define _NBITS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaEnEnergy 1 +#define _BITPOS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaEnCorr 1 +#define _NBITS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaEnCorr 1 +#define _BITPOS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaEnSync 2 +#define _NBITS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaEnSync 1 +#define _BITPOS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaCorrOp 3 +#define _NBITS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaCorrOp 1 +#define _BITPOS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaSyncOp 4 +#define _NBITS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaSyncOp 1 +#define _BITPOS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaCorrThr 5 +#define _NBITS_CMD_IEEE_MOD_CCA_newCcaOpt_ccaCorrThr 2 +#define _POSITION_CMD_IEEE_MOD_CCA_newCcaRssiThr 3 +#define _TYPE_CMD_IEEE_MOD_CCA_newCcaRssiThr int8_t +#define _SIZEOF_CMD_IEEE_MOD_CCA 4 + +#define _POSITION_CMD_IEEE_MOD_FILT_newFrameFiltOpt 2 +#define _TYPE_CMD_IEEE_MOD_FILT_newFrameFiltOpt uint16_t +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_frameFiltEn 0 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_frameFiltEn 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_frameFiltStop 1 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_frameFiltStop 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_autoAckEn 2 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_autoAckEn 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_slottedAckEn 3 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_slottedAckEn 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_autoPendEn 4 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_autoPendEn 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_defaultPend 5 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_defaultPend 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_bPendDataReqOnly 6 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_bPendDataReqOnly 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_bPanCoord 7 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_bPanCoord 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_maxFrameVersion 8 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_maxFrameVersion 2 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_fcfReservedMask 10 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_fcfReservedMask 3 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_modifyFtFilter 13 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_modifyFtFilter 2 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_bStrictLenFilter 15 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameFiltOpt_bStrictLenFilter 1 +#define _POSITION_CMD_IEEE_MOD_FILT_newFrameTypes 4 +#define _TYPE_CMD_IEEE_MOD_FILT_newFrameTypes uint8_t +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt0Beacon 0 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt0Beacon 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt1Data 1 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt1Data 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt2Ack 2 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt2Ack 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt3MacCmd 3 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt3MacCmd 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt4Reserved 4 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt4Reserved 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt5Reserved 5 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt5Reserved 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt6Reserved 6 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt6Reserved 1 +#define _BITPOS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt7Reserved 7 +#define _NBITS_CMD_IEEE_MOD_FILT_newFrameTypes_bAcceptFt7Reserved 1 +#define _SIZEOF_CMD_IEEE_MOD_FILT 5 + +#define _POSITION_CMD_IEEE_MOD_SRC_MATCH_options 2 +#define _TYPE_CMD_IEEE_MOD_SRC_MATCH_options uint8_t +#define _BITPOS_CMD_IEEE_MOD_SRC_MATCH_options_bEnable 0 +#define _NBITS_CMD_IEEE_MOD_SRC_MATCH_options_bEnable 1 +#define _BITPOS_CMD_IEEE_MOD_SRC_MATCH_options_srcPend 1 +#define _NBITS_CMD_IEEE_MOD_SRC_MATCH_options_srcPend 1 +#define _BITPOS_CMD_IEEE_MOD_SRC_MATCH_options_entryType 2 +#define _NBITS_CMD_IEEE_MOD_SRC_MATCH_options_entryType 1 +#define _POSITION_CMD_IEEE_MOD_SRC_MATCH_entryNo 3 +#define _TYPE_CMD_IEEE_MOD_SRC_MATCH_entryNo uint8_t +#define _SIZEOF_CMD_IEEE_MOD_SRC_MATCH 4 + +#define _SIZEOF_CMD_IEEE_ABORT_FG 2 + +#define _SIZEOF_CMD_IEEE_STOP_FG 2 + +#define _POSITION_CMD_IEEE_CCA_REQ_currentRssi 2 +#define _TYPE_CMD_IEEE_CCA_REQ_currentRssi int8_t +#define _POSITION_CMD_IEEE_CCA_REQ_maxRssi 3 +#define _TYPE_CMD_IEEE_CCA_REQ_maxRssi int8_t +#define _POSITION_CMD_IEEE_CCA_REQ_ccaInfo 4 +#define _TYPE_CMD_IEEE_CCA_REQ_ccaInfo uint8_t +#define _BITPOS_CMD_IEEE_CCA_REQ_ccaInfo_ccaState 0 +#define _NBITS_CMD_IEEE_CCA_REQ_ccaInfo_ccaState 2 +#define _BITPOS_CMD_IEEE_CCA_REQ_ccaInfo_ccaEnergy 2 +#define _NBITS_CMD_IEEE_CCA_REQ_ccaInfo_ccaEnergy 2 +#define _BITPOS_CMD_IEEE_CCA_REQ_ccaInfo_ccaCorr 4 +#define _NBITS_CMD_IEEE_CCA_REQ_ccaInfo_ccaCorr 2 +#define _BITPOS_CMD_IEEE_CCA_REQ_ccaInfo_ccaSync 6 +#define _NBITS_CMD_IEEE_CCA_REQ_ccaInfo_ccaSync 1 +#define _SIZEOF_CMD_IEEE_CCA_REQ 5 + +#define _POSITION_ieeeRxOutput_nTxAck 0 +#define _TYPE_ieeeRxOutput_nTxAck uint8_t +#define _POSITION_ieeeRxOutput_nRxBeacon 1 +#define _TYPE_ieeeRxOutput_nRxBeacon uint8_t +#define _POSITION_ieeeRxOutput_nRxData 2 +#define _TYPE_ieeeRxOutput_nRxData uint8_t +#define _POSITION_ieeeRxOutput_nRxAck 3 +#define _TYPE_ieeeRxOutput_nRxAck uint8_t +#define _POSITION_ieeeRxOutput_nRxMacCmd 4 +#define _TYPE_ieeeRxOutput_nRxMacCmd uint8_t +#define _POSITION_ieeeRxOutput_nRxReserved 5 +#define _TYPE_ieeeRxOutput_nRxReserved uint8_t +#define _POSITION_ieeeRxOutput_nRxNok 6 +#define _TYPE_ieeeRxOutput_nRxNok uint8_t +#define _POSITION_ieeeRxOutput_nRxIgnored 7 +#define _TYPE_ieeeRxOutput_nRxIgnored uint8_t +#define _POSITION_ieeeRxOutput_nRxBufFull 8 +#define _TYPE_ieeeRxOutput_nRxBufFull uint8_t +#define _POSITION_ieeeRxOutput_lastRssi 9 +#define _TYPE_ieeeRxOutput_lastRssi int8_t +#define _POSITION_ieeeRxOutput_maxRssi 10 +#define _TYPE_ieeeRxOutput_maxRssi int8_t +#define _POSITION_ieeeRxOutput_beaconTimeStamp 12 +#define _TYPE_ieeeRxOutput_beaconTimeStamp ratmr_t +#define _SIZEOF_ieeeRxOutput 16 + +#define _POSITION_shortAddrEntry_shortAddr 0 +#define _TYPE_shortAddrEntry_shortAddr uint16_t +#define _POSITION_shortAddrEntry_panId 2 +#define _TYPE_shortAddrEntry_panId uint16_t +#define _SIZEOF_shortAddrEntry 4 + +#define _POSITION_ieeeRxCorrCrc_status 0 +#define _TYPE_ieeeRxCorrCrc_status uint8_t +#define _BITPOS_ieeeRxCorrCrc_status_corr 0 +#define _NBITS_ieeeRxCorrCrc_status_corr 6 +#define _BITPOS_ieeeRxCorrCrc_status_bIgnore 6 +#define _NBITS_ieeeRxCorrCrc_status_bIgnore 1 +#define _BITPOS_ieeeRxCorrCrc_status_bCrcErr 7 +#define _NBITS_ieeeRxCorrCrc_status_bCrcErr 1 +#define _SIZEOF_ieeeRxCorrCrc 1 + +#endif diff --git a/cpu/cc26xx/dev/rfc-api/ieee_mailbox.h b/cpu/cc26xx/dev/rfc-api/ieee_mailbox.h new file mode 100644 index 000000000..772c4c219 --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/ieee_mailbox.h @@ -0,0 +1,107 @@ +/****************************************************************************** +* Filename: ieee_mailbox.h +* Revised: $ $ +* Revision: $ $ +* +* Description: Definitions for IEEE 802.15.4 interface +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef _IEEE_MAILBOX_H +#define _IEEE_MAILBOX_H + +#include "mailbox.h" + +/// \name CPE interrupt definitions for IEEE 802.15.4 +/// Interrupt masks for the CPE interrupt in RDBELL. These are new names for interrupts in mailbox.h, +/// used for compartibility with previous versions with separate interrupt numbers. +///@{ +#define IRQN_IEEE_BG_COMMAND_SUSPENDED IRQN_BG_COMMAND_SUSPENDED +#define IRQN_IEEE_TX_FRAME IRQN_TX_DONE +#define IRQN_IEEE_TX_ACK IRQN_TX_ACK + +#define IRQN_IEEE_RX_FRAME IRQN_RX_OK +#define IRQN_IEEE_RX_NOK IRQN_RX_NOK +#define IRQN_IEEE_RX_IGNORED IRQN_RX_IGNORED +#define IRQN_IEEE_RX_BUF_FULL IRQN_RX_BUF_FULL +#define IRQN_IEEE_RX_ENTRY_DONE IRQN_RX_ENTRY_DONE + +#define IRQ_IEEE_BG_COMMAND_SUSPENDED (1U << IRQN_IEEE_BG_COMMAND_SUSPENDED) +#define IRQ_IEEE_TX_FRAME (1U << IRQN_IEEE_TX_FRAME) +#define IRQ_IEEE_TX_ACK (1U << IRQN_IEEE_TX_ACK) +#define IRQ_IEEE_RX_FRAME (1U << IRQN_IEEE_RX_FRAME) +#define IRQ_IEEE_RX_NOK (1U << IRQN_IEEE_RX_NOK) +#define IRQ_IEEE_RX_IGNORED (1U << IRQN_IEEE_RX_IGNORED) +#define IRQ_IEEE_RX_BUF_FULL (1U << IRQN_IEEE_RX_BUF_FULL) +#define IRQ_IEEE_RX_ENTRY_DONE (1U << IRQN_IEEE_RX_ENTRY_DONE) +///@} + + + +/// \name Radio operation status +/// Radio operation status format: +/// Bits 15:12: Protocol +/// 0010: IEEE 802.15.4 +/// Bits 11:10: Type +/// 00: Not finished +/// 01: Done successfully +/// 10: Done with error +/// Bits 9:0: Identifier + +/// \name Operation not finished +///@{ +#define IEEE_SUSPENDED 0x2001 ///< Operation suspended +///@} +/// \name Operation finished normally +///@{ +#define IEEE_DONE_OK 0x2400 ///< Operation ended normally +#define IEEE_DONE_BUSY 0x2401 ///< CSMA-CA operation ended with failure +#define IEEE_DONE_STOPPED 0x2402 ///< Operation stopped after stop command +#define IEEE_DONE_ACK 0x2403 ///< ACK packet received with pending data bit cleared +#define IEEE_DONE_ACKPEND 0x2404 ///< ACK packet received with pending data bit set +#define IEEE_DONE_TIMEOUT 0x2405 ///< Operation ended due to timeout +#define IEEE_DONE_BGEND 0x2406 ///< FG operation ended because necessary background level + ///< operation ended +#define IEEE_DONE_ABORT 0x2407 ///< Operation aborted by command +///@} +/// \name Operation finished with error +///@{ +#define IEEE_ERROR_PAR 0x2800 ///< Illegal parameter +#define IEEE_ERROR_NO_SETUP 0x2801 ///< Operation using Rx or Tx attemted when not in 15.4 mode +#define IEEE_ERROR_NO_FS 0x2802 ///< Operation using Rx or Tx attemted without frequency synth configured +#define IEEE_ERROR_SYNTH_PROG 0x2803 ///< Synthesizer programming failed to complete on time +#define IEEE_ERROR_RXOVF 0x2804 ///< Receiver overflowed during operation +#define IEEE_ERROR_TXUNF 0x2805 ///< Transmitter underflowed during operation +///@} +///@} + +#endif diff --git a/cpu/cc26xx/dev/rfc-api/mailbox.h b/cpu/cc26xx/dev/rfc-api/mailbox.h new file mode 100644 index 000000000..b11d72f08 --- /dev/null +++ b/cpu/cc26xx/dev/rfc-api/mailbox.h @@ -0,0 +1,580 @@ +/****************************************************************************** +* Filename: mailbox.h +* Revised: $ $ +* Revision: $ $ +* +* Description: Definitions for interface between system and radio CPU +* +* Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef _MAILBOX_H +#define _MAILBOX_H + +#include +#include + +/// Type definition for RAT +typedef uint32_t ratmr_t; + + + +/// Type definition for a data queue +typedef struct { + uint8_t *pCurrEntry; ///< Pointer to the data queue entry to be used, NULL for an empty queue + uint8_t *pLastEntry; ///< Pointer to the last entry in the queue, NULL for a circular queue +} dataQueue_t; + + + +/// \name CPE interrupt definitions +/// Interrupt masks for the CPE interrupt in RDBELL. +///@{ +#define IRQN_COMMAND_DONE 0 ///< Radio operation command finished +#define IRQN_LAST_COMMAND_DONE 1 ///< Last radio operation command in a chain finished +#define IRQN_FG_COMMAND_DONE 2 ///< FG level Radio operation command finished +#define IRQN_LAST_FG_COMMAND_DONE 3 ///< Last FG level radio operation command in a chain finished +#define IRQN_TX_DONE 4 ///< Packet transmitted +#define IRQN_TX_ACK 5 ///< ACK packet transmitted +#define IRQN_TX_CTRL 6 ///< Control packet transmitted +#define IRQN_TX_CTRL_ACK 7 ///< Acknowledgement received on a transmitted control packet +#define IRQN_TX_CTRL_ACK_ACK 8 ///< Acknowledgement received on a transmitted control packet, and acknowledgement transmitted for that packet +#define IRQN_TX_RETRANS 9 ///< Packet retransmitted +#define IRQN_TX_ENTRY_DONE 10 ///< Tx queue data entry state changed to Finished +#define IRQN_TX_BUFFER_CHANGED 11 ///< A buffer change is complete +#define IRQN_BG_COMMAND_SUSPENDED 12 ///< A background level radio operation command has been suspended +#define IRQN_RX_OK 16 ///< Packet received with CRC OK, payload, and not to be ignored +#define IRQN_RX_NOK 17 ///< Packet received with CRC error +#define IRQN_RX_IGNORED 18 ///< Packet received with CRC OK, but to be ignored +#define IRQN_RX_EMPTY 19 ///< Packet received with CRC OK, not to be ignored, no payload +#define IRQN_RX_CTRL 20 ///< Control packet received with CRC OK, not to be ignored +#define IRQN_RX_CTRL_ACK 21 ///< Control packet received with CRC OK, not to be ignored, then ACK sent +#define IRQN_RX_BUF_FULL 22 ///< Packet received that did not fit in the Rx queue +#define IRQN_RX_ENTRY_DONE 23 ///< Rx queue data entry changing state to Finished +#define IRQN_RX_DATA_WRITTEN 24 ///< Data written to partial read Rx buffer +#define IRQN_RX_N_DATA_WRITTEN 25 ///< Specified number of bytes written to partial read Rx buffer +#define IRQN_RX_ABORTED 26 ///< Packet reception stopped before packet was done +#define IRQN_SYNTH_NO_LOCK 28 ///< The synth has gone out of lock after calibration +#define IRQN_MODULES_UNLOCKED 29 ///< As part of the boot process, the CM0 has opened access to RF core modules and memories +#define IRQN_BOOT_DONE 30 ///< The RF core CPU boot is finished + +#define IRQN_INTERNAL_ERROR 31 ///< Internal error observed + +#define IRQ_COMMAND_DONE (1U << IRQN_COMMAND_DONE) +#define IRQ_LAST_COMMAND_DONE (1U << IRQN_LAST_COMMAND_DONE) +#define IRQ_FG_COMMAND_DONE (1U << IRQN_FG_COMMAND_DONE) +#define IRQ_LAST_FG_COMMAND_DONE (1U << IRQN_LAST_FG_COMMAND_DONE) + +#define IRQ_TX_DONE (1U << IRQN_TX_DONE) +#define IRQ_TX_ACK (1U << IRQN_TX_ACK) +#define IRQ_TX_CTRL (1U << IRQN_TX_CTRL) +#define IRQ_TX_CTRL_ACK (1U << IRQN_TX_CTRL_ACK) +#define IRQ_TX_CTRL_ACK_ACK (1U << IRQN_TX_CTRL_ACK_ACK) +#define IRQ_TX_RETRANS (1U << IRQN_TX_RETRANS) + +#define IRQ_TX_ENTRY_DONE (1U << IRQN_TX_ENTRY_DONE) +#define IRQ_TX_BUFFER_CHANGED (1U << IRQN_TX_BUFFER_CHANGED) + +#define IRQ_BG_COMMAND_SUSPENDED (1U << IRQN_BG_COMMAND_SUSPENDED) + +#define IRQ_RX_OK (1U << IRQN_RX_OK) +#define IRQ_RX_NOK (1U << IRQN_RX_NOK) +#define IRQ_RX_IGNORED (1U << IRQN_RX_IGNORED) +#define IRQ_RX_EMPTY (1U << IRQN_RX_EMPTY) +#define IRQ_RX_CTRL (1U << IRQN_RX_CTRL) +#define IRQ_RX_CTRL_ACK (1U << IRQN_RX_CTRL_ACK) +#define IRQ_RX_BUF_FULL (1U << IRQN_RX_BUF_FULL) +#define IRQ_RX_ENTRY_DONE (1U << IRQN_RX_ENTRY_DONE) +#define IRQ_RX_DATA_WRITTEN (1U << IRQN_RX_DATA_WRITTEN) +#define IRQ_RX_N_DATA_WRITTEN (1U << IRQN_RX_N_DATA_WRITTEN) +#define IRQ_RX_ABORTED (1U << IRQN_RX_ABORTED) + +#define IRQ_SYNTH_NO_LOCK (1U << IRQN_SYNTH_NO_LOCK) +#define IRQ_MODULES_UNLOCKED (1U << IRQN_MODULES_UNLOCKED) +#define IRQ_BOOT_DONE (1U << IRQN_BOOT_DONE) +#define IRQ_INTERNAL_ERROR (1U << IRQN_INTERNAL_ERROR) +///@} + + + +/// \name CMDSTA values +/// Values returned in result byte of CMDSTA +///@{ +#define CMDSTA_Pending 0x00 ///< The command has not yet been parsed +#define CMDSTA_Done 0x01 ///< Command successfully parsed + +#define CMDSTA_IllegalPointer 0x81 ///< The pointer signaled in CMDR is not valid +#define CMDSTA_UnknownCommand 0x82 ///< The command number in the command structure is unknown +#define CMDSTA_UnknownDirCommand 0x83 ///< The command number for a direct command is unknown, or the + ///< command is not a direct command +#define CMDSTA_ContextError 0x85 ///< An immediate or direct command was issued in a context + ///< where it is not supported +#define CMDSTA_SchedulingError 0x86 ///< A radio operation command was attempted to be scheduled + ///< while another operation was already running in the RF core +#define CMDSTA_ParError 0x87 ///< There were errors in the command parameters that are parsed + ///< on submission. +#define CMDSTA_QueueError 0x88 ///< An operation on a data entry queue was attempted that was + ///< not supported by the queue in its current state +#define CMDSTA_QueueBusy 0x89 ///< An operation on a data entry was attempted while that entry + ///< was busy +///@} + +/// \name Macros for use with command definition files +/// The script create_command.pl generates header files from command and structure definitions in the +/// *_def.txt files. These are the macros to access the definitions +///@{ + +/// Get a field from a structure +// +/// Gets a field from a structure defined in a _def.txt file. This may be used both in assignments and +/// references (e.g. GET_FIELD(pCmd1, CMD_TEST, testParam) = GET_FIELD(pCmd2, CMD_DUMMY, dummyParam);) +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the accessed field as defined in the _def.txt file +/// +#define GET_FIELD(ptr, cmd, field) \ +(*((_TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) + +/// Get a field from a structure, reading as volatile +// +/// Gets a field from a structure defined in a _def.txt file, reading it as a volatile parameter, which +/// takes into account that it may be changed by the other side. This may be used both in assignments and +/// references (e.g. GET_FIELD(pCmd1, CMD_TEST, testParam) = GET_FIELD(pCmd2, CMD_DUMMY, dummyParam);) +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the accessed field as defined in the _def.txt file +/// +#define GET_FIELD_V(ptr, cmd, field) \ +(*((volatile _TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) + +/// Get the pointer to a field from a structure +// +/// Gets the pointer to a field from a structure defined in a _def.txt file. +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the accessed field as defined in the _def.txt file +/// +#define GET_FIELD_PTR(ptr, cmd, field) \ +((_TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field))) + +/// Get the volatile pointer to a field from a structure +// +/// Gets the volatile pointer to a field from a structure defined in a _def.txt file. +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the accessed field as defined in the _def.txt file +/// +#define GET_FIELD_VPTR(ptr, cmd, field) \ +((volatile _TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field))) + +/// Get bits from a bit field +// +/// Returns bits from a bit field defined in a _def.txt file. +/// \param[in] value +/// The value of the entire field that contains the bit field +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// +#define GET_BITS(value, cmd, field, bitfield) \ +(((value) >> (_BITPOS_##cmd##_##field##_##bitfield)) & \ + ((1U << (_NBITS_##cmd##_##field##_##bitfield)) - 1)) + +/// Get bits from a bit field as a signed value +// +/// Returns sign extended bits from a bit field defined in a _def.txt file. +/// \param[in] value +/// The value of the entire field that contains the bit field +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// +#define GET_BITS_S(value, cmd, field, bitfield) \ +(((int)(value) << (32 - ((_BITPOS_##cmd##_##field##_##bitfield) + (_NBITS_##cmd##_##field##_##bitfield)))) >> \ + (32 - (_NBITS_##cmd##_##field##_##bitfield))) + +/// Set bits in a bit field +// +/// Modifies a bit field defined in a _def.txt file. +/// \param[in,out] value +/// The value of the entire field that contains the bit field +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// \param[in] bvalue +/// The value to set in the bitfield +/// +#define SET_BITS(value, cmd, field, bitfield, bvalue) \ +(((value) = ((value) & \ + (~(((1U << (_NBITS_##cmd##_##field##_##bitfield)) - 1) << (_BITPOS_##cmd##_##field##_##bitfield))) | \ + ((bvalue) << (_BITPOS_##cmd##_##field##_##bitfield))))) + + +/// Get bits from a bit field in a structure +// +/// Returns bits from a bit field in a structure defined in a _def.txt file. +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// +#define GET_BITFIELD(ptr, cmd, field, bitfield) \ +((*((_TYPE_##cmd##_##field *) ((((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) >> \ + ((_BITPOS_##cmd##_##field##_##bitfield))) & \ + ((1U << (_NBITS_##cmd##_##field##_##bitfield)) - 1)) + +/// Get bits from a bit field in a structure, reading as volatile +// +/// Returns bits from a bit field in a structure defined in a _def.txt file, reading it as a +/// volatile parameter. +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// +#define GET_BITFIELD_V(ptr, cmd, field, bitfield) \ +((*((volatile _TYPE_##cmd##_##field *) ((((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) >> \ + ((_BITPOS_##cmd##_##field##_##bitfield))) & \ + ((1U << (_NBITS_##cmd##_##field##_##bitfield)) - 1)) + + +/// Set bits in a bit field in a structure +// +/// Modifies a bit field in a field in a structure defined in a _def.txt file. +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// \param[in] value +/// The value to set in the bitfield +/// +#define SET_BITFIELD(ptr, cmd, field, bitfield, value) \ +((*((_TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) = \ + ((*((_TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) & \ + (~(((1U << (_NBITS_##cmd##_##field##_##bitfield)) - 1) << (_BITPOS_##cmd##_##field##_##bitfield))) | \ + (((uint32_t)(value)) << (_BITPOS_##cmd##_##field##_##bitfield)))) + +/// Set bits in a bit field in a structure, reading and writing as volatile +// +/// Modifies a bit field in a field in a structure defined in a _def.txt file, accessing it as a volatile +/// parameter. +/// \param[in] ptr +/// Pointer to the structure +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// \param[in] value +/// The value to set in the bitfield +/// +#define SET_BITFIELD_V(ptr, cmd, field, bitfield, value) \ +((*((volatile _TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) = \ + ((*((volatile _TYPE_##cmd##_##field *) (((uint8_t *)(ptr)) + (_POSITION_##cmd##_##field)))) & \ + (~(((1U << (_NBITS_##cmd##_##field##_##bitfield)) - 1) << (_BITPOS_##cmd##_##field##_##bitfield))) | \ + (((uint32_t)(value)) << (_BITPOS_##cmd##_##field##_##bitfield)))) + +/// Get the value of specific bifield in a field with the remaining bits set to 0 +// +/// Returns a bitfield so that the value of the full field can be obtained by bitwise +/// OR between these +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] field +/// Name of the field that contains the bit field definition as defined in the _def.txt file +/// \param[in] bitfield +/// Name of the bitfield as defined in the _def.txt file +/// \param[in] value +/// The value to use in the bitfield +/// +#define BITVALUE(cmd, field, bitfield, value) \ +((((uint32_t)(value)) & ((1U << (_NBITS_##cmd##_##field##_##bitfield)) - 1)) << \ + (_BITPOS_##cmd##_##field##_##bitfield)) + +/// Get the size of a structure +// +/// Gets the size of a structure defined in a _def.txt file. +/// +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// +#define SIZEOF_STRUCT(cmd) \ +(_SIZEOF_##cmd) + +/// Get the size of a radio operation command structure +// +/// Gets the size of a radio operation command structure defined in a _def.txt file. The difference from +/// SIZEOF_STRUCT is for legacy reasons only. +/// +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// +#define SIZEOF_RADIO_OP(cmd) \ +(_SIZEOF_##cmd) + +/// Initializes a structure to an initialization set +// +/// Sets the value of a structure to its given initialization values +/// \param[in] ptr +/// Pointer to the structure, must be word aligned +/// \param[in] cmd +/// Name of the command or structure as defined in the _def.txt file +/// \param[in] set +/// Index of the set of initializations to use +/// +#define INIT_STRUCT(ptr, cmd, set) \ +(memcpy(((uint32_t *)(ptr)) + (_START_INIT_WIDX_##cmd), (__init_##cmd[(set)]), \ + (_N_INIT_WORDS_##cmd) * sizeof(uint32_t))) + +///@} + + +/// \name Macros for sending direct commands +///@{ +/// Direct command with no parameter +#define CMDR_DIR_CMD(cmdId) (((cmdId) << 16) | 1) + +/// Direct command with 1-byte parameter +#define CMDR_DIR_CMD_1BYTE(cmdId, par) (((cmdId) << 16) | ((par) << 8) | 1) + +/// Direct command with 2-byte parameter +#define CMDR_DIR_CMD_2BYTE(cmdId, par) (((cmdId) << 16) | ((par) & 0xFFFC) | 1) + +///@} + + + +/// \name Definitions for trigger types +///@{ +#define TRIG_NOW 0 ///< Triggers immediately +#define TRIG_NEVER 1 ///< Never trigs +#define TRIG_ABSTIME 2 ///< Trigs at an absolute time +#define TRIG_REL_SUBMIT 3 ///< Trigs at a time relative to the command was submitted +#define TRIG_REL_START 4 ///< Trigs at a time relative to the command started +#define TRIG_REL_PREVSTART 5 ///< Trigs at a time relative to the previous command in the chain started +#define TRIG_REL_FIRSTSTART 6 ///< Trigs at a time relative to the first command in the chain started +#define TRIG_REL_PREVEND 7 ///< Trigs at a time relative to the previous command in the chain ended +#define TRIG_REL_EVT1 8 ///< Trigs at a time relative to the context defined "Event 1" +#define TRIG_REL_EVT2 9 ///< Trigs at a time relative to the context defined "Event 2" +#define TRIG_EXTERNAL 10 ///< Trigs at an external event to the radio timer +#define TRIG_PAST_BM 0x80 ///< Bitmask for setting pastTrig bit in order to trig immediately if + ///< trigger happened in the past +///@} + + +/// \name Definitions for conditional execution +///@{ +#define COND_ALWAYS 0 ///< Always run next command (except in case of Abort) +#define COND_NEVER 1 ///< Never run next command +#define COND_STOP_ON_FALSE 2 ///< Run next command if this command returned True, stop if it returned + ///< False +#define COND_STOP_ON_TRUE 3 ///< Stop if this command returned True, run next command if it returned + ///< False +#define COND_SKIP_ON_FALSE 4 ///< Run next command if this command returned True, skip a number of + ///< commands if it returned False +#define COND_SKIP_ON_TRUE 5 ///< Skip a number of commands if this command returned True, run next + ///< command if it returned False +///@} + + + +/// \name Radio operation status +/// Radio operation status format: +///@{ +/// \name Operation not finished +///@{ +#define IDLE 0x0000 ///< Operation not started +#define PENDING 0x0001 ///< Start of command is pending +#define ACTIVE 0x0002 ///< Running +#define SKIPPED 0x0003 ///< Operation skipped due to condition in another command +///@} +/// \name Operation finished normally +///@{ +#define DONE_OK 0x0400 ///< Operation ended normally +#define DONE_COUNTDOWN 0x0401 ///< Counter reached zero +#define DONE_RXERR 0x0402 ///< Operation ended with CRC error +#define DONE_TIMEOUT 0x0403 ///< Operation ended with timeout +#define DONE_STOPPED 0x0404 ///< Operation stopped after CMD_STOP command +#define DONE_ABORT 0x0405 ///< Operation aborted by CMD_ABORT command +#define DONE_FAILED 0x0406 ///< Scheduled immediate command failed +///@} +/// \name Operation finished with error +///@{ +#define ERROR_PAST_START 0x0800 ///< The start trigger occurred in the past +#define ERROR_START_TRIG 0x0801 ///< Illegal start trigger parameter +#define ERROR_CONDITION 0x0802 ///< Illegal condition for next operation +#define ERROR_PAR 0x0803 ///< Error in a command specific parameter +#define ERROR_POINTER 0x0804 ///< Invalid pointer to next operation +#define ERROR_CMDID 0x0805 ///< Next operation has a command ID that is undefined or not a radio + ///< operation command +#define ERROR_WRONG_BG 0x0806 ///< FG level command not compatible with running BG level command +#define ERROR_NO_SETUP 0x0807 ///< Operation using Rx or Tx attemted without CMD_RADIO_SETUP +#define ERROR_NO_FS 0x0808 ///< Operation using Rx or Tx attemted without frequency synth configured +#define ERROR_SYNTH_PROG 0x0809 ///< Synthesizer calibration failed +#define ERROR_TXUNF 0x080A ///< Tx underflow observed +#define ERROR_RXOVF 0x080B ///< Rx overflow observed +#define ERROR_NO_RX 0x080C ///< Attempted to access data from Rx when no such data was yet received +#define ERROR_PENDING 0x080D ///< Command submitted in the future with another command at different level pending +///@} +///@} + + +/// \name Data entry types +///@{ +#define DATA_ENTRY_TYPE_GEN 0 ///< General type: Tx entry or single element Rx entry +#define DATA_ENTRY_TYPE_MULTI 1 ///< Multi-element Rx entry type +#define DATA_ENTRY_TYPE_PTR 2 ///< Pointer entry type +#define DATA_ENTRY_TYPE_PARTIAL 3 ///< Partial read entry type +///@ + + +/// \name Data entry statuses +///@{ +#define DATA_ENTRY_PENDING 0 ///< Entry not yet used +#define DATA_ENTRY_ACTIVE 1 ///< Entry in use by radio CPU +#define DATA_ENTRY_BUSY 2 ///< Entry being updated +#define DATA_ENTRY_FINISHED 3 ///< Radio CPU is finished accessing the entry +#define DATA_ENTRY_UNFINISHED 4 ///< Radio CPU is finished accessing the entry, but packet could not be finished +///@} + +/// Difference between length and size of rxData field in multi-element Rx entry +#define DATA_ENTRY_MULTI_LEN_OFFSET (_POSITION_dataEntry_rxData - _POSITION_dataEntry_data) + + +/// \name Macros for RF register override +///@{ +/// Macro for ADI half-size value-mask combination +#define ADI_VAL_MASK(addr, mask, value) \ +(((addr) & 1) ? (((mask) & 0x0F) | (((value) & 0x0F) << 4)) : \ + ((((mask) & 0x0F) << 4) | ((value) & 0x0F))) +/// 32-bit write of 16-bit value +#define HW_REG_OVERRIDE(addr, val) ((((uintptr_t) (addr)) & 0xFFFC) | ((uint32_t)(val) << 16)) +/// ADI register, full-size write +#define ADI_REG_OVERRIDE(adiNo, addr, val) (2 | ((uint32_t)(val) << 16) | \ +(((addr) & 0x3F) << 24) | (((adiNo) ? 1U : 0) << 31)) +/// 2 ADI registers, full-size write +#define ADI_2REG_OVERRIDE(adiNo, addr, val, addr2, val2) \ +(2 | ((uint32_t)(val2) << 2) | (((addr2) & 0x3F) << 10) | ((uint32_t)(val) << 16) | \ +(((addr) & 0x3F) << 24) | (((adiNo) ? 1U : 0) << 31)) +/// ADI register, half-size read-modify-write +#define ADI_HALFREG_OVERRIDE(adiNo, addr, mask, val) (2 | (ADI_VAL_MASK(addr, mask, val) << 16) | \ +(((addr) & 0x3F) << 24) | (1U << 30) | (((adiNo) ? 1U : 0) << 31)) +/// 2 ADI registers, half-size read-modify-write +#define ADI_2HALFREG_OVERRIDE(adiNo, addr, mask, val, addr2, mask2, val2) \ +(2 | (ADI_VAL_MASK(addr2, mask2, val2) << 2) | (((addr2) & 0x3F) << 10) | \ +(ADI_VAL_MASK(addr, mask, val) << 16) | (((addr) & 0x3F) << 24) | (1U << 30) | (((adiNo) ? 1U : 0) << 31)) + +/// 16-bit SW register as defined in radio_par_def.txt +#define SW_REG_OVERRIDE(cmd, field, val) (3 | ((_POSITION_##cmd##_##field) << 4) | ((uint32_t)(val) << 16)) +/// SW register as defined in radio_par_def.txt with added index (for use with registers > 16 bits). +#define SW_REG_IND_OVERRIDE(cmd, field, offset, val) (3 | \ +(((_POSITION_##cmd##_##field) + ((offset) << 1)) << 4) | ((uint32_t)(val) << 16)) +/// 8-bit SW register as defined in radio_par_def.txt +#define SW_REG_BYTE_OVERRIDE(cmd, field, val) (0x8003 | ((_POSITION_##cmd##_##field) << 4) | \ +((uint32_t)(val) << 16)) +/// Two 8-bit SW registers as defined in radio_par_def.txt; the one given by field and the next byte. +#define SW_REG_2BYTE_OVERRIDE(cmd, field, val0, val1) (3 | (((_POSITION_##cmd##_##field) & 0xFFFE) << 4) | \ + (((uint32_t)(val0) << 16) & 0x00FF0000) | ((uint32_t)(val1) << 24)) +#define HW16_ARRAY_OVERRIDE(addr, length) (1 | (((uintptr_t) (addr)) & 0xFFFC) | ((uint32_t)(length) << 16)) +#define HW32_ARRAY_OVERRIDE(addr, length) (1 | (((uintptr_t) (addr)) & 0xFFFC) | \ +((uint32_t)(length) << 16) | (1U << 30)) +#define ADI_ARRAY_OVERRIDE(adiNo, addr, bHalfSize, length) (1 | ((((addr) & 0x3F) << 2)) | \ +((!!(bHalfSize)) << 8) | ((!!(adiNo)) << 9) | ((uint32_t)(length) << 16) | (2U << 30)) +#define SW_ARRAY_OVERRIDE(cmd, firstfield, length) (1 | (((_POSITION_##cmd##_##firstfield)) << 2) | \ +((uint32_t)(length) << 16) | (3U << 30)) +#define MCE_RFE_OVERRIDE(bMceRam, mceRomBank, mceMode, bRfeRam, rfeRomBank, rfeMode) \ + (7 | ((!!(bMceRam)) << 8) | (((mceRomBank) & 0x07) << 9) | ((!!(bRfeRam)) << 12) | (((rfeRomBank) & 0x07) << 13) | \ + (((mceMode) & 0x00FF) << 16) | (((rfeMode) & 0x00FF) << 24)) +#define BAW_OVERRIDE(freqOffset) (0x000B | ((freqOffset) << 16)) +#define NEW_OVERRIDE_SEGMENT(address) (((((uintptr_t)(address)) & 0x03FFFFFC) << 6) | 0x000F | \ + (((((uintptr_t)(address) >> 24) == 0x20) ? 0x01 : \ + (((uintptr_t)(address) >> 24) == 0x21) ? 0x02 : \ + (((uintptr_t)(address) >> 24) == 0xA0) ? 0x03 : \ + (((uintptr_t)(address) >> 24) == 0x00) ? 0x04 : \ + (((uintptr_t)(address) >> 24) == 0x10) ? 0x05 : \ + (((uintptr_t)(address) >> 24) == 0x11) ? 0x06 : \ + (((uintptr_t)(address) >> 24) == 0x40) ? 0x07 : \ + (((uintptr_t)(address) >> 24) == 0x50) ? 0x08 : \ + 0x09) << 4)) // Use illegal value for illegal address range +/// End of string for override register +#define END_OVERRIDE 0xFFFFFFFF + + +#define FWPAR_8BIT_ADDR(cmd, field) (0x1800 | (_POSITION_##cmd##_##field)) +#define FWPAR_16BIT_ADDR(cmd, field) (0x1000 | (_POSITION_##cmd##_##field)) +#define FWPAR_32BIT_ADDR(cmd, field) (0x0000 | (_POSITION_##cmd##_##field)) + +/// ADI address-value pair +#define ADI_ADDR_VAL(addr, value) ((((addr) & 0x7F) << 8) | ((value) & 0xFF)) +#define ADI_ADDR_VAL_MASK(addr, mask, value) ((((addr) & 0x7F) << 8) | ADI_VAL_MASK(addr, mask, value)) + +/// Low half-word +#define LOWORD(value) ((value) & 0xFFFF) +/// High half-word +#define HIWORD(value) ((value) >> 16) +///@} + + +#endif diff --git a/cpu/cc26xx/dev/uart1.h b/cpu/cc26xx/dev/uart1.h new file mode 100644 index 000000000..76dcdcdbe --- /dev/null +++ b/cpu/cc26xx/dev/uart1.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/** + * \addtogroup cc26xx-uart + * @{ + * + * \file + * This file really only exists because some examples rely on it. + * + * For instance, some examples do uart1_set_input(f). We re-write this to + * uart_set_input + */ +#ifndef UART1_H_ +#define UART1_H_ + +#include "dev/cc26xx-uart.h" + +#define BAUD2UBR(x) x +#define uart1_set_input(f) cc26xx_uart_set_input(f) + +#endif /* UART1_H_ */ + +/** @} */ diff --git a/cpu/cc26xx/fault-handlers.c b/cpu/cc26xx/fault-handlers.c new file mode 100644 index 000000000..48dd9f204 --- /dev/null +++ b/cpu/cc26xx/fault-handlers.c @@ -0,0 +1,54 @@ +/* + * 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. + */ +/*---------------------------------------------------------------------------*/ +#include "inc/hw_types.h" +#include "inc/hw_memmap.h" +#include "inc/hw_cpu_scs.h" +/*---------------------------------------------------------------------------*/ +#define fault_handlers_hard_fault_isr FaultISR +/*---------------------------------------------------------------------------*/ +void +fault_handlers_hard_fault_isr(void) +{ + /* + * Workaround for (Im)precise Bus Faults caused under unknown circumstances, + * likely by access to RFC registers while the RF PD is off (which is + * something that should never happen because we do in fact check before + * accessing) + */ + if((HWREG(CPU_SCS_BASE + CPU_SCS_O_CFSR) == CPU_SCS_CFSR_IMPRECISERR) || + (HWREG(CPU_SCS_BASE + CPU_SCS_O_CFSR) & CPU_SCS_CFSR_PRECISERR)){ + /* ToDo: Check BFARVALID and then BFAR to filter down even further */ + return; + } + + while(1); +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/cc26xx/ieee-addr.c b/cpu/cc26xx/ieee-addr.c new file mode 100644 index 000000000..1d70aff18 --- /dev/null +++ b/cpu/cc26xx/ieee-addr.c @@ -0,0 +1,90 @@ +/* + * 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 cc26xx-ieee-addr + * @{ + * + * \file + * Driver for the CC26xx IEEE addresses + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "net/linkaddr.h" +#include "ieee-addr.h" + +#include +#include +/*---------------------------------------------------------------------------*/ +void +ieee_addr_cpy_to(uint8_t *dst, uint8_t len) +{ + if(IEEE_ADDR_CONF_HARDCODED) { + uint8_t ieee_addr_hc[8] = IEEE_ADDR_CONF_ADDRESS; + + memcpy(dst, &ieee_addr_hc[8 - len], len); + } else { + int i; + + /* Reading from primary location... */ + uint8_t *location = (uint8_t *)IEEE_ADDR_LOCATION_PRIMARY; + + /* + * ...unless we can find a byte != 0xFF in secondary + * + * Intentionally checking all 8 bytes here instead of len, because we + * are checking validity of the entire IEEE address irrespective of the + * actual number of bytes the caller wants to copy over. + */ + for(i = 0; i < 8; i++) { + if(((uint8_t *)IEEE_ADDR_LOCATION_SECONDARY)[i] != 0xFF) { + /* A byte in the secondary location is not 0xFF. Use the secondary */ + location = (uint8_t *)IEEE_ADDR_LOCATION_SECONDARY; + break; + } + } + + /* + * We have chosen what address to read the IEEE address from. Do so, + * inverting byte order + */ + for(i = 0; i < len; i++) { + dst[i] = location[len - 1 - i]; + } + } + +#if IEEE_ADDR_NODE_ID + dst[len - 1] = IEEE_ADDR_NODE_ID & 0xFF; + dst[len - 2] = IEEE_ADDR_NODE_ID >> 8; +#endif +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc26xx/ieee-addr.h b/cpu/cc26xx/ieee-addr.h new file mode 100644 index 000000000..3cd97d72a --- /dev/null +++ b/cpu/cc26xx/ieee-addr.h @@ -0,0 +1,105 @@ +/* + * 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 cc26xx + * @{ + * + * \defgroup cc26xx-ieee-addr CC26xx IEEE Address Control + * + * Driver for the retrieval of an IEEE address from flash + * + * The user can specify a hardcoded IEEE address through the + * IEEE_ADDR_CONF_HARDCODED configuration macro. + * + * If the user does not hard-code an address, then one will be read from either + * the primary location (InfoPage) or from the secondary location (on flash). + * + * In order to allow the user to easily program nodes with addresses, the + * secondary location is given priority: If it contains a valid address then + * it will be chosen in favour of the one on InfoPage. + * + * In this context, an address is valid if at least one of the 8 bytes does not + * equal 0xFF. If all 8 bytes are 0xFF, then the primary location will be used. + * + * In all cases, the address is assumed to be written little-endian. + * + * Lastly, it is possible to override the 2 LSB's of the address by using the + * NODE_ID make variable. + * @{ + * + * \file + * Header file with register and macro declarations for the cc26xx IEEE address + * driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef IEEE_ADDR_H_ +#define IEEE_ADDR_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" + +#include +/*---------------------------------------------------------------------------*/ +/** + * \name IEEE address locations + * + * The address of the secondary location can be configured by the platform + * or example + * + * @{ + */ +#define IEEE_ADDR_LOCATION_PRIMARY 0x500012F0 /**< Primary IEEE address location */ + +#ifdef IEEE_ADDR_CONF_LOCATION_SECONDARY +#define IEEE_ADDR_LOCATION_SECONDARY IEEE_ADDR_CONF_LOCATION_SECONDARY +#else +#define IEEE_ADDR_LOCATION_SECONDARY 0x0001FFC8 /**< Secondary IEEE address location */ +#endif +/** @} */ +/*---------------------------------------------------------------------------*/ +/** + * \brief Copy the node's IEEE address to a destination memory area + * \param dst A pointer to the destination area where the IEEE address is to be + * written + * \param len The number of bytes to write to destination area + * + * This function will copy \e len LS bytes and it will invert byte order in + * the process. The factory address on devices is normally little-endian, + * therefore you should expect dst to store the address in a big-endian order. + */ +void ieee_addr_cpy_to(uint8_t *dst, uint8_t len); +/*---------------------------------------------------------------------------*/ +#endif /* IEEE_ADDR_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/lpm.c b/cpu/cc26xx/lpm.c new file mode 100644 index 000000000..0322f940c --- /dev/null +++ b/cpu/cc26xx/lpm.c @@ -0,0 +1,408 @@ +/* + * 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 cc26xx-lpm + * @{ + * + * Implementation of CC26xx low-power operation functionality + * + * @{ + * + * \file + * Driver for CC26xx's low-power operation + */ +/*---------------------------------------------------------------------------*/ +#include "prcm.h" +#include "contiki-conf.h" +#include "ti-lib.h" +#include "lpm.h" +#include "sys/energest.h" +#include "lib/list.h" +#include "dev/leds.h" +#include "dev/watchdog.h" +#include "dev/cc26xx-rtc.h" +/*---------------------------------------------------------------------------*/ +#if ENERGEST_CONF_ON +static unsigned long irq_energest = 0; + +#define ENERGEST_IRQ_SAVE(a) do { \ + a = energest_type_time(ENERGEST_TYPE_IRQ); } while(0) +#define ENERGEST_IRQ_RESTORE(a) do { \ + energest_type_set(ENERGEST_TYPE_IRQ, a); } while(0) +#else +#define ENERGEST_IRQ_SAVE(a) do {} while(0) +#define ENERGEST_IRQ_RESTORE(a) do {} while(0) +#endif +/*---------------------------------------------------------------------------*/ +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)) +/*---------------------------------------------------------------------------*/ +/* + * Don't consider standby mode if the next AON RTC event is scheduled to fire + * in less than STANDBY_MIN_DURATION rtimer ticks + */ +#define STANDBY_MIN_DURATION (RTIMER_SECOND >> 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_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; + + for(module = list_head(modules_list); module != NULL; + module = module->next) { + if(module->shutdown) { + module->shutdown(LPM_MODE_SHUTDOWN); + } + } + + leds_off(LEDS_ALL); + + for(i = 0; i < 5; i++) { + t0 = RTIMER_NOW(); + leds_toggle(LEDS_ALL); + while(RTIMER_CLOCK_LT(RTIMER_NOW(), (t0 + (RTIMER_SECOND >> 3)))); + } + + leds_off(LEDS_ALL); + + ti_lib_gpio_dir_mode_set((1 << pin), GPIO_DIR_MODE_IN); + ti_lib_ioc_port_configure_set(pin, IOC_PORT_GPIO, io_cfg); + + ti_lib_pwr_ctrl_state_set(LPM_MODE_SHUTDOWN); +} +/*---------------------------------------------------------------------------*/ +/* + * 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 + * and power domains as required. + */ +void +lpm_wake_up() +{ + lpm_registered_module_t *module; + + /* Remember IRQ energest for next pass */ + ENERGEST_IRQ_SAVE(irq_energest); + ENERGEST_ON(ENERGEST_TYPE_CPU); + ENERGEST_OFF(ENERGEST_TYPE_LPM); + + /* Sync so that we get the latest values before adjusting recharge settings */ + ti_lib_sys_ctrl_aon_sync(); + + /* Adjust recharge settings */ + ti_lib_sys_ctrl_adjust_recharge_after_power_down(); + + /* + * Release the request to the uLDO + * This is likely not required, since the switch to GLDO/DCDC is automatic + * when coming back from deep sleep + */ + ti_lib_prcm_mcu_uldo_configure(false); + + /* Turn on cache again */ + ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_ENABLED); + ti_lib_prcm_retention_enable(PRCM_DOMAIN_VIMS); + + 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); + + /* Notify all registered modules that we've just woken up */ + for(module = list_head(modules_list); module != NULL; + module = module->next) { + if(module->wakeup) { + module->wakeup(); + } + } +} +/*---------------------------------------------------------------------------*/ +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(); + return; + } + + /* Collect max allowed PM permission from interested modules */ + for(module = list_head(modules_list); module != NULL; + module = module->next) { + if(module->request_max_pm) { + module_pm = module->request_max_pm(); + if(module_pm < max_pm) { + max_pm = module_pm; + } + } + } + + /* Check if any events fired during this process. Last chance to abort */ + if(process_nevents()) { + return; + } + + /* Drop */ + if(max_pm == LPM_MODE_SLEEP) { + lpm_sleep(); + } else { + /* Critical. Don't get interrupted! */ + ti_lib_int_master_disable(); + + /* + * Notify all registered modules that we are dropping to mode X. We do not + * need to do this for simple sleep. + * + * This is a chance for modules to delay us a little bit until an ongoing + * operation has finished (e.g. uart TX) or to configure themselves for + * deep sleep. + */ + 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; + } + + /* Pat the dog: We don't want it to shout right after we wake up */ + watchdog_periodic(); + + /* Clear unacceptable bits, just in case a lock provided a bad value */ + domains &= LOCKABLE_DOMAINS; + + /* + * Freeze the IOs on the boundary between MCU and AON. We only do this if + * PERIPH is not needed + */ + if(domains & PRCM_DOMAIN_PERIPH) { + ti_lib_aon_ioc_freeze_enable(); + } + + /* + * Among LOCKABLE_DOMAINS, turn off those that are not locked + * + * If domains is != 0, pass it as-is + */ + if(domains) { + ti_lib_prcm_power_domain_off(domains); + } + + /* Configure clock sources for MCU and AUX: No clock */ + ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK); + ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK); + + /* Full RAM retention. */ + ti_lib_aon_wuc_mcu_sram_config(MCU_RAM0_RETENTION | MCU_RAM1_RETENTION | + MCU_RAM2_RETENTION | MCU_RAM3_RETENTION); + + /* 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 + */ + ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_CPU | + PRCM_DOMAIN_VIMS | PRCM_DOMAIN_SYSBUS); + + /* Request JTAG domain power off */ + ti_lib_aon_wuc_jtag_power_off(); + + /* Turn off AUX */ + ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF); + ti_lib_aon_wuc_domain_power_down_enable(); + while(ti_lib_aon_wuc_power_status() & 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 + * source while in deep sleep. + */ + if(domains == LOCKABLE_DOMAINS) { + ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_ULDO); + } + + /* We are only interested in IRQ energest while idle or in LPM */ + ENERGEST_IRQ_RESTORE(irq_energest); + ENERGEST_OFF(ENERGEST_TYPE_CPU); + ENERGEST_ON(ENERGEST_TYPE_LPM); + + /* Sync the AON interface to ensure all writes have gone through. */ + ti_lib_sys_ctrl_aon_sync(); + + /* + * Explicitly turn off VIMS cache, CRAM and TRAM. Needed because of + * retention mismatch between VIMS logic and cache. We wait to do this + * until right before deep sleep to be able to use the cache for as long + * as possible. + */ + ti_lib_prcm_retention_disable(PRCM_DOMAIN_VIMS); + ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF); + + /* Deep Sleep */ + ti_lib_prcm_deep_sleep(); + + /* + * When we reach here, some interrupt woke us up. The global interrupt + * flag is off, hence we have a chance to run things here. We will wake up + * the chip properly, and then we will enable the global interrupt without + * unpending events so the handlers can fire + */ + lpm_wake_up(); + + ti_lib_int_master_enable(); + } +} +/*---------------------------------------------------------------------------*/ +void +lpm_sleep(void) +{ + ENERGEST_OFF(ENERGEST_TYPE_CPU); + ENERGEST_ON(ENERGEST_TYPE_LPM); + + /* We are only interested in IRQ energest while idle or in LPM */ + ENERGEST_IRQ_RESTORE(irq_energest); + + /* Just to be on the safe side, explicitly disable Deep Sleep */ + HWREG(NVIC_SYS_CTRL) &= ~(NVIC_SYS_CTRL_SLEEPDEEP); + + ti_lib_prcm_sleep(); + + /* Remember IRQ energest for next pass */ + ENERGEST_IRQ_SAVE(irq_energest); + + ENERGEST_ON(ENERGEST_TYPE_CPU); + ENERGEST_OFF(ENERGEST_TYPE_LPM); +} +/*---------------------------------------------------------------------------*/ +void +lpm_register_module(lpm_registered_module_t *module) +{ + list_add(modules_list, module); +} +/*---------------------------------------------------------------------------*/ +void +lpm_init() +{ + list_init(modules_list); + list_init(power_domain_locks_list); +} +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/lpm.h b/cpu/cc26xx/lpm.h new file mode 100644 index 000000000..85c20e77b --- /dev/null +++ b/cpu/cc26xx/lpm.h @@ -0,0 +1,172 @@ +/* + * 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 cc26xx + * @{ + * + * \defgroup cc26xx-lpm CC26xx Low-Power management + * + * CC26xx low-power operation + * + * @{ + * + * \file + * Header file for the management of CC26xx low-power operation + */ +/*---------------------------------------------------------------------------*/ +#ifndef LPM_H_ +#define LPM_H_ +/*---------------------------------------------------------------------------*/ +#include "pwr_ctrl.h" + +#include +/*---------------------------------------------------------------------------*/ +#define LPM_MODE_SLEEP PWRCTRL_ACTIVE +#define LPM_MODE_DEEP_SLEEP PWRCTRL_POWER_DOWN +#define LPM_MODE_SHUTDOWN PWRCTRL_SHUTDOWN + +#define LPM_MODE_MAX_SUPPORTED LPM_MODE_DEEP_SLEEP +/*---------------------------------------------------------------------------*/ +typedef struct lpm_registered_module { + struct lpm_registered_module *next; + uint8_t (*request_max_pm)(void); + void (*shutdown)(uint8_t mode); + void (*wakeup)(void); +} lpm_registered_module_t; +/*---------------------------------------------------------------------------*/ +/** + * \brief Declare a variable to be used in order to get notifications from LPM + * \param n the variable name to be declared + * \param m A pointer to a function which will tell the LPM module the max + * PM this module is willing to handle. This function will return + * LPM_MODE_SLEEP, LPM_MODE_DEEP_SLEEP etc. The LPM module will ask all + * registered modules and will trigger the highest LPM permitted + * \param s A pointer to a function which will receive a notification just + * before entering the low power mode. The callee can prepare for the + * imminent LPM state. The argument to this function will be the + * upcoming low power mode. This function can e.g. turn off a + * peripheral before the LPM module shuts down the power domain. + * \param w A pointer to a function which will be called just after we have + * 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. + */ +#define LPM_MODULE(n, m, s, w) static lpm_registered_module_t n = \ + { NULL, m, s, w } +/*---------------------------------------------------------------------------*/ +/** + * + * \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 + * + * Whether the cortex will drop to sleep or deep sleep is configurable. The + * exact peripherals which will be shut down is also configurable + */ +void lpm_drop(void); + +/** + * \brief Enter sleep mode + */ +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... + */ +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); + +/** + * \brief Register a module for LPM notifications. + * \param module A pointer to the data structure with the module definition + * + * When the LPM module is about to drop to some low power mode, it will first + * notify all modules about this. + * + * This function must not be called before the module has been initialised + * with lpm_init(). The code does not perform checks: This is the caller's + * responsibility. + */ +void lpm_register_module(lpm_registered_module_t *module); + +/** + * \brief Initialise the low-power mode management module + */ +void lpm_init(void); +/*---------------------------------------------------------------------------*/ +#endif /* LPM_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/mtarch.h b/cpu/cc26xx/mtarch.h new file mode 100644 index 000000000..4f696669d --- /dev/null +++ b/cpu/cc26xx/mtarch.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010, Loughborough University - Computer Science + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +/* + * \file + * Stub header file for multi-threading. It doesn't do anything, it + * just exists so that mt.c can compile cleanly. + * + * This is based on the original mtarch.h for z80 by Takahide Matsutsuka + * + * \author + * George Oikonomou - + */ +#ifndef __MTARCH_H__ +#define __MTARCH_H__ + +struct mtarch_thread { + unsigned char *sp; +}; + +#endif /* __MTARCH_H__ */ diff --git a/cpu/cc26xx/putchar.c b/cpu/cc26xx/putchar.c new file mode 100644 index 000000000..0f91deea5 --- /dev/null +++ b/cpu/cc26xx/putchar.c @@ -0,0 +1,70 @@ +/* + * 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. + */ +/*---------------------------------------------------------------------------*/ +#include "cc26xx-uart.h" + +#include +/*---------------------------------------------------------------------------*/ +int +putchar(int c) +{ + cc26xx_uart_write_byte(c); + return c; +} +/*---------------------------------------------------------------------------*/ +int +puts(const char *str) +{ + int i; + if(str == NULL) { + return 0; + } + for(i = 0; i < strlen(str); i++) { + putchar(str[i]); + } + putchar('\n'); + return i; +} +/*---------------------------------------------------------------------------*/ +unsigned int +dbg_send_bytes(const unsigned char *s, unsigned int len) +{ + unsigned int i = 0; + + while(s && *s != 0) { + if(i >= len) { + break; + } + putchar(*s++); + i++; + } + return i; +} +/*---------------------------------------------------------------------------*/ diff --git a/cpu/cc26xx/rtimer-arch.c b/cpu/cc26xx/rtimer-arch.c new file mode 100644 index 000000000..37077f1b3 --- /dev/null +++ b/cpu/cc26xx/rtimer-arch.c @@ -0,0 +1,92 @@ +/* + * 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 cc26xx-rtimer + * @{ + * + * \file + * Implementation of the arch-specific rtimer functions for the cc26xx + * + */ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "sys/energest.h" +#include "sys/rtimer.h" +#include "cpu.h" +#include "dev/cc26xx-rtc.h" + +#include "ti-lib.h" + +#include +/*---------------------------------------------------------------------------*/ +/** + * \brief We don't need to do anything special here. The RTC is initialised + * elsewhere + */ +void +rtimer_arch_init(void) +{ + return; +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Schedules an rtimer task to be triggered at time t + * \param t The time when the task will need executed. + * + * \e t is an absolute time, in other words the task will be executed AT + * time \e t, not IN \e t rtimer ticks. + * + * This function schedules a one-shot event with the AON RTC. + * + * This functions converts \e to a value suitable for the AON RTC. + */ +void +rtimer_arch_schedule(rtimer_clock_t t) +{ + /* Convert the rtimer tick value to a value suitable for the AON RTC */ + cc26xx_rtc_schedule_one_shot(t); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Returns the current real-time clock time + * \return The current rtimer time in ticks + * + * The value is read from the AON RTC counter and converted to a number of + * rtimer ticks + * + */ +rtimer_clock_t +rtimer_arch_now() +{ + return ti_lib_aon_rtc_current_compare_value_get(); +} +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/cpu/cc26xx/rtimer-arch.h b/cpu/cc26xx/rtimer-arch.h new file mode 100644 index 000000000..1a4a50c09 --- /dev/null +++ b/cpu/cc26xx/rtimer-arch.h @@ -0,0 +1,65 @@ +/* + * 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 cc26xx-clocks + * @{ + * + * \defgroup cc26xx-rtimer CC26xx rtimer + * + * Implementation of the rtimer module for the CC26xx + * + * The rtimer runs on the AON RTC. We set the RTC's channel 2 to continuous + * compare mode, instead of scheduling the next tick interrupt by software. + * This gives us completely equidistant events. + * + * The RTC runs in all power modes (except shutdown) + * @{ + */ +/** + * \file + * Header file for the CC26xx rtimer driver + */ +/*---------------------------------------------------------------------------*/ +#ifndef RTIMER_ARCH_H_ +#define RTIMER_ARCH_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +/*---------------------------------------------------------------------------*/ +#define RTIMER_ARCH_SECOND 65536 +/*---------------------------------------------------------------------------*/ +rtimer_clock_t rtimer_arch_now(void); +/*---------------------------------------------------------------------------*/ +#endif /* RTIMER_ARCH_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/cc26xx/slip-arch.c b/cpu/cc26xx/slip-arch.c new file mode 100644 index 000000000..268c84548 --- /dev/null +++ b/cpu/cc26xx/slip-arch.c @@ -0,0 +1,65 @@ +/* + * 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 cc26xx-char-io + * @{ + * + * \file + * Arch-specific SLIP functions for the cc26xx + */ +/*---------------------------------------------------------------------------*/ +#include "contiki-conf.h" +#include "dev/cc26xx-uart.h" +#include "dev/slip.h" +/*---------------------------------------------------------------------------*/ +/** + * \brief Write a byte over SLIP + * \param c the byte + */ +void +slip_arch_writeb(unsigned char c) +{ + cc26xx_uart_write_byte(c); +} +/*---------------------------------------------------------------------------*/ +/** + * \brief Initialise the arch-specific SLIP driver + * \param ubr Ignored for the cc26xx + */ +void +slip_arch_init(unsigned long ubr) +{ + cc26xx_uart_set_input(slip_input_byte); +} +/*---------------------------------------------------------------------------*/ + +/** @} */ diff --git a/cpu/cc26xx/ti-lib.h b/cpu/cc26xx/ti-lib.h new file mode 100644 index 000000000..df5e2cf39 --- /dev/null +++ b/cpu/cc26xx/ti-lib.h @@ -0,0 +1,667 @@ +/* + * 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 cc26xx + * @{ + * + * \defgroup cc26xx-ti-lib TI CC26xxware Glue + * + * Glue file which renames TI CC26xxware functions. Thus, for example, + * PowerCtrlIOFreezeDisable() becomes power_ctrl_io_freeze_disable() + * + * This is not strictly required and a call to the former will work perfectly + * correctly. However, in using those macros, we make the core of the Contiki + * port match the naming convention. + * + * Since all functions are prefixed with ti_lib, it also becomes clear to the + * reader that this is a call to TI driverlib's sources and not a call to a + * function inside Contiki + * + * @{ + * + * \file + * Header file with macros which rename TI CC26xxware functions. + */ +#ifndef TI_LIB_H_ +#define TI_LIB_H_ +/*---------------------------------------------------------------------------*/ +/* aon_batmon.h */ +#include "driverlib/aon_batmon.h" + +#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_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__) +/*---------------------------------------------------------------------------*/ +/* aon_event.h */ +#include "driverlib/aon_event.h" + +#define ti_lib_aon_event_mcu_wake_up_set(...) AONEventMcuWakeUpSet(__VA_ARGS__) +#define ti_lib_aon_event_mcu_wake_up_get(...) AONEventMcuWakeUpGet(__VA_ARGS__) +#define ti_lib_aon_event_aux_wake_up_set(...) AONEventAuxWakeUpSet(__VA_ARGS__) +#define ti_lib_aon_event_aux_wake_up_get(...) AONEventAuxWakeUpGet(__VA_ARGS__) +#define ti_lib_aon_event_mcu_set(...) AONEventMcuSet(__VA_ARGS__) +#define ti_lib_aon_event_mcu_get(...) AONEventMcuGet(__VA_ARGS__) +#define ti_lib_aon_event_rtc_set(...) AONEventRtcSet(__VA_ARGS__) +#define ti_lib_aon_event_rtc_get(...) AONEventRtcGet(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* aon_ioc.h */ +#include "driverlib/aon_ioc.h" + +#define ti_lib_aon_ioc_drive_strength_set(...) AONIOCDriveStrengthSet(__VA_ARGS__) +#define ti_lib_aon_ioc_drive_strength_get(...) AONIOCDriveStrengthGet(__VA_ARGS__) +#define ti_lib_aon_ioc_freeze_enable(...) AONIOCFreezeEnable(__VA_ARGS__) +#define ti_lib_aon_ioc_freeze_disable(...) AONIOCFreezeDisable(__VA_ARGS__) +#define ti_lib_aon_ioc_32_khz_output_disable(...) AONIOC32kHzOutputDisable(__VA_ARGS__) +#define ti_lib_aon_ioc_32_khz_output_enable(...) AONIOC32kHzOutputEnable(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* aon_rtc.h */ +#include "driverlib/aon_rtc.h" + +#define ti_lib_aon_rtc_enable(...) AONRTCEnable(__VA_ARGS__) +#define ti_lib_aon_rtc_disable(...) AONRTCDisable(__VA_ARGS__) +#define ti_lib_aon_rtc_status(...) AONRTCStatus(__VA_ARGS__) +#define ti_lib_aon_rtc_reset(...) AONRTCReset(__VA_ARGS__) +#define ti_lib_aon_rtc_delay_config(...) AONRTCDelayConfig(__VA_ARGS__) +#define ti_lib_aon_rtc_combined_event_config(...) AONRTCCombinedEventConfig(__VA_ARGS__) +#define ti_lib_aon_rtc_event_clear(...) AONRTCEventClear(__VA_ARGS__) +#define ti_lib_aon_rtc_event_get(...) AONRTCEventGet(__VA_ARGS__) +#define ti_lib_aon_rtc_sec_get(...) AONRTCSecGet(__VA_ARGS__) +#define ti_lib_aon_rtc_fraction_get(...) AONRTCFractionGet(__VA_ARGS__) +#define ti_lib_aon_rtc_sub_sec_incr_get(...) AONRTCSubSecIncrGet(__VA_ARGS__) +#define ti_lib_aon_rtc_mode_ch1_set(...) AONRTCModeCh1Set(__VA_ARGS__) +#define ti_lib_aon_rtc_mode_ch1_get(...) AONRTCModeCh1Get(__VA_ARGS__) +#define ti_lib_aon_rtc_mode_ch2_set(...) AONRTCModeCh2Set(__VA_ARGS__) +#define ti_lib_aon_rtc_mode_ch2_get(...) AONRTCModeCh2Get(__VA_ARGS__) +#define ti_lib_aon_rtc_channel_enable(...) AONRTCChannelEnable(__VA_ARGS__) +#define ti_lib_aon_rtc_channel_disable(...) AONRTCChannelDisable(__VA_ARGS__) +#define ti_lib_aon_rtc_compare_value_set(...) AONRTCCompareValueSet(__VA_ARGS__) +#define ti_lib_aon_rtc_compare_value_get(...) AONRTCCompareValueGet(__VA_ARGS__) +#define ti_lib_aon_rtc_current_compare_value_get(...) AONRTCCurrentCompareValueGet(__VA_ARGS__) +#define ti_lib_aon_rtc_inc_value_ch2_set(...) AONRTCIncValueCh2Set(__VA_ARGS__) +#define ti_lib_aon_rtc_inc_value_ch2_get(...) AONRTCIncValueCh2Get(__VA_ARGS__) +#define ti_lib_aon_rtc_capture_value_ch1_get(...) AONRTCCaptureValueCh1Get(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* aon_wuc.h */ +#include "driverlib/aon_wuc.h" + +#define ti_lib_aon_wuc_mcu_wake_up_config(...) AONWUCMcuWakeUpConfig(__VA_ARGS__) +#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_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_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__) +#define ti_lib_aon_wuc_osc_config(...) AONWUCOscConfig(__VA_ARGS__) +#define ti_lib_aon_wuc_jtag_power_off(...) AONWUCJtagPowerOff(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* aux_wuc.h */ +#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_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__) +#define ti_lib_aux_wuc_freeze_enable(...) AUXWUCFreezeEnable(__VA_ARGS__) +#define ti_lib_aux_wuc_freeze_disable(...) AUXWUCFreezeDisable(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* cpu.h */ +#include "driverlib/cpu.h" + +#define ti_lib_cpu_cpsid(...) CPUcpsid(__VA_ARGS__) +#define ti_lib_cpu_cpsie(...) CPUcpsie(__VA_ARGS__) +#define ti_lib_cpu_primask(...) CPUprimask(__VA_ARGS__) +#define ti_lib_cpu_wfi(...) CPUwfi(__VA_ARGS__) +#define ti_lib_cpu_wfe(...) CPUwfe(__VA_ARGS__) +#define ti_lib_cpu_sev(...) CPUsev(__VA_ARGS__) +#define ti_lib_cpu_base_pri_get(...) CPUbasepriGet(__VA_ARGS__) +#define ti_lib_cpu_base_pri_set(...) CPUbasepriSet(__VA_ARGS__) +#define ti_lib_cpu_delay(...) CPUdelay(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* ddi.h */ +#include "driverlib/ddi.h" + +#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__) +#define ti_lib_ddi_32_bits_clear(...) DDI32BitsClear(__VA_ARGS__) +#define ti_lib_ddi_8_set_val_bit(...) DDI8SetValBit(__VA_ARGS__) +#define ti_lib_ddi_16_set_val_bit(...) DDI16SetValBit(__VA_ARGS__) +#define ti_lib_ddi_16_bit_write(...) DDI16BitWrite(__VA_ARGS__) +#define ti_lib_ddi_16_bit_field_write(...) DDI16BitfieldWrite(__VA_ARGS__) +#define ti_lib_ddi_16_bit_read(...) DDI16BitRead(__VA_ARGS__) +#define ti_lib_ddi_16_bitfield_read(...) DDI16BitfieldRead(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* gpio.h */ +#include "driverlib/gpio.h" + +#define ti_lib_gpio_dir_mode_set(...) GPIODirModeSet(__VA_ARGS__) +#define ti_lib_gpio_dir_mode_get(...) GPIODirModeGet(__VA_ARGS__) +#define ti_lib_gpio_pin_write(...) GPIOPinWrite(__VA_ARGS__) +#define ti_lib_gpio_pin_read(...) GPIOPinRead(__VA_ARGS__) +#define ti_lib_gpio_pin_clear(...) GPIOPinClear(__VA_ARGS__) +#define ti_lib_gpio_pin_toggle(...) GPIOPinToggle(__VA_ARGS__) +#define ti_lib_gpio_event_get(...) GPIOEventGet(__VA_ARGS__) +#define ti_lib_gpio_event_clear(...) GPIOEventClear(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* i2c.h */ +#include "driverlib/i2c.h" + +#define ti_lib_i2c_int_register(...) I2CIntRegister(__VA_ARGS__) +#define ti_lib_i2c_int_unregister(...) I2CIntUnregister(__VA_ARGS__) +#define ti_lib_i2c_master_bus_busy(...) I2CMasterBusBusy(__VA_ARGS__) +#define ti_lib_i2c_master_busy(...) I2CMasterBusy(__VA_ARGS__) +#define ti_lib_i2c_master_control(...) I2CMasterControl(__VA_ARGS__) +#define ti_lib_i2c_master_data_get(...) I2CMasterDataGet(__VA_ARGS__) +#define ti_lib_i2c_master_data_put(...) I2CMasterDataPut(__VA_ARGS__) +#define ti_lib_i2c_master_disable(...) I2CMasterDisable(__VA_ARGS__) +#define ti_lib_i2c_master_enable(...) I2CMasterEnable(__VA_ARGS__) +#define ti_lib_i2c_master_err(...) I2CMasterErr(__VA_ARGS__) +#define ti_lib_i2c_master_init_exp_clk(...) I2CMasterInitExpClk(__VA_ARGS__) +#define ti_lib_i2c_master_int_clear(...) I2CMasterIntClear(__VA_ARGS__) +#define ti_lib_i2c_master_int_disable(...) I2CMasterIntDisable(__VA_ARGS__) +#define ti_lib_i2c_master_int_enable(...) I2CMasterIntEnable(__VA_ARGS__) +#define ti_lib_i2c_master_int_status(...) I2CMasterIntStatus(__VA_ARGS__) +#define ti_lib_i2c_master_slave_addr_set(...) I2CMasterSlaveAddrSet(__VA_ARGS__) +#define ti_lib_i2c_slave_data_get(...) I2CSlaveDataGet(__VA_ARGS__) +#define ti_lib_i2c_slave_data_put(...) I2CSlaveDataPut(__VA_ARGS__) +#define ti_lib_i2c_slave_disable(...) I2CSlaveDisable(__VA_ARGS__) +#define ti_lib_i2c_slave_enable(...) I2CSlaveEnable(__VA_ARGS__) +#define ti_lib_i2c_slave_init(...) I2CSlaveInit(__VA_ARGS__) +#define ti_lib_i2c_slave_address_set(...) I2CSlaveAddressSet(__VA_ARGS__) +#define ti_lib_i2c_slave_int_clear(...) I2CSlaveIntClear(__VA_ARGS__) +#define ti_lib_i2c_slave_int_disable(...) I2CSlaveIntDisable(__VA_ARGS__) +#define ti_lib_i2c_slave_int_enable(...) I2CSlaveIntEnable(__VA_ARGS__) +#define ti_lib_i2c_slave_int_status(...) I2CSlaveIntStatus(__VA_ARGS__) +#define ti_lib_i2c_slave_status(...) I2CSlaveStatus(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* interrupt.h */ +#include "driverlib/interrupt.h" + +#define ti_lib_int_master_enable(...) IntMasterEnable(__VA_ARGS__) +#define ti_lib_int_master_disable(...) IntMasterDisable(__VA_ARGS__) +#define ti_lib_int_register(...) IntRegister(__VA_ARGS__); +#define ti_lib_int_unregsiter(...) IntUnregister(__VA_ARGS__) +#define ti_lib_int_priority_grouping_set(...) IntPriorityGroupingSet(__VA_ARGS__) +#define ti_lib_int_priority_grouping_get(...) IntPriorityGroupingGet(__VA_ARGS__) +#define ti_lib_int_priority_set(...) IntPrioritySet(__VA_ARGS__) +#define ti_lib_int_priority_get(...) IntPriorityGet(__VA_ARGS__) +#define ti_lib_int_enable(...) IntEnable(__VA_ARGS__) +#define ti_lib_int_disable(...) IntDisable(__VA_ARGS__) +#define ti_lib_int_pend_set(...) IntPendSet(__VA_ARGS__) +#define ti_lib_int_pend_get(...) IntPendGet(__VA_ARGS__) +#define ti_lib_int_pend_clear(...) IntPendClear(__VA_ARGS__) +#define ti_lib_int_mask_set(...) IntPriorityMaskSet(__VA_ARGS__) +#define ti_lib_int_mask_get(...) IntPriorityMaskGet(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* ioc.h */ +#include "driverlib/ioc.h" + +#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__) +#define ti_lib_ioc_io_input_set(...) IOCIOInputSet(__VA_ARGS__) +#define ti_lib_ioc_io_slew_ctrl_set(...) IOCIOSlewCtrlSet(__VA_ARGS__) +#define ti_lib_ioc_io_drv_strength_set(...) IOCIODrvStrengthSet(__VA_ARGS__) +#define ti_lib_ioc_io_port_id_set(...) IOCIOPortIdSet(__VA_ARGS__) +#define ti_lib_ioc_io_int_set(...) IOCIOIntSet(__VA_ARGS__) +#define ti_lib_ioc_int_register(...) IOCIntRegister(__VA_ARGS__); +#define ti_lib_ioc_int_unregister(...) IOCIntUnregister(__VA_ARGS__) +#define ti_lib_ioc_int_enable(...) IOCIntEnable(__VA_ARGS__) +#define ti_lib_ioc_int_disable(...) IOCIntDisable(__VA_ARGS__) +#define ti_lib_ioc_int_clear(...) IOCIntClear(__VA_ARGS__) +#define ti_lib_ioc_int_status(...) IOCIntStatus(__VA_ARGS__) +#define ti_lib_ioc_pin_type_gpio_input(...) IOCPinTypeGpioInput(__VA_ARGS__) +#define ti_lib_ioc_pin_type_gpio_output(...) IOCPinTypeGpioOutput(__VA_ARGS__) +#define ti_lib_ioc_pin_type_uart(...) IOCPinTypeUart(__VA_ARGS__) +#define ti_lib_ioc_pin_type_ssi_master(...) IOCPinTypeSsiMaster(__VA_ARGS__) +#define ti_lib_ioc_pin_type_ssi_slave(...) IOCPinTypeSsiSlave(__VA_ARGS__) +#define ti_lib_ioc_pin_type_i2c(...) IOCPinTypeI2c(__VA_ARGS__) +#define ti_lib_ioc_pin_type_aux(...) IOCPinTypeAux(__VA_ARGS__) +#define ti_lib_ioc_pin_type_spis(...) IOCPinTypeSpis(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* osc.h */ +#include "driverlib/osc.h" + +#define ti_lib_osc_xhf_power_mode_set(...) OSCXHfPowerModeSet(__VA_ARGS__) +#define ti_lib_osc_clock_source_set(...) OSCClockSourceSet(__VA_ARGS__) +#define ti_lib_osc_clock_source_get(...) OSCClockSourceGet(__VA_ARGS__) +#define ti_lib_osc_hf_source_ready(...) OSCHfSourceReady(__VA_ARGS__) +#define ti_lib_osc_hf_source_switch(...) OSCHfSourceSwitch(__VA_ARGS__) +#define ti_lib_osc_interface_enable(...) OSCInterfaceEnable(__VA_ARGS__) +#define ti_lib_osc_interface_disable(...) OSCInterfaceDisable(__VA_ARGS__) +#define ti_lib_osc_hf_get_startup_time(...) OSCHF_GetStartupTime(__VA_ARGS__) +#define ti_lib_osc_hf_turn_on_xosc(...) OSCHF_TurnOnXosc(__VA_ARGS__) +#define ti_lib_osc_hf_attempt_to_switch_to_xosc(...) OSCHF_AttemptToSwitchToXosc(__VA_ARGS__) +#define ti_lib_osc_hf_switch_to_rc_osc_turn_off_xosc(...) OSCHF_SwitchToRcOscTurnOffXosc(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* prcm.h */ +#include "driverlib/prcm.h" + +#define ti_lib_prcm_inf_clock_configure_set(...) PRCMInfClockConfigureSet(__VA_ARGS__) +#define ti_lib_prcm_inf_clock_configure_get(...) PRCMInfClockConfigureGet(__VA_ARGS__) +#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__) +#define ti_lib_prcm_load_set(...) PRCMLoadSet(__VA_ARGS__) +#define ti_lib_prcm_load_get(...) PRCMLoadGet(__VA_ARGS__) +#define ti_lib_prcm_domain_enable(...) PRCMDomainEnable(__VA_ARGS__) +#define ti_lib_prcm_domain_disable(...) PRCMDomainDisable(__VA_ARGS__) +#define ti_lib_prcm_power_domain_on(...) PRCMPowerDomainOn(__VA_ARGS__) +#define ti_lib_prcm_power_domain_off(...) PRCMPowerDomainOff(__VA_ARGS__) +#define ti_lib_prcm_rf_power_down_when_idle(...) PRCMRfPowerDownWhenIdle(__VA_ARGS__) +#define ti_lib_prcm_peripheral_run_enable(...) PRCMPeripheralRunEnable(__VA_ARGS__) +#define ti_lib_prcm_peripheral_run_disable(...) PRCMPeripheralRunDisable(__VA_ARGS__) +#define ti_lib_prcm_peripheral_sleep_enable(...) PRCMPeripheralSleepEnable(__VA_ARGS__) +#define ti_lib_prcm_peripheral_sleep_disable(...) PRCMPeripheralSleepDisable(__VA_ARGS__) +#define ti_lib_prcm_peripheral_deep_sleep_enable(...) PRCMPeripheralDeepSleepEnable(__VA_ARGS__) +#define ti_lib_prcm_peripheral_deep_sleep_disable(...) PRCMPeripheralDeepSleepDisable(__VA_ARGS__) +#define ti_lib_prcm_power_domain_status(...) PRCMPowerDomainStatus(__VA_ARGS__) +#define ti_lib_prcm_rf_ready(...) PRCMRfReady(__VA_ARGS__) +#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__) +/*---------------------------------------------------------------------------*/ +/* sys_ctrl.h */ +#include "driverlib/pwr_ctrl.h" + +#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__) +#define ti_lib_pwr_ctrl_io_freeze_disable(...) PowerCtrlIOFreezeDisable(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* rom.h */ +#include "driverlib/rom.h" + +/* AON API */ +#define ti_lib_rom_aon_event_mcu_wake_up_set ROM_AONEventMcuWakeUpSet +#define ti_lib_rom_aon_event_mcu_wake_up_get ROM_AONEventMcuWakeUpGet +#define ti_lib_rom_aon_event_aux_wake_up_set ROM_AONEventAuxWakeUpSet +#define ti_lib_rom_aon_event_aux_wake_up_get ROM_AONEventAuxWakeUpGet +#define ti_lib_rom_aon_event_mcu_set ROM_AONEventMcuSet +#define ti_lib_rom_aon_event_mcu_get ROM_AONEventMcuGet + +/* AON_IOC API */ +#define ti_lib_rom_aon_ioc_drive_strength_set ROM_AONIOCDriveStrengthSet +#define ti_lib_rom_aon_ioc_drive_strength_get ROM_AONIOCDriveStrengthGet + +/* AON_RTC API */ +#define ti_lib_rom_aon_rtc_status ROM_AONRTCStatus +#define ti_lib_rom_aon_rtc_event_clear ROM_AONRTCEventClear +#define ti_lib_rom_aon_rtc_event_get ROM_AONRTCEventGet +#define ti_lib_rom_aon_rtc_mode_ch1_set ROM_AONRTCModeCh1Set +#define ti_lib_rom_aon_rtc_mode_ch1_get ROM_AONRTCModeCh1Get +#define ti_lib_rom_aon_rtc_mode_ch2_set ROM_AONRTCModeCh2Set +#define ti_lib_rom_aon_rtc_mode_ch2_get ROM_AONRTCModeCh2Get +#define ti_lib_rom_aon_rtc_channel_enable ROM_AONRTCChannelEnable +#define ti_lib_rom_aon_rtc_channel_disable ROM_AONRTCChannelDisable +#define ti_lib_rom_aon_rtc_compare_value_set ROM_AONRTCCompareValueSet +#define ti_lib_rom_aon_rtc_compare_value_get ROM_AONRTCCompareValueGet +#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 +#define ti_lib_rom_aon_wuc_recharge_ctrl_config_set ROM_AONWUCRechargeCtrlConfigSet +#define ti_lib_rom_aon_wuc_osc_config ROM_AONWUCOscConfig + +/* AUX_TDC API */ +#define ti_lib_rom_aux_tdc_config_set ROM_AUXTDCConfigSet +#define ti_lib_rom_aux_tdc_measurement_done ROM_AUXTDCMeasurementDone + +/* AUX_TIMER API */ +#define ti_lib_rom_aux_timer_configure ROM_AUXTimerConfigure +#define ti_lib_rom_aux_timer_start ROM_AUXTimerStart +#define ti_lib_rom_aux_timer_stop ROM_AUXTimerStop +#define ti_lib_rom_aux_timer_prescale_set ROM_AUXTimerPrescaleSet +#define ti_lib_rom_aux_timer_prescale_get ROM_AUXTimerPrescaleGet + +/* AUX_WUC API */ +#define ti_lib_rom_aux_wuc_clock_enable ROM_AUXWUCClockEnable +#define ti_lib_rom_aux_wuc_clock_disable ROM_AUXWUCClockDisable +#define ti_lib_rom_aux_wuc_clock_status ROM_AUXWUCClockStatus +#define ti_lib_rom_aux_wuc_power_ctrl ROM_AUXWUCPowerCtrl + +/* FLASH API */ +#define ti_lib_rom_flash_power_mode_get ROM_FlashPowerModeGet +#define ti_lib_rom_flash_protection_set ROM_FlashProtectionSet +#define ti_lib_rom_flash_protection_get ROM_FlashProtectionGet +#define ti_lib_rom_flash_protection_save ROM_FlashProtectionSave +#define ti_lib_rom_flash_sector_erase ROM_FlashSectorErase +#define ti_lib_rom_flash_program ROM_FlashProgram +#define ti_lib_rom_flash_program_nowait ROM_FlashProgramNowait + +#define ti_lib_rom_flash_efuse_read_row ROM_FlashEfuseReadRow +#define ti_lib_rom_flash_disable_sectors_for_write ROM_FlashDisableSectorsForWrite + +/* I2C API */ +#define ti_lib_rom_i2c_master_init_exp_clk ROM_I2CMasterInitExpClk +#define ti_lib_rom_i2c_master_err ROM_I2CMasterErr + +/* INTERRUPT API */ +#define ti_lib_rom_int_priority_grouping_set ROM_IntPriorityGroupingSet +#define ti_lib_rom_int_priority_grouping_get ROM_IntPriorityGroupingGet +#define ti_lib_rom_int_priority_set ROM_IntPrioritySet +#define ti_lib_rom_int_priority_get ROM_IntPriorityGet +#define ti_lib_rom_int_enable ROM_IntEnable +#define ti_lib_rom_int_disable ROM_IntDisable +#define ti_lib_rom_int_pend_set ROM_IntPendSet +#define ti_lib_rom_int_pend_get ROM_IntPendGet +#define ti_lib_rom_int_pend_clear ROM_IntPendClear + +/* IOC API */ +#define ti_lib_rom_ioc_port_configure_set ROM_IOCPortConfigureSet +#define ti_lib_rom_ioc_port_configure_get ROM_IOCPortConfigureGet +#define ti_lib_rom_ioc_io_shutdown_set ROM_IOCIOShutdownSet +#define ti_lib_rom_ioc_io_jtag_set ROM_IOCIOJTagSet +#define ti_lib_rom_ioc_io_mode_set ROM_IOCIOModeSet +#define ti_lib_rom_ioc_io_int_set ROM_IOCIOIntSet +#define ti_lib_rom_ioc_io_port_pull_set ROM_IOCIOPortPullSet +#define ti_lib_rom_ioc_io_hyst_set ROM_IOCIOHystSet +#define ti_lib_rom_ioc_io_input_set ROM_IOCIOInputSet +#define ti_lib_rom_ioc_io_slew_ctrl_set ROM_IOCIOSlewCtrlSet +#define ti_lib_rom_ioc_io_drv_strength_set ROM_IOCIODrvStrengthSet +#define ti_lib_rom_ioc_io_port_id_set ROM_IOCIOPortIdSet +#define ti_lib_rom_ioc_int_enable ROM_IOCIntEnable +#define ti_lib_rom_ioc_int_disable ROM_IOCIntDisable +#define ti_lib_rom_ioc_pin_type_gpio_input ROM_IOCPinTypeGpioInput +#define ti_lib_rom_ioc_pin_type_gpio_output ROM_IOCPinTypeGpioOutput +#define ti_lib_rom_ioc_pin_type_uart ROM_IOCPinTypeUart +#define ti_lib_rom_ioc_pin_type_ssi_master ROM_IOCPinTypeSsiMaster +#define ti_lib_rom_ioc_pin_type_ssi_slave ROM_IOCPinTypeSsiSlave +#define ti_lib_rom_ioc_pin_type_i2c ROM_IOCPinTypeI2c +#define ti_lib_rom_ioc_pin_type_spis ROM_IOCPinTypeSpis +#define ti_lib_rom_ioc_pin_type_aux ROM_IOCPinTypeAux + +/* 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 +#define ti_lib_rom_prcm_peripheral_run_enable ROM_PRCMPeripheralRunEnable +#define ti_lib_rom_prcm_peripheral_run_disable ROM_PRCMPeripheralRunDisable +#define ti_lib_rom_prcm_peripheral_sleep_enable ROM_PRCMPeripheralSleepEnable +#define ti_lib_rom_prcm_peripheral_sleep_disable ROM_PRCMPeripheralSleepDisable +#define ti_lib_rom_prcm_peripheral_deep_sleep_enable ROM_PRCMPeripheralDeepSleepEnable +#define ti_lib_rom_prcm_peripheral_deep_sleep_disable ROM_PRCMPeripheralDeepSleepDisable +#define ti_lib_rom_prcm_power_domain_status ROM_PRCMPowerDomainStatus +#define ti_lib_rom_prcm_deep_sleep ROM_PRCMDeepSleep +#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 + +/* SPIS API */ +#define ti_lib_rom_spis_data_put ROM_SPISDataPut +#define ti_lib_rom_spis_tx_get_value ROM_SPISTxGetValue +#define ti_lib_rom_spis_data_get ROM_SPISDataGet +#define ti_lib_rom_spis_rx_get_value ROM_SPISRxGetValue +#define ti_lib_rom_spis_int_status ROM_SPISIntStatus + +/* SSI API */ +#define ti_lib_rom_ssi_config_set_exp_clk ROM_SSIConfigSetExpClk +#define ti_lib_rom_ssi_data_put ROM_SSIDataPut +#define ti_lib_rom_ssi_data_put_non_blocking ROM_SSIDataPutNonBlocking +#define ti_lib_rom_ssi_data_get ROM_SSIDataGet +#define ti_lib_rom_ssi_data_get_non_blocking ROM_SSIDataGetNonBlocking + +/* TIMER API */ +#define ti_lib_rom_timer_configure ROM_TimerConfigure +#define ti_lib_rom_timer_level_control ROM_TimerLevelControl +#define ti_lib_rom_timer_trigger_control ROM_TimerTriggerControl +#define ti_lib_rom_timer_stall_control ROM_TimerStallControl +#define ti_lib_rom_timer_wait_on_trigger_control ROM_TimerWaitOnTriggerControl + +/* TRNG API */ +#define ti_lib_rom_trng_configure ROM_TRNGConfigure +#define ti_lib_rom_trng_number_get ROM_TRNGNumberGet + +/* UART API */ +#define ti_lib_rom_uart_fifo_level_get ROM_UARTFIFOLevelGet +#define ti_lib_rom_uart_config_set_exp_clk ROM_UARTConfigSetExpClk +#define ti_lib_rom_uart_config_get_exp_clk ROM_UARTConfigGetExpClk +#define ti_lib_rom_uart_disable ROM_UARTDisable +#define ti_lib_rom_uart_char_get_non_blocking ROM_UARTCharGetNonBlocking +#define ti_lib_rom_uart_char_get ROM_UARTCharGet +#define ti_lib_rom_uart_char_put_non_blocking ROM_UARTCharPutNonBlocking +#define ti_lib_rom_uart_char_put ROM_UARTCharPut + +/* UDMA API */ +#define ti_lib_rom_udma_channel_attribute_enable ROM_uDMAChannelAttributeEnable +#define ti_lib_rom_udma_channel_attribute_disable ROM_uDMAChannelAttributeDisable +#define ti_lib_rom_udma_channel_attribute_get ROM_uDMAChannelAttributeGet +#define ti_lib_rom_udma_channel_control_set ROM_uDMAChannelControlSet +#define ti_lib_rom_udma_channel_transfer_set ROM_uDMAChannelTransferSet +#define ti_lib_rom_udma_channel_scatter_gather_set ROM_uDMAChannelScatterGatherSet +#define ti_lib_rom_udma_channel_size_get ROM_uDMAChannelSizeGet +#define ti_lib_rom_udma_channel_mode_get ROM_uDMAChannelModeGet + +/* VIMS API */ +#define ti_lib_rom_vims_configure ROM_VIMSConfigure +#define ti_lib_rom_vims_mode_set ROM_VIMSModeSet +#define ti_lib_rom_vims_mode_get ROM_VIMSModeGet +/*---------------------------------------------------------------------------*/ +/* sys_ctrl.h */ +#include "driverlib/sys_ctrl.h" + +#define ti_lib_sys_ctrl_power_everything(...) SysCtrlPowerEverything(__VA_ARGS__) +#define ti_lib_sys_ctrl_powerdown(...) SysCtrlPowerdown(__VA_ARGS__) +#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__) +/*---------------------------------------------------------------------------*/ +/* ssi.h */ +#include "driverlib/ssi.h" + +#define ti_lib_ssi_config_set_exp_clk(...) SSIConfigSetExpClk(__VA_ARGS__) +#define ti_lib_ssi_enable(...) SSIEnable(__VA_ARGS__) +#define ti_lib_ssi_disable(...) SSIDisable(__VA_ARGS__) +#define ti_lib_ssi_data_put(...) SSIDataPut(__VA_ARGS__) +#define ti_lib_ssi_data_put_non_blocking(...) SSIDataPutNonBlocking(__VA_ARGS__) +#define ti_lib_ssi_data_get(...) SSIDataGet(__VA_ARGS__) +#define ti_lib_ssi_data_get_non_blocking(...) SSIDataGetNonBlocking(__VA_ARGS__) +#define ti_lib_ssi_busy(...) SSIBusy(__VA_ARGS__) +#define ti_lib_ssi_status(...) SSIStatus(__VA_ARGS__) +#define ti_lib_ssi_int_register(...) SSIIntRegister(__VA_ARGS__) +#define ti_lib_ssi_int_unregister(...) SSIIntUnregister(__VA_ARGS__) +#define ti_lib_ssi_int_enable(...) SSIIntEnable(__VA_ARGS__) +#define ti_lib_ssi_int_disable(...) SSIIntDisable(__VA_ARGS__) +#define ti_lib_ssi_int_clear(...) SSIIntClear(__VA_ARGS__) +#define ti_lib_ssi_int_status(...) SSIIntStatus(__VA_ARGS__) +#define ti_lib_ssi_dma_enable(...) SSIDMAEnable(__VA_ARGS__) +#define ti_lib_ssi_dma_disable(...) SSIDMADisable(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* systick.h */ +#include "driverlib/systick.h" + +#define ti_lib_systick_enable(...) SysTickEnable(__VA_ARGS__) +#define ti_lib_systick_disable(...) SysTickDisable(__VA_ARGS__) +#define ti_lib_systick_int_register(...) SysTickIntRegister(__VA_ARGS__) +#define ti_lib_systick_int_unregister(...) SysTickIntUnregister(__VA_ARGS__) +#define ti_lib_systick_int_enable(...) SysTickIntEnable(__VA_ARGS__) +#define ti_lib_systick_int_disable(...) SysTickIntDisable(__VA_ARGS__) +#define ti_lib_systick_period_set(...) SysTickPeriodSet(__VA_ARGS__) +#define ti_lib_systick_period_get(...) SysTickPeriodGet(__VA_ARGS__) +#define ti_lib_systick_value_get(...) SysTickValueGet(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* timer.h */ +#include "driverlib/timer.h" + +#define ti_lib_timer_enable(...) TimerEnable(__VA_ARGS__) +#define ti_lib_timer_disable(...) TimerDisable(__VA_ARGS__) +#define ti_lib_timer_configure(...) TimerConfigure(__VA_ARGS__) +#define ti_lib_timer_level_control(...) TimerLevelControl(__VA_ARGS__) +#define ti_lib_timer_trigger_control(...) TimerTriggerControl(__VA_ARGS__) +#define ti_lib_timer_event_control(...) TimerEventControl(__VA_ARGS__) +#define ti_lib_timer_stall_control(...) TimerStallControl(__VA_ARGS__) +#define ti_lib_timer_wait_on_trigger_control(...) TimerWaitOnTriggerControl(__VA_ARGS__) +#define ti_lib_timer_rtc_enable(...) TimerRtcEnable(__VA_ARGS__) +#define ti_lib_timer_rtc_disable(...) TimerRtcDisable(__VA_ARGS__) +#define ti_lib_timer_prescale_set(...) TimerPrescaleSet(__VA_ARGS__) +#define ti_lib_timer_prescale_get(...) TimerPrescaleGet(__VA_ARGS__) +#define ti_lib_timer_prescale_match_set(...) TimerPrescaleMatchSet(__VA_ARGS__) +#define ti_lib_timer_prescale_match_get(...) TimerPrescaleMatchGet(__VA_ARGS__) +#define ti_lib_timer_load_set(...) TimerLoadSet(__VA_ARGS__) +#define ti_lib_timer_load_get(...) TimerLoadGet(__VA_ARGS__) +#define ti_lib_timer_value_get(...) TimerValueGet(__VA_ARGS__) +#define ti_lib_timer_match_set(...) TimerMatchSet(__VA_ARGS__) +#define ti_lib_timer_match_get(...) TimerMatchGet(__VA_ARGS__) +#define ti_lib_timer_int_register(...) TimerIntRegister(__VA_ARGS__) +#define ti_lib_timer_int_unregister(...) TimerIntUnregister(__VA_ARGS__) +#define ti_lib_timer_int_enable(...) TimerIntEnable(__VA_ARGS__) +#define ti_lib_timer_int_disable(...) TimerIntDisable(__VA_ARGS__) +#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__) +/*---------------------------------------------------------------------------*/ +/* uart.h */ +#include "driverlib/uart.h" + +#define ti_lib_uart_parity_mode_set(...) UARTParityModeSet(__VA_ARGS__) +#define ti_lib_uart_parity_mode_get(...) UARTParityModeGet(__VA_ARGS__) +#define ti_lib_uart_fifo_level_set(...) UARTFIFOLevelSet(__VA_ARGS__) +#define ti_lib_uart_fifo_level_get(...) UARTFIFOLevelGet(__VA_ARGS__) +#define ti_lib_uart_config_set_exp_clk(...) UARTConfigSetExpClk(__VA_ARGS__) +#define ti_lib_uart_config_get_exp_clk(...) UARTConfigGetExpClk(__VA_ARGS__) +#define ti_lib_uart_enable(...) UARTEnable(__VA_ARGS__) +#define ti_lib_uart_disable(...) UARTDisable(__VA_ARGS__) +#define ti_lib_uart_fifo_enable(...) UARTFIFOEnable(__VA_ARGS__) +#define ti_lib_uart_fifo_disable(...) UARTFIFODisable(__VA_ARGS__) +#define ti_lib_uart_chars_avail(...) UARTCharsAvail(__VA_ARGS__) +#define ti_lib_uart_space_avail(...) UARTSpaceAvail(__VA_ARGS__) +#define ti_lib_uart_char_get_non_blocking(...) UARTCharGetNonBlocking(__VA_ARGS__) +#define ti_lib_uart_char_get(...) UARTCharGet(__VA_ARGS__) +#define ti_lib_uart_char_put_non_blocking(...) UARTCharPutNonBlocking(__VA_ARGS__) +#define ti_lib_uart_char_put(...) UARTCharPut(__VA_ARGS__) +#define ti_lib_uart_break_ctl(...) UARTBreakCtl(__VA_ARGS__) +#define ti_lib_uart_busy(...) UARTBusy(__VA_ARGS__) +#define ti_lib_uart_int_register(...) UARTIntRegister(__VA_ARGS__) +#define ti_lib_uart_int_unregister(...) UARTIntUnregister(__VA_ARGS__) +#define ti_lib_uart_int_enable(...) UARTIntEnable(__VA_ARGS__) +#define ti_lib_uart_int_disable(...) UARTIntDisable(__VA_ARGS__) +#define ti_lib_uart_int_status(...) UARTIntStatus(__VA_ARGS__) +#define ti_lib_uart_int_clear(...) UARTIntClear(__VA_ARGS__) +#define ti_lib_uart_dma_enable(...) UARTDMAEnable(__VA_ARGS__) +#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__) +/*---------------------------------------------------------------------------*/ +/* vims.h */ +#include "driverlib/vims.h" + +#define ti_lib_vims_configure(...) VIMSConfigure(__VA_ARGS__) +#define ti_lib_vims_mode_set(...) VIMSModeSet(__VA_ARGS__) +#define ti_lib_vims_mode_get(...) VIMSModeGet(__VA_ARGS__) +/*---------------------------------------------------------------------------*/ +/* 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__) +/*---------------------------------------------------------------------------*/ +#endif /* TI_LIB_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/cpu/mc1322x/clock.c b/cpu/mc1322x/clock.c index 611a90251..ac70dfcf5 100644 --- a/cpu/mc1322x/clock.c +++ b/cpu/mc1322x/clock.c @@ -97,7 +97,7 @@ clock_wait(clock_time_t t) while ((signed long)(current_clock - endticks) < 0) {;} } /*---------------------------------------------------------------------------*/ -/** +/* * Delay the CPU for up to 65535 microseconds. * Use the 250KHz MACA clock for longer delays to avoid interrupt effects. * However that can't be used if the radio is being power cycled! @@ -118,7 +118,7 @@ clock_delay_usec(uint16_t howlong) while(--i); } /*---------------------------------------------------------------------------*/ -/** +/* * Delay the CPU for up to 65535 milliseconds. The watchdog is NOT disabled. */ void @@ -127,7 +127,7 @@ clock_delay_msec(uint16_t howlong) while(howlong--) clock_delay_usec(1000); } /*---------------------------------------------------------------------------*/ -/** +/* * Legacy delay. The original clock_delay for the msp430 used a granularity * of 2.83 usec. This approximates that delay for values up to 1456 usec. * (The largest core call in leds.c uses 400). @@ -139,7 +139,7 @@ clock_delay(unsigned int howlong) clock_delay_usec((283*howlong)/100); } /*---------------------------------------------------------------------------*/ -/** +/* * Adjust clock ticks after a cpu sleep. */ void clock_adjust_ticks(clock_time_t howmany) { diff --git a/cpu/msp430/Makefile.msp430 b/cpu/msp430/Makefile.msp430 index 182cd19dd..264538611 100644 --- a/cpu/msp430/Makefile.msp430 +++ b/cpu/msp430/Makefile.msp430 @@ -151,7 +151,7 @@ ifneq (,$(findstring 4.7.,$(shell msp430-gcc -dumpversion))) ifdef CPU_HAS_MSP430X TARGET_MEMORY_MODEL ?= medium CFLAGS += -mmemory-model=$(TARGET_MEMORY_MODEL) - CFLAGS += -ffunction-sections -fdata-sections -mcode-region=far + CFLAGS += -ffunction-sections -fdata-sections -mcode-region=any LDFLAGS += -mmemory-model=$(TARGET_MEMORY_MODEL) -Wl,-gc-sections endif endif diff --git a/cpu/msp430/f1xxx/clock.c b/cpu/msp430/f1xxx/clock.c index b99827c04..b81bb7498 100644 --- a/cpu/msp430/f1xxx/clock.c +++ b/cpu/msp430/f1xxx/clock.c @@ -195,7 +195,7 @@ clock_delay(unsigned int i) } } /*---------------------------------------------------------------------------*/ -/** +/* * Wait for a multiple of 10 ms. * */ diff --git a/cpu/msp430/f5xxx/clock.c b/cpu/msp430/f5xxx/clock.c index b0047a9e6..1def811e6 100644 --- a/cpu/msp430/f5xxx/clock.c +++ b/cpu/msp430/f5xxx/clock.c @@ -192,7 +192,7 @@ clock_delay(unsigned int i) } } /*---------------------------------------------------------------------------*/ -/** +/* * Wait for a multiple of 10 ms. * */ diff --git a/cpu/stm32w108/clock.c b/cpu/stm32w108/clock.c index f4a17ad53..5e3464d16 100644 --- a/cpu/stm32w108/clock.c +++ b/cpu/stm32w108/clock.c @@ -113,7 +113,7 @@ clock_delay(unsigned int i) } } /*---------------------------------------------------------------------------*/ -/** +/* * Wait for a multiple of 1 ms. */ void diff --git a/cpu/stm32w108/hal/micro/cortexm3/mfg-token.c b/cpu/stm32w108/hal/micro/cortexm3/mfg-token.c index c6c0b532c..14d143bc7 100644 --- a/cpu/stm32w108/hal/micro/cortexm3/mfg-token.c +++ b/cpu/stm32w108/hal/micro/cortexm3/mfg-token.c @@ -50,10 +50,10 @@ void halInternalGetMfgTokenData(void *data, uint16_t ID, uint8_t index, uint8_t MEMCOPY(ram, eui64, 8 /*EUI64_SIZE*/); } else { //read from the Information Blocks. The token ID is only the - //bottom 16bits of the token's actual address. Since the info blocks - //exist in the range DATA_BIG_INFO_BASE-DATA_BIG_INFO_END, we need - //to OR the ID with DATA_BIG_INFO_BASE to get the real address. - uint32_t realAddress = (DATA_BIG_INFO_BASE|ID) + (len*index); + //DATA_BIG_INFO_BASE-relative 16-bit offset of the token. Since the + //info blocks exist in the range DATA_BIG_INFO_BASE-DATA_BIG_INFO_END, + //we need to add the ID to DATA_BIG_INFO_BASE to get the real address. + uint32_t realAddress = (DATA_BIG_INFO_BASE+ID) + (len*index); uint8_t *flash = (uint8_t *)realAddress; @@ -77,7 +77,7 @@ void halInternalGetMfgTokenData(void *data, uint16_t ID, uint8_t index, uint8_t void halInternalSetMfgTokenData(uint16_t token, void *data, uint8_t len) { StStatus flashStatus; - uint32_t realAddress = (DATA_BIG_INFO_BASE|token); + uint32_t realAddress = (DATA_BIG_INFO_BASE+token); uint8_t * flash = (uint8_t *)realAddress; uint32_t i; diff --git a/dev/cc2420/cc2420.c b/dev/cc2420/cc2420.c index 1e0ce8c75..970f9dca7 100644 --- a/dev/cc2420/cc2420.c +++ b/dev/cc2420/cc2420.c @@ -152,6 +152,7 @@ static int cc2420_send(const void *data, unsigned short len); static int cc2420_receiving_packet(void); static int pending_packet(void); +static int get_cca_threshold(void); static int cc2420_cca(void); signed char cc2420_last_rssi; @@ -186,6 +187,9 @@ get_value(radio_param_t param, radio_value_t *value) } } return RADIO_RESULT_OK; + case RADIO_PARAM_CCA_THRESHOLD: + *value = get_cca_threshold() + RSSI_OFFSET; + return RADIO_RESULT_OK; case RADIO_PARAM_RSSI: /* Return the RSSI value in dBm */ *value = cc2420_rssi(); @@ -241,6 +245,9 @@ set_value(radio_param_t param, radio_value_t value) } cc2420_set_txpower(output_power[i - 1].config); return RADIO_RESULT_OK; + case RADIO_PARAM_CCA_THRESHOLD: + cc2420_set_cca_threshold(value - RSSI_OFFSET); + return RADIO_RESULT_OK; default: return RADIO_RESULT_NOT_SUPPORTED; } @@ -1033,6 +1040,17 @@ pending_packet(void) return CC2420_FIFOP_IS_1; } /*---------------------------------------------------------------------------*/ +static int +get_cca_threshold(void) +{ + int value; + + GET_LOCK(); + value = (int8_t)(getreg(CC2420_RSSI) >> 8); + RELEASE_LOCK(); + return value; +} +/*---------------------------------------------------------------------------*/ void cc2420_set_cca_threshold(int value) { diff --git a/dev/enc28j60/enc28j60-ip64-driver.c b/dev/enc28j60/enc28j60-ip64-driver.c new file mode 100644 index 000000000..f1804d998 --- /dev/null +++ b/dev/enc28j60/enc28j60-ip64-driver.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2012-2013, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "contiki.h" +#include "enc28j60.h" +#include "enc28j60-ip64-driver.h" + +#include "ip64.h" +#include "ip64-eth.h" + +#include +#include + +PROCESS(enc28j60_ip64_driver_process, "ENC28J60 IP64 driver"); + +/*---------------------------------------------------------------------------*/ +static void +init(void) +{ + uint8_t eui64[8]; + uint8_t macaddr[6]; + + /* Assume that linkaddr_node_addr holds the EUI64 of this device. */ + memcpy(eui64, &linkaddr_node_addr, sizeof(eui64)); + + /* Mangle the EUI64 into a 48-bit Ethernet address. */ + memcpy(&macaddr[0], &eui64[0], 3); + memcpy(&macaddr[3], &eui64[5], 3); + + /* In case the OUI happens to contain a broadcast bit, we mask that + out here. */ + macaddr[0] = (macaddr[0] & 0xfe); + + /* Set the U/L bit, in order to create a locally administered MAC address */ + macaddr[0] = (macaddr[0] | 0x02); + + memcpy(ip64_eth_addr.addr, macaddr, sizeof(macaddr)); + + printf("MAC addr %02x:%02x:%02x:%02x:%02x:%02x\n", + macaddr[0], macaddr[1], macaddr[2], + macaddr[3], macaddr[4], macaddr[5]); + enc28j60_init(macaddr); + process_start(&enc28j60_ip64_driver_process, NULL); +} +/*---------------------------------------------------------------------------*/ +static int +output(uint8_t *packet, uint16_t len) +{ + enc28j60_send(packet, len); + return len; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(enc28j60_ip64_driver_process, ev, data) +{ + static int len; + static struct etimer e; + PROCESS_BEGIN(); + + while(1) { + etimer_set(&e, 1); + PROCESS_WAIT_EVENT(); + len = enc28j60_read(ip64_packet_buffer, ip64_packet_buffer_maxlen); + if(len > 0) { + IP64_INPUT(ip64_packet_buffer, len); + } + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +const struct ip64_driver enc28j60_ip64_driver = { + init, + output +}; +/*---------------------------------------------------------------------------*/ diff --git a/dev/enc28j60/enc28j60-ip64-driver.h b/dev/enc28j60/enc28j60-ip64-driver.h new file mode 100644 index 000000000..29d3ed5a4 --- /dev/null +++ b/dev/enc28j60/enc28j60-ip64-driver.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2012-2013, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef ENC28J60_IP64_DRIVER_H +#define ENC28J60_IP64_DRIVER_H + +#include "ip64-driver.h" +extern const struct ip64_driver enc28j60_ip64_driver; + +#endif /* ENC28J60_IP64_DRIVER_H */ diff --git a/dev/enc28j60/enc28j60.c b/dev/enc28j60/enc28j60.c new file mode 100644 index 000000000..dd00dddeb --- /dev/null +++ b/dev/enc28j60/enc28j60.c @@ -0,0 +1,644 @@ +/* + * Copyright (c) 2012-2013, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "contiki.h" +#include "enc28j60.h" +#include +#include + +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +#define EIE 0x1b +#define EIR 0x1c +#define ESTAT 0x1d +#define ECON2 0x1e +#define ECON1 0x1f + +#define ESTAT_CLKRDY 0x01 +#define ESTAT_TXABRT 0x02 + +#define ECON1_RXEN 0x04 +#define ECON1_TXRTS 0x08 + +#define ECON2_AUTOINC 0x80 +#define ECON2_PKTDEC 0x40 + +#define EIR_TXIF 0x08 + +#define ERXTX_BANK 0x00 + +#define ERDPTL 0x00 +#define ERDPTH 0x01 +#define EWRPTL 0x02 +#define EWRPTH 0x03 +#define ETXSTL 0x04 +#define ETXSTH 0x05 +#define ETXNDL 0x06 +#define ETXNDH 0x07 +#define ERXSTL 0x08 +#define ERXSTH 0x09 +#define ERXNDL 0x0a +#define ERXNDH 0x0b +#define ERXRDPTL 0x0c +#define ERXRDPTH 0x0d + +#define RX_BUF_START 0x0000 +#define RX_BUF_END 0x0fff + +#define TX_BUF_START 0x1200 + +/* MACONx registers are in bank 2 */ +#define MACONX_BANK 0x02 + +#define MACON1 0x00 +#define MACON2 0x01 +#define MACON3 0x02 +#define MACON4 0x03 +#define MABBIPG 0x04 +#define MAIPGL 0x06 +#define MAIPGH 0x07 +#define MAMXFLL 0x0a +#define MAMXFLH 0x0b + +#define MACON1_TXPAUS 0x08 +#define MACON1_RXPAUS 0x04 +#define MACON1_MARXEN 0x01 + +#define MACON2_MARST 0x80 + +#define MACON3_PADCFG_FULL 0xe0 +#define MACON3_TXCRCEN 0x10 +#define MACON3_FRMLNEN 0x02 +#define MACON3_FULDPX 0x01 + +#define MAX_MAC_LENGTH 1518 + +#define MAADRX_BANK 0x03 +#define MAADR1 0x04 /* MAADR<47:40> */ +#define MAADR2 0x05 /* MAADR<39:32> */ +#define MAADR3 0x02 /* MAADR<31:24> */ +#define MAADR4 0x03 /* MAADR<23:16> */ +#define MAADR5 0x00 /* MAADR<15:8> */ +#define MAADR6 0x01 /* MAADR<7:0> */ + +#define EPKTCNT_BANK 0x01 +#define ERXFCON 0x18 +#define EPKTCNT 0x19 + +#define ERXFCON_UCEN 0x80 +#define ERXFCON_ANDOR 0x40 +#define ERXFCON_CRCEN 0x20 +#define ERXFCON_MCEN 0x02 +#define ERXFCON_BCEN 0x01 + + +PROCESS(enc_watchdog_process, "Enc28j60 watchdog"); + +static uint8_t initialized = 0; +static uint8_t enc_mac_addr[6]; +static int received_packets = 0; +static int sent_packets = 0; + +/*---------------------------------------------------------------------------*/ +static uint8_t +readreg(uint8_t reg) +{ + uint8_t r; + enc28j60_arch_spi_select(); + enc28j60_arch_spi_write(0x00 | (reg & 0x1f)); + r = enc28j60_arch_spi_read(); + enc28j60_arch_spi_deselect(); + return r; +} +/*---------------------------------------------------------------------------*/ +static void +writereg(uint8_t reg, uint8_t data) +{ + enc28j60_arch_spi_select(); + enc28j60_arch_spi_write(0x40 | (reg & 0x1f)); + enc28j60_arch_spi_write(data); + enc28j60_arch_spi_deselect(); +} +/*---------------------------------------------------------------------------*/ +static void +setregbank(uint8_t bank) +{ + writereg(ECON1, (readreg(ECON1) & 0xfc) | (bank & 0x03)); +} +/*---------------------------------------------------------------------------*/ +static void +writedatabyte(uint8_t byte) +{ + enc28j60_arch_spi_select(); + /* The Write Buffer Memory (WBM) command is 0 1 1 1 1 0 1 0 */ + enc28j60_arch_spi_write(0x7a); + enc28j60_arch_spi_write(byte); + enc28j60_arch_spi_deselect(); +} +/*---------------------------------------------------------------------------*/ +static void +writedata(uint8_t *data, int datalen) +{ + int i; + enc28j60_arch_spi_select(); + /* The Write Buffer Memory (WBM) command is 0 1 1 1 1 0 1 0 */ + enc28j60_arch_spi_write(0x7a); + for(i = 0; i < datalen; i++) { + enc28j60_arch_spi_write(data[i]); + } + enc28j60_arch_spi_deselect(); +} +/*---------------------------------------------------------------------------*/ +static uint8_t +readdatabyte(void) +{ + uint8_t r; + enc28j60_arch_spi_select(); + /* THe Read Buffer Memory (RBM) command is 0 0 1 1 1 0 1 0 */ + enc28j60_arch_spi_write(0x3a); + r = enc28j60_arch_spi_read(); + enc28j60_arch_spi_deselect(); + return r; +} +/*---------------------------------------------------------------------------*/ +static int +readdata(uint8_t *buf, int len) +{ + int i; + enc28j60_arch_spi_select(); + /* THe Read Buffer Memory (RBM) command is 0 0 1 1 1 0 1 0 */ + enc28j60_arch_spi_write(0x3a); + for(i = 0; i < len; i++) { + buf[i] = enc28j60_arch_spi_read(); + } + enc28j60_arch_spi_deselect(); + return i; +} +/*---------------------------------------------------------------------------*/ +static void +softreset(void) +{ + enc28j60_arch_spi_select(); + /* The System Command (soft reset) is 1 1 1 1 1 1 1 1 */ + enc28j60_arch_spi_write(0xff); + enc28j60_arch_spi_deselect(); +} +/*---------------------------------------------------------------------------*/ +static void +reset(void) +{ + PRINTF("enc28j60: resetting chip\n"); + + enc28j60_arch_spi_init(); + + /* + 6.0 INITIALIZATION + + Before the ENC28J60 can be used to transmit and receive packets, + certain device settings must be initialized. Depending on the + application, some configuration options may need to be + changed. Normally, these tasks may be accomplished once after + Reset and do not need to be changed thereafter. + + 6.1 Receive Buffer + + Before receiving any packets, the receive buffer must be + initialized by programming the ERXST and ERXND pointers. All + memory between and including the ERXST and ERXND addresses will be + dedicated to the receive hardware. It is recommended that the + ERXST pointer be programmed with an even address. + + Applications expecting large amounts of data and frequent packet + delivery may wish to allocate most of the memory as the receive + buffer. Applications that may need to save older packets or have + several packets ready for transmission should allocate less + memory. + + When programming the ERXST pointer, the ERXWRPT registers will + automatically be updated with the same values. The address in + ERXWRPT will be used as the starting location when the receive + hardware begins writing received data. For tracking purposes, the + ERXRDPT registers should additionally be programmed with the same + value. To program ERXRDPT, the host controller must write to + ERXRDPTL first, followed by ERXRDPTH. See Section 7.2.4 “Freeing + Receive Buffer Space for more information + + 6.2 Transmission Buffer + + All memory which is not used by the receive buffer is considered + the transmission buffer. Data which is to be transmitted should be + written into any unused space. After a packet is transmitted, + however, the hardware will write a seven-byte status vector into + memory after the last byte in the packet. Therefore, the host + controller should leave at least seven bytes between each packet + and the beginning of the receive buffer. No explicit action is + required to initialize the transmission buffer. + + 6.3 Receive Filters + + The appropriate receive filters should be enabled or disabled by + writing to the ERXFCON register. See Section 8.0 “Receive Filters + for information on how to configure it. + + 6.4 Waiting For OST + + If the initialization procedure is being executed immediately + following a Power-on Reset, the ESTAT.CLKRDY bit should be polled + to make certain that enough time has elapsed before proceeding to + modify the MAC and PHY registers. For more information on the OST, + see Section 2.2 “Oscillator Start-up Timer. + */ + + /* Wait for OST */ + while((readreg(ESTAT) & ESTAT_CLKRDY) == 0); + + softreset(); + + setregbank(ERXTX_BANK); + /* Set up receive buffer */ + writereg(ERXSTL, RX_BUF_START & 0xff); + writereg(ERXSTH, RX_BUF_START >> 8); + writereg(ERXNDL, RX_BUF_END & 0xff); + writereg(ERXNDH, RX_BUF_END >> 8); + writereg(ERDPTL, RX_BUF_START & 0xff); + writereg(ERDPTH, RX_BUF_START >> 8); + writereg(ERXRDPTL, RX_BUF_START & 0xff); + writereg(ERXRDPTH, RX_BUF_START >> 8); + + /* Receive filters */ + setregbank(EPKTCNT_BANK); + /* writereg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | + ERXFCON_MCEN | ERXFCON_BCEN);*/ + /* XXX: can't seem to get the unicast filter to work right now, + using promiscous mode for now. */ + writereg(ERXFCON, 0); + + /* + 6.5 MAC Initialization Settings + + Several of the MAC registers require configuration during + initialization. This only needs to be done once; the order of + programming is unimportant. + + 1. Clear the MARST bit in MACON2 to pull the MAC out of Reset. + + 2. Set the MARXEN bit in MACON1 to enable the MAC to receive + frames. If using full duplex, most applications should also set + TXPAUS and RXPAUS to allow IEEE defined flow control to function. + + 3. Configure the PADCFG, TXCRCEN and FULDPX bits of MACON3. Most + applications should enable automatic padding to at least 60 bytes + and always append a valid CRC. For convenience, many applications + may wish to set the FRMLNEN bit as well to enable frame length + status reporting. The FULDPX bit should be set if the application + will be connected to a full-duplex configured remote node; + otherwise, it should be left clear. + + 4. Configure the bits in MACON4. Many applications may not need to + modify the Reset default. + + 5. Program the MAMXFL registers with the maximum frame length to + be permitted to be received or transmitted. Normal network nodes + are designed to handle packets that are 1518 bytes or less. + + 6. Configure the Back-to-Back Inter-Packet Gap register, + MABBIPG. Most applications will program this register with 15h + when Full-Duplex mode is used and 12h when Half-Duplex mode is + used. + + 7. Configure the Non-Back-to-Back Inter-Packet Gap register low + byte, MAIPGL. Most applications will program this register with + 12h. + + 8. If half duplex is used, the Non-Back-to-Back Inter-Packet Gap + register high byte, MAIPGH, should be programmed. Most + applications will program this register to 0Ch. + + 9. If Half-Duplex mode is used, program the Retransmission and + Collision Window registers, MACLCON1 and MACLCON2. Most + applications will not need to change the default Reset values. If + the network is spread over exceptionally long cables, the default + value of MACLCON2 may need to be increased. + + 10. Program the local MAC address into the + MAADR0:MAADR5 registers. + */ + + setregbank(MACONX_BANK); + + /* Pull MAC out of reset */ + writereg(MACON2, 0);//readreg(MACON2) & (~MACON2_MARST)); + + /* Turn on reception and IEEE-defined flow control */ + writereg(MACON1, readreg(MACON1) | (MACON1_MARXEN + MACON1_TXPAUS + + MACON1_RXPAUS)); + + /* Set padding, crc, full duplex */ + writereg(MACON3, readreg(MACON3) | (MACON3_PADCFG_FULL + MACON3_TXCRCEN + + MACON3_FULDPX + MACON3_FRMLNEN)); + + /* Don't modify MACON4 */ + + /* Set maximum frame length in MAMXFL */ + writereg(MAMXFLL, MAX_MAC_LENGTH & 0xff); + writereg(MAMXFLH, MAX_MAC_LENGTH >> 8); + + /* Set back-to-back inter packet gap */ + writereg(MABBIPG, 0x15); + + /* Set non-back-to-back packet gap */ + writereg(MAIPGL, 0x12); + writereg(MAIPGH, 0x0c); + + /* Set MAC address */ + setregbank(MAADRX_BANK); + writereg(MAADR6, enc_mac_addr[5]); + writereg(MAADR5, enc_mac_addr[4]); + writereg(MAADR4, enc_mac_addr[3]); + writereg(MAADR3, enc_mac_addr[2]); + writereg(MAADR2, enc_mac_addr[1]); + writereg(MAADR1, enc_mac_addr[0]); + + /* Receive filters */ + setregbank(EPKTCNT_BANK); + writereg(ERXFCON, ERXFCON_UCEN | ERXFCON_CRCEN | ERXFCON_BCEN); + + /* + 6.6 PHY Initialization Settings + + Depending on the application, bits in three of the PHY module’s + registers may also require configuration. The PHCON1.PDPXMD bit + partially controls the device’s half/full-duplex + configuration. Normally, this bit is initialized correctly by the + external circuitry (see Section 2.6 “LED Configuration). If the + external circuitry is not present or incorrect, however, the host + controller must program the bit properly. Alternatively, for an + externally configurable system, the PDPXMD bit may be read and the + FULDPX bit be programmed to match. + + For proper duplex operation, the PHCON1.PDPXMD bit must also match + the value of the MACON3.FULDPX bit. + + If using half duplex, the host controller may wish to set the + PHCON2.HDLDIS bit to prevent automatic loopback of the data which + is transmitted. The PHY register, PHLCON, controls the outputs of + LEDA and LEDB. If an application requires a LED configuration + other than the default, PHLCON must be altered to match the new + requirements. The settings for LED operation are discussed in + Section 2.6 “LED Configuration. The PHLCON register is shown in + Register 2-2 (page 9). + */ + + /* Don't worry about PHY configuration for now */ + + /* Turn on autoincrement for buffer access */ + writereg(ECON2, readreg(ECON2) | ECON2_AUTOINC); + + /* Turn on reception */ + writereg(ECON1, ECON1_RXEN); +} +/*---------------------------------------------------------------------------*/ +void +enc28j60_init(uint8_t *mac_addr) +{ + if(initialized) { + return; + } + + memcpy(enc_mac_addr, mac_addr, 6); + + /* Start watchdog process */ + process_start(&enc_watchdog_process, NULL); + + reset(); + + initialized = 1; +} +/*---------------------------------------------------------------------------*/ +int +enc28j60_send(uint8_t *data, uint16_t datalen) +{ + int padding = 0; + + if(!initialized) { + return -1; + } + + /* + 1. Appropriately program the ETXST pointer to point to an unused + location in memory. It will point to the per packet control + byte. In the example, it would be programmed to 0120h. It is + recommended that an even address be used for ETXST. + + 2. Use the WBM SPI command to write the per packet control byte, + the destination address, the source MAC address, the + type/length and the data payload. + + 3. Appropriately program the ETXND pointer. It should point to the + last byte in the data payload. In the example, it would be + programmed to 0156h. + + 4. Clear EIR.TXIF, set EIE.TXIE and set EIE.INTIE to enable an + interrupt when done (if desired). + + 5. Start the transmission process by setting + ECON1.TXRTS. + */ + + setregbank(ERXTX_BANK); + /* Set up the transmit buffer pointer */ + writereg(ETXSTL, TX_BUF_START & 0xff); + writereg(ETXSTH, TX_BUF_START >> 8); + writereg(EWRPTL, TX_BUF_START & 0xff); + writereg(EWRPTH, TX_BUF_START >> 8); + + /* Write the transmission control register as the first byte of the + output packet. We write 0x00 to indicate that the default + configuration (the values in MACON3) will be used. */ +#define WITH_MANUAL_PADDING 1 +#if WITH_MANUAL_PADDING +#define PADDING_MIN_SIZE 60 + writedatabyte(0x0B); /* POVERRIDE, PCRCEN, PHUGEEN. Not PPADEN */ + if(datalen < PADDING_MIN_SIZE) { + padding = PADDING_MIN_SIZE - datalen; + } else { + padding = 0; + } +#else /* WITH_MANUAL_PADDING */ + writedatabyte(0x00); /* MACON3 */ + padding = 0; +#endif /* WITH_MANUAL_PADDING */ + + /* Write a pointer to the last data byte. */ + writereg(ETXNDL, (TX_BUF_START + datalen + 0 + padding) & 0xff); + writereg(ETXNDH, (TX_BUF_START + datalen + 0 + padding) >> 8); + + writedata(data, datalen); + if(padding > 0) { + uint8_t padding_buf[60]; + memset(padding_buf, 0, padding); + writedata(padding_buf, padding); + } + + /* Clear EIR.TXIF */ + writereg(EIR, readreg(EIR) & (~EIR_TXIF)); + + /* Don't care about interrupts for now */ + + /* Send the packet */ + writereg(ECON1, readreg(ECON1) | ECON1_TXRTS); + while((readreg(ECON1) & ECON1_TXRTS) > 0); + + if((readreg(ESTAT) & ESTAT_TXABRT) != 0) { + PRINTF("enc28j60: tx err: %d: %02x:%02x:%02x:%02x:%02x:%02x\n", datalen, + 0xff & data[0], 0xff & data[1], 0xff & data[2], + 0xff & data[3], 0xff & data[4], 0xff & data[5]); + } else { + PRINTF("enc28j60: tx: %d: %02x:%02x:%02x:%02x:%02x:%02x\n", datalen, + 0xff & data[0], 0xff & data[1], 0xff & data[2], + 0xff & data[3], 0xff & data[4], 0xff & data[5]); + } + sent_packets++; + PRINTF("enc28j60: sent_packets %d\n", sent_packets); + return datalen; +} +/*---------------------------------------------------------------------------*/ +int +enc28j60_read(uint8_t *buffer, uint16_t bufsize) +{ + int n, len, next, err; + + uint8_t nxtpkt[2]; + uint8_t status[2]; + uint8_t length[2]; + + err = 0; + + setregbank(EPKTCNT_BANK); + n = readreg(EPKTCNT); + + if(n == 0) { + return 0; + } + + PRINTF("enc28j60: EPKTCNT 0x%02x\n", n); + + setregbank(ERXTX_BANK); + /* Read the next packet pointer */ + nxtpkt[0] = readdatabyte(); + nxtpkt[1] = readdatabyte(); + + PRINTF("enc28j60: nxtpkt 0x%02x%02x\n", nxtpkt[1], nxtpkt[0]); + + length[0] = readdatabyte(); + length[1] = readdatabyte(); + + PRINTF("enc28j60: length 0x%02x%02x\n", length[1], length[0]); + + status[0] = readdatabyte(); + status[1] = readdatabyte(); + + /* This statement is just to avoid a compiler warning: */ + status[0] = status[0]; + PRINTF("enc28j60: status 0x%02x%02x\n", status[1], status[0]); + + len = (length[1] << 8) + length[0]; + if(bufsize >= len) { + readdata(buffer, len); + } else { + uint16_t i; + + err = 1; + + /* flush rx fifo */ + for(i = 0; i < len; i++) { + readdatabyte(); + } + } + + /* Read an additional byte at odd lengths, to avoid FIFO corruption */ + if((len % 2) != 0) { + readdatabyte(); + } + + /* Errata #14 */ + next = (nxtpkt[1] << 8) + nxtpkt[0]; + if(next == RX_BUF_START) { + next = RX_BUF_END; + } else { + next = next - 1; + } + writereg(ERXRDPTL, next & 0xff); + writereg(ERXRDPTH, next >> 8); + + writereg(ECON2, readreg(ECON2) | ECON2_PKTDEC); + + if(err) { + PRINTF("enc28j60: rx err: flushed %d\n", len); + return 0; + } + PRINTF("enc28j60: rx: %d: %02x:%02x:%02x:%02x:%02x:%02x\n", len, + 0xff & buffer[0], 0xff & buffer[1], 0xff & buffer[2], + 0xff & buffer[3], 0xff & buffer[4], 0xff & buffer[5]); + + received_packets++; + PRINTF("enc28j60: received_packets %d\n", received_packets); + return len; +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(enc_watchdog_process, ev, data) +{ + static struct etimer et; + + PROCESS_BEGIN(); + + while(1) { +#define RESET_PERIOD (30 * CLOCK_SECOND) + etimer_set(&et, RESET_PERIOD); + PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); + + PRINTF("enc28j60: test received_packet %d > sent_packets %d\n", received_packets, sent_packets); + if(received_packets <= sent_packets) { + PRINTF("enc28j60: resetting chip\n"); + reset(); + } + received_packets = 0; + sent_packets = 0; + } + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/dev/enc28j60/enc28j60.h b/dev/enc28j60/enc28j60.h new file mode 100644 index 000000000..059528816 --- /dev/null +++ b/dev/enc28j60/enc28j60.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2012-2013, Thingsquare, http://www.thingsquare.com/. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef ENC28J60_H +#define ENC28J60_H + +void enc28j60_init(uint8_t *mac_addr); + +int enc28j60_send(uint8_t *data, uint16_t datalen); + +int enc28j60_read(uint8_t *buffer, uint16_t bufsize); + +/* ENC28J60 architecture-specific SPI functions that are called by the + enc28j60 driver and must be implemented by the platform code */ + +void enc28j60_arch_spi_init(void); +uint8_t enc28j60_arch_spi_write(uint8_t data); +uint8_t enc28j60_arch_spi_read(void); +void enc28j60_arch_spi_select(void); +void enc28j60_arch_spi_deselect(void); + + +#endif /* ENC28J60_H */ diff --git a/doc/Doxyfile b/doc/Doxyfile index cd6b1235b..7379f5c06 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1,110 +1,129 @@ -# Doxyfile 1.8.1.2 +# Doxyfile 1.8.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # -# All text after a hash (#) is considered a comment and will be ignored. +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. # The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" "). +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or sequence of words) that should -# identify the project. Note that if you do not use Doxywizard you need -# to put quotes around the project name if it contains spaces. +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. PROJECT_NAME = "Contiki 3.x" -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer -# a quick idea about the purpose of the project. Keep the description short. +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = -# With the PROJECT_LOGO tag one can specify an logo or icon that is -# included in the documentation. The maximum height of the logo should not -# exceed 55 pixels and the maximum width should not exceed 200 pixels. -# Doxygen will copy the logo to the output directory. +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. PROJECT_LOGO = -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. OUTPUT_DIRECTORY = . -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. CREATE_SUBDIRS = NO +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. +# The default value is: YES. REPEAT_BRIEF = YES -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief +# doxygen will generate a detailed section even if there is only a brief # description. +# The default value is: NO. ALWAYS_DETAILED_SEC = NO @@ -112,169 +131,207 @@ ALWAYS_DETAILED_SEC = NO # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. +# The default value is: NO. INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. FULL_PATH_NAMES = YES -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = $(docroot) -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. STRIP_FROM_INC_PATH = $(docroot) -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful if your file system -# doesn't support long names like on DOS, Mac, or CD-ROM. +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. SHORT_NAMES = YES -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. JAVADOC_AUTOBRIEF = YES -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. QT_AUTOBRIEF = NO -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. SEPARATE_MEMBER_PAGES = NO -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 8 -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding -# "class=itcl::class" will allow you to use the command class in the -# itcl::class meaning. +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. TCL_SUBST = -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this -# tag. The format is ext=language, where ext is a file extension, and language -# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, -# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions -# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. EXTENSION_MAPPING = -# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all -# comments according to the Markdown format, which allows for more readable +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you -# can mix doxygen, HTML, and XML commands with Markdown formatting. -# Disable only in case of backward compatibilities issues. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. MARKDOWN_SUPPORT = YES +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also makes the inheritance and collaboration +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. +# The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. +# The default value is: NO. CPP_CLI_SUPPORT = NO -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. SIP_SUPPORT = NO -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. IDL_PROPERTY_SUPPORT = YES @@ -282,67 +339,61 @@ IDL_PROPERTY_SUPPORT = YES # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. +# The default value is: NO. DISTRIBUTE_GROUP_DOC = NO -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. SUBGROUPING = YES -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and -# unions are shown inside the group in which they are included (e.g. using -# @ingroup) instead of on a separate page (for HTML and Man pages) or -# section (for LaTeX and RTF). +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. INLINE_GROUPED_CLASSES = NO -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and -# unions with only public data fields will be shown inline in the documentation -# of the scope in which they are defined (i.e. file, namespace, or group -# documentation), provided this scope is documented. If set to NO (the default), -# structs, classes, and unions are shown on a separate page (for HTML and Man -# pages) or section (for LaTeX and RTF). +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. INLINE_SIMPLE_STRUCTS = NO -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. TYPEDEF_HIDES_STRUCT = NO -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penalty. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will roughly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. - -SYMBOL_CACHE_SIZE = 0 - -# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be -# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given -# their name and scope. Since this can be an expensive process and often the -# same symbol appear multiple times in the code, doxygen keeps a cache of -# pre-resolved symbols. If the cache is too small doxygen will become slower. -# If the cache is too large, memory is wasted. The cache size is given by this -# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 @@ -351,342 +402,392 @@ LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. EXTRACT_ALL = NO -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. EXTRACT_PRIVATE = NO -# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. EXTRACT_PACKAGE = NO -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. EXTRACT_STATIC = NO -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. EXTRACT_LOCAL_CLASSES = NO -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespaces are hidden. +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. EXTRACT_ANON_NSPACES = NO -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_MEMBERS = YES -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_CLASSES = YES -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. HIDE_IN_BODY_DOCS = NO -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. +# The default value is: system dependent. CASE_SENSE_NAMES = YES -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. HIDE_SCOPE_NAMES = NO -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. SHOW_INCLUDE_FILES = YES -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. FORCE_LOCAL_INCLUDES = NO -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. SORT_MEMBER_DOCS = YES -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. SORT_BRIEF_DOCS = NO -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. SORT_GROUP_NAMES = NO -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. SORT_BY_SCOPE_NAME = NO -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to -# do proper type resolution of all parameters of a function it will reject a -# match between the prototype and the implementation of a member function even -# if there is only one candidate or it is obvious which candidate to choose -# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen -# will still accept a match between prototype and implementation in such cases. +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. STRICT_PROTO_MATCHING = NO -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. GENERATE_TODOLIST = YES -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. GENERATE_TESTLIST = YES -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. GENERATE_BUGLIST = NO -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. GENERATE_DEPRECATEDLIST= NO -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. ENABLED_SECTIONS = -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or macro consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and macros in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. SHOW_USED_FILES = NO -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. SHOW_FILES = YES -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. LAYOUT_FILE = -# The CITE_BIB_FILES tag can be used to specify one or more bib files -# containing the references data. This must be a list of .bib files. The -# .bib extension is automatically appended if omitted. Using this command -# requires the bibtex tool to be installed. See also -# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style -# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this -# feature you need bibtex and perl available in the search path. +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- -# configuration options related to warning and progress messages +# Configuration options related to warning and progress messages #--------------------------------------------------------------------------- -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. WARNINGS = YES -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. WARN_IF_UNDOCUMENTED = NO -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. WARN_IF_DOC_ERROR = YES -# The WARN_NO_PARAMDOC option can be enabled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. WARN_NO_PARAMDOC = NO -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). WARN_LOGFILE = doxygen.log #--------------------------------------------------------------------------- -# configuration options related to the input files +# Configuration options related to the input files #--------------------------------------------------------------------------- -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. INPUT = $(docsrc) # This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh -# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py -# *.f90 *.f *.for *.vhd *.vhdl +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. FILE_PATTERNS = *.h \ *.c \ *.doc.html \ *.txt -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. +# # Note that relative paths are relative to the directory from which doxygen is # run. @@ -695,14 +796,16 @@ EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. +# The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* +# certain files from those directories. +# +# 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 = @@ -711,757 +814,1082 @@ EXCLUDE_PATTERNS = # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). EXAMPLE_PATH = . \ ../examples/rime \ ../examples/multi-threading # If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. EXAMPLE_RECURSIVE = NO -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). IMAGE_PATH = pics # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty or if -# non of the patterns match the file name, INPUT_FILTER is applied. +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) -# and it is also possible to disable source filtering for a specific pattern -# using *.ext= (so without naming a filter). This option only has effect when -# FILTER_SOURCE_FILES is enabled. +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + #--------------------------------------------------------------------------- -# configuration options related to source browsing +# Configuration options related to source browsing #--------------------------------------------------------------------------- -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. SOURCE_BROWSER = YES -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C, C++ and Fortran comments will always remain visible. +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. STRIP_CODE_COMMENTS = NO -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. REFERENCED_BY_RELATION = YES -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. REFERENCES_RELATION = YES -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. REFERENCES_LINK_SOURCE = YES -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index +# Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. ALPHABETICAL_INDEX = YES -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- -# configuration options related to the HTML output +# Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. Note that when using a custom header you are responsible -# for the proper inclusion of any scripts and style sheets that doxygen -# needs, which is dependent on the configuration options used. -# It is advised to generate a default header using "doxygen -w html -# header.html footer.html stylesheet.css YourConfigFile" and then modify -# that header. Note that the header is subject to change so you typically -# have to redo this when upgrading to a newer version of doxygen or when -# changing the value of configuration settings such as GENERATE_TREEVIEW! +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# style sheet in the HTML output directory as well, or it will be erased! +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra stylesheet files is of importance (e.g. the last +# stylesheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the -# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that -# the files will be copied as-is; there are no commands or markers available. +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the style sheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of -# entries shown in the various tree structured indices initially; the user -# can expand and collapse entries dynamically later on. Doxygen will expand -# the tree to such a level that at most the specified number of entries are -# visible (unless a fully collapsed tree already exceeds this amount). -# So setting the number of entries 1 will produce a full collapsed tree by -# default. 0 is a special value representing an infinite number of entries -# and will result in a full expanded tree by default. +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = YES -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be # written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = YES -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = YES -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = YES # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# -# Qt Help Project / Custom Filters. +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project -# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) -# at top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. Since the tabs have the same information as the -# navigation tree you can set this option to NO if you already set -# GENERATE_TREEVIEW to YES. +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. -# Since the tree basically has the same information as the tab index you -# could consider to set DISABLE_INDEX to NO when enabling this option. +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. -GENERATE_TREEVIEW = YES +GENERATE_TREEVIEW = NO -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values -# (range [0,1..20]) that doxygen will group on one line in the generated HTML -# documentation. Note that a value of 0 will completely suppress the enum -# values from appearing in the overview section. +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax -# (see http://www.mathjax.org) which uses client side Javascript for the -# rendering instead of using prerendered bitmaps. Use this if you do not -# have LaTeX installed or if you want to formulas look prettier in the HTML -# output. When enabled you may also need to install MathJax separately and -# configure the path to it using the MATHJAX_RELPATH option. +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO -# When MathJax is enabled you need to specify the location relative to the -# HTML output directory using the MATHJAX_RELPATH option. The destination -# directory should contain the MathJax.js script. For instance, if the mathjax -# directory is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to -# the MathJax Content Delivery Network so you can quickly see the result without -# installing MathJax. -# However, it is strongly recommended to install a local -# copy of MathJax from http://www.mathjax.org before deployment. +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest -# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension -# names that should be enabled during MathJax rendering. +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /