Merge branch 'contiki' into osd

This commit is contained in:
Harald Pichler 2015-02-18 10:04:47 +01:00
commit d31ecbf486
116 changed files with 5024 additions and 1427 deletions

View file

@ -115,6 +115,6 @@ env:
- BUILD_TYPE='compile-8051-ports' BUILD_CATEGORY='compile' BUILD_ARCH='8051' - 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-arm-apcs-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm-apcs'
- BUILD_TYPE='compile-6502-ports' BUILD_CATEGORY='compile' BUILD_ARCH='6502' - BUILD_TYPE='compile-6502-ports' BUILD_CATEGORY='compile' BUILD_ARCH='6502'
# - BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm' - BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm'
- BUILD_TYPE='slip-radio' MAKE_TARGETS='cooja' - BUILD_TYPE='slip-radio' MAKE_TARGETS='cooja'
- BUILD_TYPE='llsec' MAKE_TARGETS='cooja' - BUILD_TYPE='llsec' MAKE_TARGETS='cooja'

1
apps/mqtt/Makefile.mqtt Normal file
View file

@ -0,0 +1 @@
mqtt_src = mqtt.c

1484
apps/mqtt/mqtt.c Normal file

File diff suppressed because it is too large Load diff

509
apps/mqtt/mqtt.h Normal file
View file

@ -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 <stdlib.h>
#include <stdio.h>
#include <string.h>
/*---------------------------------------------------------------------------*/
/* 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_ */
/*---------------------------------------------------------------------------*/
/**
* @}
* @}
*/

View file

@ -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: * Example usage:
* 'download <node addr> <filename> | write <local_filename'. * 'download \<node addr\> \<filename\> | write \<local_filename\>'.
* *
* \author Luca Mottola <luca@sics.se>, Fredrik Osterlind <fros@sics.se> * \author Luca Mottola <luca@sics.se>, Fredrik Osterlind <fros@sics.se>
*/ */

View file

@ -40,7 +40,7 @@
* of ACM/IEEE IPSN 2009. * of ACM/IEEE IPSN 2009.
* *
* \author * \author
* Nicolas Tsiftes <nvt@sics.se> * Nicolas Tsiftes <nvt@sics.se>
*/ */
#include <limits.h> #include <limits.h>
@ -62,13 +62,13 @@
/* Micro logs enable modifications on storage types that do not support /* Micro logs enable modifications on storage types that do not support
in-place updates. This applies primarily to flash memories. */ in-place updates. This applies primarily to flash memories. */
#ifndef COFFEE_MICRO_LOGS #ifndef COFFEE_MICRO_LOGS
#define COFFEE_MICRO_LOGS 1 #define COFFEE_MICRO_LOGS 1
#endif #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. */ can be set to save some code space. */
#ifndef COFFEE_APPEND_ONLY #ifndef COFFEE_APPEND_ONLY
#define COFFEE_APPEND_ONLY 0 #define COFFEE_APPEND_ONLY 0
#endif #endif
#if COFFEE_MICRO_LOGS && COFFEE_APPEND_ONLY #if COFFEE_MICRO_LOGS && COFFEE_APPEND_ONLY
@ -78,7 +78,7 @@
/* 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. */ file access on certain storage types. */
#ifndef COFFEE_IO_SEMANTICS #ifndef COFFEE_IO_SEMANTICS
#define COFFEE_IO_SEMANTICS 0 #define COFFEE_IO_SEMANTICS 0
#endif #endif
/* /*
@ -87,72 +87,72 @@
* to longer garbage collection procedures. * to longer garbage collection procedures.
*/ */
#ifndef COFFEE_EXTENDED_WEAR_LEVELLING #ifndef COFFEE_EXTENDED_WEAR_LEVELLING
#define COFFEE_EXTENDED_WEAR_LEVELLING 1 #define COFFEE_EXTENDED_WEAR_LEVELLING 1
#endif #endif
#if COFFEE_START & (COFFEE_SECTOR_SIZE - 1) #if COFFEE_START & (COFFEE_SECTOR_SIZE - 1)
#error COFFEE_START must point to the first byte in a sector. #error COFFEE_START must point to the first byte in a sector.
#endif #endif
#define COFFEE_FD_FREE 0x0 #define COFFEE_FD_FREE 0x0
#define COFFEE_FD_READ 0x1 #define COFFEE_FD_READ 0x1
#define COFFEE_FD_WRITE 0x2 #define COFFEE_FD_WRITE 0x2
#define COFFEE_FD_APPEND 0x4 #define COFFEE_FD_APPEND 0x4
#define COFFEE_FILE_MODIFIED 0x1 #define COFFEE_FILE_MODIFIED 0x1
#define INVALID_PAGE ((coffee_page_t)-1) #define INVALID_PAGE ((coffee_page_t)-1)
#define UNKNOWN_OFFSET ((cfs_offset_t)-1) #define UNKNOWN_OFFSET ((cfs_offset_t)-1)
#define REMOVE_LOG 1 #define REMOVE_LOG 1
#define CLOSE_FDS 1 #define CLOSE_FDS 1
#define ALLOW_GC 1 #define ALLOW_GC 1
/* "Greedy" garbage collection erases as many sectors as possible. */ /* "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. */ /* "Reluctant" garbage collection stops after erasing one sector. */
#define GC_RELUCTANT 1 #define GC_RELUCTANT 1
/* File descriptor macros. */ /* File descriptor macros. */
#define FD_VALID(fd) \ #define FD_VALID(fd) \
((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \ ((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \
coffee_fd_set[(fd)].flags != COFFEE_FD_FREE) coffee_fd_set[(fd)].flags != COFFEE_FD_FREE)
#define FD_READABLE(fd) (coffee_fd_set[(fd)].flags & CFS_READ) #define FD_READABLE(fd) (coffee_fd_set[(fd)].flags & CFS_READ)
#define FD_WRITABLE(fd) (coffee_fd_set[(fd)].flags & CFS_WRITE) #define FD_WRITABLE(fd) (coffee_fd_set[(fd)].flags & CFS_WRITE)
#define FD_APPENDABLE(fd) (coffee_fd_set[(fd)].flags & CFS_APPEND) #define FD_APPENDABLE(fd) (coffee_fd_set[(fd)].flags & CFS_APPEND)
/* File object macros. */ /* File object macros. */
#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED) #define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED)
#define FILE_FREE(file) ((file)->max_pages == 0) #define FILE_FREE(file) ((file)->max_pages == 0)
#define FILE_UNREFERENCED(file) ((file)->references == 0) #define FILE_UNREFERENCED(file) ((file)->references == 0)
/* File header flags. */ /* File header flags. */
#define HDR_FLAG_VALID 0x1 /* Completely written header. */ #define HDR_FLAG_VALID 0x1 /* Completely written header. */
#define HDR_FLAG_ALLOCATED 0x2 /* Allocated file. */ #define HDR_FLAG_ALLOCATED 0x2 /* Allocated file. */
#define HDR_FLAG_OBSOLETE 0x4 /* File marked for GC. */ #define HDR_FLAG_OBSOLETE 0x4 /* File marked for GC. */
#define HDR_FLAG_MODIFIED 0x8 /* Modified file, log exists. */ #define HDR_FLAG_MODIFIED 0x8 /* Modified file, log exists. */
#define HDR_FLAG_LOG 0x10 /* Log file. */ #define HDR_FLAG_LOG 0x10 /* Log file. */
#define HDR_FLAG_ISOLATED 0x20 /* Isolated page. */ #define HDR_FLAG_ISOLATED 0x20 /* Isolated page. */
/* File header macros. */ /* File header macros. */
#define CHECK_FLAG(hdr, flag) ((hdr).flags & (flag)) #define CHECK_FLAG(hdr, flag) ((hdr).flags & (flag))
#define HDR_VALID(hdr) CHECK_FLAG(hdr, HDR_FLAG_VALID) #define HDR_VALID(hdr) CHECK_FLAG(hdr, HDR_FLAG_VALID)
#define HDR_ALLOCATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ALLOCATED) #define HDR_ALLOCATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ALLOCATED)
#define HDR_FREE(hdr) !HDR_ALLOCATED(hdr) #define HDR_FREE(hdr) !HDR_ALLOCATED(hdr)
#define HDR_LOG(hdr) CHECK_FLAG(hdr, HDR_FLAG_LOG) #define HDR_LOG(hdr) CHECK_FLAG(hdr, HDR_FLAG_LOG)
#define HDR_MODIFIED(hdr) CHECK_FLAG(hdr, HDR_FLAG_MODIFIED) #define HDR_MODIFIED(hdr) CHECK_FLAG(hdr, HDR_FLAG_MODIFIED)
#define HDR_ISOLATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ISOLATED) #define HDR_ISOLATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ISOLATED)
#define HDR_OBSOLETE(hdr) CHECK_FLAG(hdr, HDR_FLAG_OBSOLETE) #define HDR_OBSOLETE(hdr) CHECK_FLAG(hdr, HDR_FLAG_OBSOLETE)
#define HDR_ACTIVE(hdr) (HDR_ALLOCATED(hdr) && \ #define HDR_ACTIVE(hdr) (HDR_ALLOCATED(hdr) && \
!HDR_OBSOLETE(hdr) && \ !HDR_OBSOLETE(hdr) && \
!HDR_ISOLATED(hdr)) !HDR_ISOLATED(hdr))
/* Shortcuts derived from the hardware-dependent configuration of Coffee. */ /* Shortcuts derived from the hardware-dependent configuration of Coffee. */
#define COFFEE_SECTOR_COUNT (unsigned)(COFFEE_SIZE / COFFEE_SECTOR_SIZE) #define COFFEE_SECTOR_COUNT (unsigned)(COFFEE_SIZE / COFFEE_SECTOR_SIZE)
#define COFFEE_PAGE_COUNT \ #define COFFEE_PAGE_COUNT \
((coffee_page_t)(COFFEE_SIZE / COFFEE_PAGE_SIZE)) ((coffee_page_t)(COFFEE_SIZE / COFFEE_PAGE_SIZE))
#define COFFEE_PAGES_PER_SECTOR \ #define COFFEE_PAGES_PER_SECTOR \
((coffee_page_t)(COFFEE_SECTOR_SIZE / COFFEE_PAGE_SIZE)) ((coffee_page_t)(COFFEE_SECTOR_SIZE / COFFEE_PAGE_SIZE))
/* This structure is used for garbage collection statistics. */ /* This structure is used for garbage collection statistics. */
struct sector_status { struct sector_status {
@ -212,10 +212,10 @@ static struct protected_mem_t {
coffee_page_t next_free; coffee_page_t next_free;
char gc_wait; char gc_wait;
} protected_mem; } protected_mem;
static struct file * const coffee_files = protected_mem.coffee_files; static struct file *const coffee_files = protected_mem.coffee_files;
static struct file_desc * const coffee_fd_set = protected_mem.coffee_fd_set; 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 coffee_page_t *const next_free = &protected_mem.next_free;
static char * const gc_wait = &protected_mem.gc_wait; static char *const gc_wait = &protected_mem.gc_wait;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
@ -339,7 +339,7 @@ get_sector_status(uint16_t sector, struct sector_status *stats)
* immediately without requiring page isolation. * immediately without requiring page isolation.
*/ */
return (last_pages_are_active || (skip_pages >= COFFEE_PAGES_PER_SECTOR)) ? return (last_pages_are_active || (skip_pages >= COFFEE_PAGES_PER_SECTOR)) ?
0 : skip_pages; 0 : skip_pages;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void 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", PRINTF("Coffee: Isolated %u pages starting in sector %d\n",
(unsigned)skip_pages, (int)start / COFFEE_PAGES_PER_SECTOR); (unsigned)skip_pages, (int)start / COFFEE_PAGES_PER_SECTOR);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static void static void
@ -370,7 +369,7 @@ collect_garbage(int mode)
coffee_page_t first_page, isolation_count; coffee_page_t first_page, isolation_count;
PRINTF("Coffee: Running the file system garbage collector in %s mode\n", 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 * The garbage collector erases as many sectors as possible. A sector is
* erasable if there are only free or obsolete pages in it. * 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++) { for(sector = 0; sector < COFFEE_SECTOR_COUNT; sector++) {
isolation_count = get_sector_status(sector, &stats); isolation_count = get_sector_status(sector, &stats);
PRINTF("Coffee: Sector %u has %u active, %u obsolete, and %u free pages.\n", PRINTF("Coffee: Sector %u has %u active, %u obsolete, and %u free pages.\n",
sector, (unsigned)stats.active, sector, (unsigned)stats.active,
(unsigned)stats.obsolete, (unsigned)stats.free); (unsigned)stats.obsolete, (unsigned)stats.free);
if(stats.active > 0) { if(stats.active > 0) {
continue; continue;
@ -521,10 +520,10 @@ file_end(coffee_page_t start)
COFFEE_READ(buf, sizeof(buf), (start + page) * COFFEE_PAGE_SIZE); COFFEE_READ(buf, sizeof(buf), (start + page) * COFFEE_PAGE_SIZE);
for(i = COFFEE_PAGE_SIZE - 1; i >= 0; i--) { for(i = COFFEE_PAGE_SIZE - 1; i >= 0; i--) {
if(buf[i] != 0) { if(buf[i] != 0) {
if(page == 0 && i < sizeof(hdr)) { if(page == 0 && i < sizeof(hdr)) {
return 0; return 0;
} }
return 1 + i + (page * COFFEE_PAGE_SIZE) - sizeof(hdr); return 1 + i + (page * COFFEE_PAGE_SIZE) - sizeof(hdr);
} }
} }
} }
@ -544,7 +543,7 @@ find_contiguous_pages(coffee_page_t amount)
read_header(&hdr, page); read_header(&hdr, page);
if(HDR_FREE(hdr)) { if(HDR_FREE(hdr)) {
if(start == INVALID_PAGE) { if(start == INVALID_PAGE) {
start = page; start = page;
if(start + amount >= COFFEE_PAGE_COUNT) { if(start + amount >= COFFEE_PAGE_COUNT) {
/* We can stop immediately if the remaining pages are not enough. */ /* We can stop immediately if the remaining pages are not enough. */
break; break;
@ -557,9 +556,9 @@ find_contiguous_pages(coffee_page_t amount)
if(start + amount <= page) { if(start + amount <= page) {
if(start == *next_free) { if(start == *next_free) {
*next_free = start + amount; *next_free = start + amount;
} }
return start; return start;
} }
} else { } else {
start = INVALID_PAGE; start = INVALID_PAGE;
@ -596,7 +595,7 @@ remove_by_page(coffee_page_t page, int remove_log, int close_fds,
if(close_fds) { if(close_fds) {
for(i = 0; i < COFFEE_FD_SET_SIZE; i++) { for(i = 0; i < COFFEE_FD_SET_SIZE; i++) {
if(coffee_fd_set[i].file != NULL && coffee_fd_set[i].file->page == page) { 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) page_count(cfs_offset_t size)
{ {
return (size + sizeof(struct file_header) + COFFEE_PAGE_SIZE - 1) / return (size + sizeof(struct file_header) + COFFEE_PAGE_SIZE - 1) /
COFFEE_PAGE_SIZE; COFFEE_PAGE_SIZE;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static struct file * static struct file *
reserve(const char *name, coffee_page_t pages, reserve(const char *name, coffee_page_t pages,
int allow_duplicates, unsigned flags) int allow_duplicates, unsigned flags)
{ {
struct file_header hdr; struct file_header hdr;
coffee_page_t page; coffee_page_t page;
@ -657,7 +656,7 @@ reserve(const char *name, coffee_page_t pages,
write_header(&hdr, page); write_header(&hdr, page);
PRINTF("Coffee: Reserved %u pages starting from %u for file %s\n", PRINTF("Coffee: Reserved %u pages starting from %u for file %s\n",
pages, page, name); pages, page, name);
file = load_file(page, &hdr); file = load_file(page, &hdr);
if(file != NULL) { if(file != NULL) {
@ -670,19 +669,19 @@ reserve(const char *name, coffee_page_t pages,
#if COFFEE_MICRO_LOGS #if COFFEE_MICRO_LOGS
static void static void
adjust_log_config(struct file_header *hdr, 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 ? *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 ? *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 */ #endif /* COFFEE_MICRO_LOGS */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if COFFEE_MICRO_LOGS #if COFFEE_MICRO_LOGS
static uint16_t static uint16_t
modify_log_buffer(uint16_t log_record_size, 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; uint16_t region;
@ -700,7 +699,7 @@ modify_log_buffer(uint16_t log_record_size,
#if COFFEE_MICRO_LOGS #if COFFEE_MICRO_LOGS
static int static int
get_record_index(coffee_page_t log_page, uint16_t search_records, get_record_index(coffee_page_t log_page, uint16_t search_records,
uint16_t region) uint16_t region)
{ {
cfs_offset_t base; cfs_offset_t base;
uint16_t processed; 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); base = absolute_offset(log_page, sizeof(uint16_t) * search_records);
batch_size = search_records > COFFEE_LOG_TABLE_LIMIT ? batch_size = search_records > COFFEE_LOG_TABLE_LIMIT ?
COFFEE_LOG_TABLE_LIMIT : search_records; COFFEE_LOG_TABLE_LIMIT : search_records;
processed = 0; processed = 0;
match_index = -1; match_index = -1;
{ {
uint16_t indices[batch_size]; uint16_t indices[batch_size];
while(processed < search_records && match_index < 0) { while(processed < search_records && match_index < 0) {
if(batch_size + processed > search_records) { if(batch_size + processed > search_records) {
batch_size = search_records - processed; 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;
} }
}
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; return match_index;
@ -869,7 +868,7 @@ merge_log(coffee_page_t file_page, int extend)
#if COFFEE_MICRO_LOGS #if COFFEE_MICRO_LOGS
static int static int
find_next_record(struct file *file, coffee_page_t log_page, find_next_record(struct file *file, coffee_page_t log_page,
int log_records) int log_records)
{ {
int log_record, preferred_batch_size; 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 ? 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. */ /* The next log record is unknown at this point; search for it. */
uint16_t indices[preferred_batch_size]; 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; log_record = log_records;
for(processed = 0; processed < log_records; processed += batch_size) { for(processed = 0; processed < log_records; processed += batch_size) {
batch_size = log_records - processed >= preferred_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]), 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++) { for(log_record = 0; log_record < batch_size; log_record++) {
if(indices[log_record] == 0) { if(indices[log_record] == 0) {
log_record += processed; log_record += processed;
break; break;
} }
} }
} }
} }
@ -940,7 +939,7 @@ write_log_page(struct file *file, struct log_param *lp)
return -1; return -1;
} }
PRINTF("Coffee: Created a log structure for file %s at page %u\n", 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; hdr.log_page = log_page;
log_record = 0; log_record = 0;
} }
@ -953,9 +952,9 @@ write_log_page(struct file *file, struct log_param *lp)
lp_out.size = log_record_size; lp_out.size = log_record_size;
if((lp->offset > 0 || lp->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), COFFEE_READ(copy_buf, sizeof(copy_buf),
absolute_offset(file->page, offset)); absolute_offset(file->page, offset));
} }
memcpy(&copy_buf[lp->offset], lp->buf, lp->size); memcpy(&copy_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); offset = absolute_offset(log_page, 0);
++region; ++region;
COFFEE_WRITE(&region, sizeof(region), COFFEE_WRITE(&region, sizeof(region),
offset + log_record * sizeof(region)); offset + log_record * sizeof(region));
offset += log_records * sizeof(region); offset += log_records * sizeof(region);
COFFEE_WRITE(copy_buf, sizeof(copy_buf), 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; 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)) { if(!(fdp->io_flags & CFS_COFFEE_IO_FIRM_SIZE)) {
#endif #endif
while(size + fdp->offset + sizeof(struct file_header) > 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) { if(merge_log(file->page, 1) < 0) {
return -1; 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); PRINTF("Extended the file at page %u\n", (unsigned)file->page);
} }
#if COFFEE_IO_SEMANTICS #if COFFEE_IO_SEMANTICS
} }
#endif #endif
#if COFFEE_MICRO_LOGS #if COFFEE_MICRO_LOGS
@ -1196,19 +1195,19 @@ cfs_write(int fd, const void *buf, unsigned size)
lp.size = bytes_left; lp.size = bytes_left;
i = write_log_page(file, &lp); i = write_log_page(file, &lp);
if(i < 0) { if(i < 0) {
/* Return -1 if we wrote nothing because the log write failed. */ /* Return -1 if we wrote nothing because the log write failed. */
if(size == bytes_left) { if(size == bytes_left) {
return -1; return -1;
} }
break; break;
} else if(i == 0) { } else if(i == 0) {
/* The file was merged with the log. */ /* The file was merged with the log. */
file = fdp->file; file = fdp->file;
} else { } else {
/* A log record was written. */ /* A log record was written. */
bytes_left -= i; bytes_left -= i;
fdp->offset += i; fdp->offset += i;
buf = (char *)buf + i; buf = (char *)buf + i;
/* Update the file end for a potential log merge that might /* Update the file end for a potential log merge that might
occur while writing log records. */ occur while writing log records. */
@ -1231,15 +1230,15 @@ cfs_write(int fd, const void *buf, unsigned size)
} else { } else {
#endif /* COFFEE_MICRO_LOGS */ #endif /* COFFEE_MICRO_LOGS */
#if COFFEE_APPEND_ONLY #if COFFEE_APPEND_ONLY
if(fdp->offset < file->end) { if(fdp->offset < file->end) {
return -1; return -1;
} }
#endif /* COFFEE_APPEND_ONLY */ #endif /* COFFEE_APPEND_ONLY */
COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset)); COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset));
fdp->offset += size; fdp->offset += size;
#if COFFEE_MICRO_LOGS #if COFFEE_MICRO_LOGS
} }
#endif /* COFFEE_MICRO_LOGS */ #endif /* COFFEE_MICRO_LOGS */
if(fdp->offset > file->end) { if(fdp->offset > file->end) {
@ -1300,7 +1299,7 @@ cfs_coffee_reserve(const char *name, cfs_offset_t size)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
int int
cfs_coffee_configure_log(const char *filename, unsigned log_size, cfs_coffee_configure_log(const char *filename, unsigned log_size,
unsigned log_record_size) unsigned log_record_size)
{ {
struct file *file; struct file *file;
struct file_header hdr; struct file_header hdr;

View file

@ -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 * drawn, in screen coordinates (line 1 is the first line below the
* menus) * menus)
* *
* \param draw_borders The border style
*/ */
void ctk_draw_window(struct ctk_window *window, void ctk_draw_window(struct ctk_window *window,
unsigned char focus, unsigned char focus,
@ -318,7 +319,7 @@ extern unsigned char ctk_draw_windowborder_width,
/** /**
* The character used for the Return/Enter key. * The character used for the Return/Enter key.
* *
* \define #define CH_ENTER '\n' * \#define CH_ENTER '\n'
*/ */
/** /**

View file

@ -77,7 +77,7 @@ unsigned short crc16_add(unsigned char b, unsigned short crc);
* \brief Calculate the CRC16 over a data area * \brief Calculate the CRC16 over a data area
* \param data Pointer to the data * \param data Pointer to the data
* \param datalen The length of 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. * \return The CRC16 checksum.
* *
* This function calculates the CRC16 checksum of a data area. * This function calculates the CRC16 checksum of a data area.

View file

@ -142,7 +142,7 @@ int simple_udp_sendto(struct simple_udp_connection *c,
* \param data A pointer to the data to be sent * \param data A pointer to the data to be sent
* \param datalen The length of the data * \param datalen The length of the data
* \param to The IP address of the receiver * \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 * This function sends a UDP packet to a specified IP
* address and UDP port. The packet will be sent with the * address and UDP port. The packet will be sent with the

View file

@ -350,7 +350,7 @@ void uip_setipid(uint16_t id);
* Periodic processing for a connection identified by its number. * Periodic processing for a connection identified by its number.
* *
* This function does the necessary periodic processing (timers, * 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 * periodic uIP timer goes off. It should be called for every
* connection, regardless of whether they are open of closed. * 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) 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) #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 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 * packets. The device driver should place incoming data into this
* buffer. When sending data, the device driver should read the link * buffer. When sending data, the device driver should read the link
* level headers and the TCP/IP headers from this buffer. The size of * level headers and the TCP/IP headers from this buffer. The size of
@ -519,6 +521,8 @@ typedef union {
} uip_buf_t; } uip_buf_t;
CCIF extern uip_buf_t uip_aligned_buf; 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) #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. * Check if an address is a broadcast address for a network.
* *
* Checks if an address is the broadcast address for a network. The * 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. * 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. * computed.
* *
* \param len The length of the buffer over which the checksum is to * \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. * \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. * Calculate the IP header checksum of the packet header in uip_buf.

View file

@ -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, * \note This function is not called in the current version of uIP,
* but future versions might make use of it. * 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. * computed.
* *
* \param len The length of the buffer over which the checksum is to * \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. * \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. * Calculate the IP header checksum of the packet header in uip_buf.

View file

@ -699,7 +699,7 @@ uip_process(uint8_t flag)
} }
goto drop; 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) { } else if(flag == UIP_TIMER) {
#if UIP_REASSEMBLY #if UIP_REASSEMBLY
if(uip_reasstmr != 0) { if(uip_reasstmr != 0) {
@ -851,7 +851,7 @@ uip_process(uint8_t flag)
that the packet has been corrupted in transit. If the size of 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, 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 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) { if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) {
uip_len = (BUF->len[0] << 8) + BUF->len[1]; uip_len = (BUF->len[0] << 8) + BUF->len[1];
@ -891,7 +891,7 @@ uip_process(uint8_t flag)
if(uip_ipaddr_cmp(&uip_hostaddr, &uip_all_zeroes_addr)) { if(uip_ipaddr_cmp(&uip_hostaddr, &uip_all_zeroes_addr)) {
/* If we are configured to use ping IP address configuration and /* 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. */ packets. */
#if UIP_PINGADDRCONF && !NETSTACK_CONF_WITH_IPV6 #if UIP_PINGADDRCONF && !NETSTACK_CONF_WITH_IPV6
if(BUF->proto == UIP_PROTO_ICMP) { if(BUF->proto == UIP_PROTO_ICMP) {
@ -1252,7 +1252,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 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, destined for a connection in LISTEN. If the SYN flag isn't set,
it is an old packet and we send a RST. */ it is an old packet and we send a RST. */
@ -1441,7 +1441,7 @@ uip_process(uint8_t flag)
uip_flags = 0; uip_flags = 0;
/* We do a very naive form of TCP reset processing; we just accept /* 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 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. */ before we accept the reset. */
if(BUF->flags & TCP_RST) { if(BUF->flags & TCP_RST) {
uip_connr->tcpstateflags = UIP_CLOSED; uip_connr->tcpstateflags = UIP_CLOSED;

View file

@ -29,20 +29,15 @@
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
*/ */
/**
* \addtogroup roll-tm
* @{
*/
/** /**
* \file * \file
* This file implements IPv6 MCAST forwarding according to the * Implementation of the ROLL TM multicast engine
* 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
*
* \author * \author
* George Oikonomou - <oikonomou@users.sourceforge.net> * George Oikonomou - <oikonomou@users.sourceforge.net>
*/ */
#include "contiki.h" #include "contiki.h"
@ -1440,6 +1435,9 @@ init()
return; return;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/**
* \brief The ROLL TM engine driver
*/
const struct uip_mcast6_driver roll_tm_driver = { const struct uip_mcast6_driver roll_tm_driver = {
"ROLL TM", "ROLL TM",
init, init,
@ -1447,3 +1445,4 @@ const struct uip_mcast6_driver roll_tm_driver = {
in, in,
}; };
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** @} */

View file

@ -29,25 +29,34 @@
* This file is part of the Contiki operating system. * 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 * \file
* Header file for IPv6 multicast according to the algorithm in the * Header file for the implementation of the ROLL-TM multicast engine
* "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.
*
* \author * \author
* George Oikonomou - <oikonomou@users.sourceforge.net> * George Oikonomou - <oikonomou@users.sourceforge.net>
*/ */
#ifndef ROLL_TM_H_ #ifndef ROLL_TM_H_
@ -60,9 +69,9 @@
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Protocol Constants */ /* Protocol Constants */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define ROLL_TM_VER 1 /* Supported Draft Version */ #define ROLL_TM_VER 1 /**< Supported Draft Version */
#define ROLL_TM_ICMP_CODE 0 /* ICMPv6 code field */ #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_IP_HOP_LIMIT 0xFF /**< Hop limit for ICMP messages */
#define ROLL_TM_INFINITE_REDUNDANCY 0xFF #define ROLL_TM_INFINITE_REDUNDANCY 0xFF
#define ROLL_TM_DGRAM_OUT 0 #define ROLL_TM_DGRAM_OUT 0
#define ROLL_TM_DGRAM_IN 1 #define ROLL_TM_DGRAM_IN 1
@ -153,7 +162,7 @@
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Configuration */ /* Configuration */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /**
* Number of Sliding Windows * Number of Sliding Windows
* In essence: How many unique sources of simultaneous multicast traffic do we * In essence: How many unique sources of simultaneous multicast traffic do we
* want to support for our lowpan * want to support for our lowpan
@ -166,7 +175,7 @@
#define ROLL_TM_WINS 2 #define ROLL_TM_WINS 2
#endif #endif
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /**
* Maximum Number of Buffered Multicast Messages * Maximum Number of Buffered Multicast Messages
* This buffer is shared across all Seed IDs, therefore a new very active Seed * 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 * may eventually occupy all slots. It would make little sense (if any) to
@ -178,7 +187,7 @@
#define ROLL_TM_BUFF_NUM 6 #define ROLL_TM_BUFF_NUM 6
#endif #endif
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /**
* Use Short Seed IDs [short: 2, long: 16 (default)] * 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 * 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 * 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 #define ROLL_TM_SHORT_SEEDS 0
#endif #endif
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /**
* Destination address for our ICMPv6 advertisements. The draft gives us a * Destination address for our ICMPv6 advertisements. The draft gives us a
* choice between LL all-nodes or LL all-routers * choice between LL all-nodes or LL all-routers
* *
@ -202,7 +211,7 @@
#define ROLL_TM_DEST_ALL_NODES 0 #define ROLL_TM_DEST_ALL_NODES 0
#endif #endif
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /**
* M param for our outgoing messages * M param for our outgoing messages
* By default, we set the M bit (conservative). Define this as 0 to clear the * By default, we set the M bit (conservative). Define this as 0 to clear the
* M bit in our outgoing messages (aggressive) * M bit in our outgoing messages (aggressive)
@ -215,10 +224,21 @@
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Stats datatype */ /* Stats datatype */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/**
* \brief Multicast stats extension for the ROLL TM engine
*/
struct roll_tm_stats { struct roll_tm_stats {
/** Number of received ICMP datagrams */
UIP_MCAST6_STATS_DATATYPE icmp_in; UIP_MCAST6_STATS_DATATYPE icmp_in;
/** Number of ICMP datagrams sent */
UIP_MCAST6_STATS_DATATYPE icmp_out; UIP_MCAST6_STATS_DATATYPE icmp_out;
/** Number of malformed ICMP datagrams seen by us */
UIP_MCAST6_STATS_DATATYPE icmp_bad; UIP_MCAST6_STATS_DATATYPE icmp_bad;
}; };
/*---------------------------------------------------------------------------*/
#endif /* ROLL_TM_H_ */ #endif /* ROLL_TM_H_ */
/*---------------------------------------------------------------------------*/
/** @} */
/** @} */

View file

@ -29,14 +29,16 @@
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
*/ */
/**
* \addtogroup smrf-multicast
* @{
*/
/** /**
* \file * \file
* This file implements 'Stateless Multicast RPL Forwarding' (SMRF) * This file implements 'Stateless Multicast RPL Forwarding' (SMRF)
*
* It will only work in RPL networks in MOP 3 "Storing with Multicast"
* *
* \author * \author
* George Oikonomou - <oikonomou@users.sourceforge.net> * George Oikonomou - <oikonomou@users.sourceforge.net>
*/ */
#include "contiki.h" #include "contiki.h"
@ -199,6 +201,9 @@ out()
return; return;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/**
* \brief The SMRF engine driver
*/
const struct uip_mcast6_driver smrf_driver = { const struct uip_mcast6_driver smrf_driver = {
"SMRF", "SMRF",
init, init,
@ -206,3 +211,4 @@ const struct uip_mcast6_driver smrf_driver = {
in, in,
}; };
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** @} */

View file

@ -29,12 +29,22 @@
* This file is part of the Contiki operating system. * 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 * \file
* Header file for 'Stateless Multicast RPL Forwarding' (SMRF) * Header file for the SMRF forwarding engine
* *
* \author * \author
* George Oikonomou - <oikonomou@users.sourceforge.net> * George Oikonomou - <oikonomou@users.sourceforge.net>
*/ */
#ifndef SMRF_H_ #ifndef SMRF_H_
@ -71,5 +81,8 @@ struct smrf_stats {
uint16_t mcast_bad; uint16_t mcast_bad;
uint16_t mcast_dropped; uint16_t mcast_dropped;
}; };
/*---------------------------------------------------------------------------*/
#endif /* SMRF_H_ */ #endif /* SMRF_H_ */
/*---------------------------------------------------------------------------*/
/** @} */
/** @} */

View file

@ -29,22 +29,27 @@
* This file is part of the Contiki operating system. * This file is part of the Contiki operating system.
*/ */
/**
* \addtogroup uip6-multicast
* @{
*/
/** /**
* \file * \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 * When writing a new engine, add it here with a unique number and
* then modify uip-mcast6.h accordingly * then modify uip-mcast6.h accordingly
* *
* \author * \author
* George Oikonomou - <oikonomou@users.sourceforge.net> * George Oikonomou - <oikonomou@users.sourceforge.net>
*/ */
#ifndef UIP_MCAST6_ENGINES_H_ #ifndef UIP_MCAST6_ENGINES_H_
#define UIP_MCAST6_ENGINES_H_ #define UIP_MCAST6_ENGINES_H_
#define UIP_MCAST6_ENGINE_NONE 0 /* Selecting this disables mcast */ #define UIP_MCAST6_ENGINE_NONE 0 /**< Selecting this disables mcast */
#define UIP_MCAST6_ENGINE_SMRF 1 #define UIP_MCAST6_ENGINE_SMRF 1 /**< The SMRF engine */
#define UIP_MCAST6_ENGINE_ROLL_TM 2 #define UIP_MCAST6_ENGINE_ROLL_TM 2 /**< The ROLL TM engine */
#endif /* UIP_MCAST6_ENGINES_H_ */ #endif /* UIP_MCAST6_ENGINES_H_ */
/** @} */

View file

@ -28,12 +28,16 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE. * OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/**
* \addtogroup uip6-multicast
* @{
*/
/** /**
* \file * \file
* Multicast routing table manipulation * Multicast routing table manipulation
* *
* \author * \author
* George Oikonomou - <oikonomou@users.sourceforge.net> * George Oikonomou - <oikonomou@users.sourceforge.net>
*/ */
#include "contiki.h" #include "contiki.h"
@ -128,3 +132,4 @@ uip_mcast6_route_init()
list_init(mcast_route_list); list_init(mcast_route_list);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** @} */

View file

@ -28,12 +28,16 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE. * OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/**
* \addtogroup uip6-multicast
* @{
*/
/** /**
* \file * \file
* Multicast routing table manipulation * Header file for multicast routing table manipulation
* *
* \author * \author
* George Oikonomou - <oikonomou@users.sourceforge.net> * George Oikonomou - <oikonomou@users.sourceforge.net>
*/ */
#ifndef UIP_MCAST6_ROUTE_H_ #ifndef UIP_MCAST6_ROUTE_H_
#define UIP_MCAST6_ROUTE_H_ #define UIP_MCAST6_ROUTE_H_
@ -45,18 +49,48 @@
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \brief An entry in the multicast routing table */ /** \brief An entry in the multicast routing table */
typedef struct uip_mcast6_route { typedef struct uip_mcast6_route {
struct uip_mcast6_route *next; struct uip_mcast6_route *next; /**< Routes are arranged in a linked list */
uip_ipaddr_t group; uip_ipaddr_t group; /**< The multicast group */
uint32_t lifetime; /* seconds */ uint32_t lifetime; /**< Entry lifetime seconds */
void *dag; /* Pointer to an rpl_dag_t struct */ void *dag; /**< Pointer to an rpl_dag_t struct */
} uip_mcast6_route_t; } uip_mcast6_route_t;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name Multicast Routing Table Manipulation */ /** \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); 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); 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); 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); 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_ */ #endif /* UIP_MCAST6_ROUTE_H_ */
/** @} */

View file

@ -27,12 +27,16 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE. * OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/**
* \addtogroup uip6-multicast
* @{
*/
/** /**
* \file * \file
* IPv6 multicast forwarding stats maintenance * IPv6 multicast forwarding stats maintenance
* *
* \author * \author
* George Oikonomou - <oikonomou@users.sourceforge.net> * George Oikonomou - <oikonomou@users.sourceforge.net>
*/ */
#include "net/ipv6/multicast/uip-mcast6-stats.h" #include "net/ipv6/multicast/uip-mcast6-stats.h"
@ -47,3 +51,4 @@ uip_mcast6_stats_init(void *stats)
uip_mcast6_stats.engine_stats = stats; uip_mcast6_stats.engine_stats = stats;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** @} */

View file

@ -27,12 +27,16 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE. * OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/**
* \addtogroup uip6-multicast
* @{
*/
/** /**
* \file * \file
* Header file for IPv6 multicast forwarding stats maintenance * Header file for IPv6 multicast forwarding stats maintenance
* *
* \author * \author
* George Oikonomou - <oikonomou@users.sourceforge.net> * George Oikonomou - <oikonomou@users.sourceforge.net>
*/ */
#ifndef UIP_MCAST6_STATS_H_ #ifndef UIP_MCAST6_STATS_H_
#define UIP_MCAST6_STATS_H_ #define UIP_MCAST6_STATS_H_
@ -56,15 +60,35 @@
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Stats datatype */ /* 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 { typedef struct uip_mcast6_stats {
/** Count of unique datagrams received */
UIP_MCAST6_STATS_DATATYPE mcast_in_unique; 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 */ /** Count of all datagrams received */
UIP_MCAST6_STATS_DATATYPE mcast_fwd; /* Forwarded by us but we are not the seed */ UIP_MCAST6_STATS_DATATYPE mcast_in_all;
UIP_MCAST6_STATS_DATATYPE mcast_out; /* We are the seed */
/** 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; UIP_MCAST6_STATS_DATATYPE mcast_bad;
/** Count of multicast datagrams correclty formed but dropped by us */
UIP_MCAST6_STATS_DATATYPE mcast_dropped; 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; } uip_mcast6_stats_t;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Access macros */ /* Access macros */
@ -89,3 +113,5 @@ extern uip_mcast6_stats_t uip_mcast6_stats;
void uip_mcast6_stats_init(void *stats); void uip_mcast6_stats_init(void *stats);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#endif /* UIP_MCAST6_STATS_H_ */ #endif /* UIP_MCAST6_STATS_H_ */
/*---------------------------------------------------------------------------*/
/** @} */

View file

@ -30,9 +30,11 @@
*/ */
/** /**
* \file * \addtogroup uip6
* This header file contains configuration directives for uIPv6 * @{
* multicast support. */
/**
* \defgroup uip6-multicast IPv6 Multicast Forwarding
* *
* We currently support 2 engines: * We currently support 2 engines:
* - 'Stateless Multicast RPL Forwarding' (SMRF) * - 'Stateless Multicast RPL Forwarding' (SMRF)
@ -42,6 +44,14 @@
* in the internet draft: * in the internet draft:
* http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast * http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast
* *
* @{
*/
/**
* \file
* This header file contains configuration directives for uIPv6
* multicast support.
*
* \author * \author
* George Oikonomou - <oikonomou@users.sourceforge.net> * George Oikonomou - <oikonomou@users.sourceforge.net>
*/ */
@ -83,7 +93,11 @@
* Multicast API. Similar to NETSTACK, each engine must define a driver and * Multicast API. Similar to NETSTACK, each engine must define a driver and
* populate the fields with suitable function pointers * populate the fields with suitable function pointers
*/ */
/**
* \brief The data structure used to represent a multicast engine
*/
struct uip_mcast6_driver { struct uip_mcast6_driver {
/** The driver's name */
char *name; char *name;
/** Initialize the multicast engine */ /** Initialize the multicast engine */
@ -110,6 +124,7 @@ struct uip_mcast6_driver {
* *
* \return 0: Drop, 1: Deliver * \return 0: Drop, 1: Deliver
* *
*
* When a datagram with a multicast destination address is received, * When a datagram with a multicast destination address is received,
* the forwarding logic in core is bypassed. Instead, we let the * the forwarding logic in core is bypassed. Instead, we let the
* multicast engine handle forwarding internally if and as necessary. * 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." #error "Check the value of UIP_CONF_IPV6_RPL in conf files."
#endif #endif
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#endif /* UIP_MCAST6_H_ */ #endif /* UIP_MCAST6_H_ */
/*---------------------------------------------------------------------------*/
/** @} */
/** @} */

View file

@ -234,7 +234,7 @@ struct sicslowpan_addr_context {
* \brief check whether we can compress the IID in * \brief check whether we can compress the IID in
* address 'a' to 16 bits. * address 'a' to 16 bits.
* This is used for unicast addresses only, and is true * This is used for unicast addresses only, and is true
* if the address is on the format <PREFIX>::0000:00ff:fe00:XXXX * if the address is on the format \<PREFIX\>::0000:00ff:fe00:XXXX
* NOTE: we currently assume 64-bits prefixes * NOTE: we currently assume 64-bits prefixes
*/ */
#define sicslowpan_is_iid_16_bit_compressable(a) \ #define sicslowpan_is_iid_16_bit_compressable(a) \

View file

@ -29,20 +29,20 @@
* *
*/ */
/**
* \addtogroup uip6
* @{
*/
/** /**
* \file * \file
* IPv6 Neighbor cache (link-layer/IPv6 address mapping) * IPv6 Neighbor cache (link-layer/IPv6 address mapping)
* \author Mathilde Durvy <mdurvy@cisco.com> * \author Mathilde Durvy <mdurvy@cisco.com>
* \author Julien Abeille <jabeille@cisco.com> * \author Julien Abeille <jabeille@cisco.com>
* \author Simon Duquennoy <simonduq@sics.se> * \author Simon Duquennoy <simonduq@sics.se>
* *
*/ */
/**
* \addtogroup uip6
* @{
*/
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stddef.h> #include <stddef.h>

View file

@ -29,20 +29,20 @@
* *
*/ */
/**
* \addtogroup uip6
* @{
*/
/** /**
* \file * \file
* IPv6 Neighbor cache (link-layer/IPv6 address mapping) * IPv6 Neighbor cache (link-layer/IPv6 address mapping)
* \author Mathilde Durvy <mdurvy@cisco.com> * \author Mathilde Durvy <mdurvy@cisco.com>
* \author Julien Abeille <jabeille@cisco.com> * \author Julien Abeille <jabeille@cisco.com>
* \author Simon Duquennoy <simonduq@sics.se> * \author Simon Duquennoy <simonduq@sics.se>
* *
*/ */
/**
* \addtogroup uip6
* @{
*/
#ifndef UIP_DS6_NEIGHBOR_H_ #ifndef UIP_DS6_NEIGHBOR_H_
#define UIP_DS6_NEIGHBOR_H_ #define UIP_DS6_NEIGHBOR_H_
@ -99,12 +99,12 @@ int uip_ds6_nbr_num(void);
/** /**
* \brief * \brief
* This searches inside the neighbor table for the neighbor that is about to * This searches inside the neighbor table for the neighbor that is about to
* expire the next. * expire the next.
* *
* \return * \return
* A reference to the neighbor about to expire the next or NULL if * A reference to the neighbor about to expire the next or NULL if
* table is empty. * table is empty.
*/ */
uip_ds6_nbr_t *uip_ds6_get_least_lifetime_neighbor(void); uip_ds6_nbr_t *uip_ds6_get_least_lifetime_neighbor(void);

View file

@ -29,6 +29,15 @@
* OF THE POSSIBILITY OF SUCH DAMAGE. * OF THE POSSIBILITY OF SUCH DAMAGE.
* *
*/ */
/**
* \addtogroup uip6
* @{
*/
/**
* \file
* Routing table manipulation
*/
#include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-ds6.h"
#include "net/ip/uip.h" #include "net/ip/uip.h"
@ -636,3 +645,4 @@ uip_ds6_defrt_periodic(void)
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** @} */

View file

@ -29,6 +29,14 @@
* OF THE POSSIBILITY OF SUCH DAMAGE. * OF THE POSSIBILITY OF SUCH DAMAGE.
* *
*/ */
/**
* \addtogroup uip6
* @{
*/
/**
* \file
* Header file for routing table manipulation
*/
#ifndef UIP_DS6_ROUTE_H #ifndef UIP_DS6_ROUTE_H
#define 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 */ #endif /* UIP_DS6_ROUTE_H */
/** @} */

View file

@ -29,17 +29,17 @@
*/ */
/** /**
* \file * \addtogroup uip6
* IPv6 data structures handling functions. * @{
* Comprises part of the Neighbor discovery (RFC 4861)
* and auto configuration (RFC 4862) state machines.
* \author Mathilde Durvy <mdurvy@cisco.com>
* \author Julien Abeille <jabeille@cisco.com>
*/ */
/** /**
* \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 <mdurvy@cisco.com>
* \author Julien Abeille <jabeille@cisco.com>
*/ */
#include <string.h> #include <string.h>

View file

@ -5,7 +5,7 @@
/** /**
* \file * \file
* Network interface and stateless autoconfiguration (RFC 4862) * Header file for IPv6-related data structures
* \author Mathilde Durvy <mdurvy@cisco.com> * \author Mathilde Durvy <mdurvy@cisco.com>
* \author Julien Abeille <jabeille@cisco.com> * \author Julien Abeille <jabeille@cisco.com>
* *

View file

@ -31,15 +31,15 @@
*/ */
/** /**
* \file * \addtogroup uip6
* ICMPv6 echo request and error messages (RFC 4443) * @{
* \author Julien Abeille <jabeille@cisco.com>
* \author Mathilde Durvy <mdurvy@cisco.com>
*/ */
/** /**
* \addtogroup uip6 * \file
* @{ * ICMPv6 (RFC 4443) implementation, with message and error handling
* \author Julien Abeille <jabeille@cisco.com>
* \author Mathilde Durvy <mdurvy@cisco.com>
*/ */
#include <string.h> #include <string.h>

View file

@ -31,15 +31,15 @@
*/ */
/** /**
* \file * \addtogroup uip6
* ICMPv6 echo request and error messages (RFC 4443) * @{
* \author Julien Abeille <jabeille@cisco.com>
* \author Mathilde Durvy <mdurvy@cisco.com>
*/ */
/** /**
* \addtogroup uip6 * \file
* @{ * Header file for ICMPv6 message and error handing (RFC 4443)
* \author Julien Abeille <jabeille@cisco.com>
* \author Mathilde Durvy <mdurvy@cisco.com>
*/ */
#ifndef ICMP6_H_ #ifndef ICMP6_H_

View file

@ -57,15 +57,15 @@
*/ */
/** /**
* \file * \addtogroup uip6
* Neighbor discovery (RFC 4861) * @{
* \author Mathilde Durvy <mdurvy@cisco.com>
* \author Julien Abeille <jabeille@cisco.com>
*/ */
/** /**
* \addtogroup uip6 * \file
* @{ * Neighbor discovery (RFC 4861)
* \author Mathilde Durvy <mdurvy@cisco.com>
* \author Julien Abeille <jabeille@cisco.com>
*/ */
#include <string.h> #include <string.h>

View file

@ -31,15 +31,15 @@
*/ */
/** /**
* \file * \addtogroup uip6
* Neighbor discovery (RFC 4861) * @{
* \author Julien Abeille <jabeille@cisco.com>
* \author Mathilde Durvy <mdurvy@cisco.com>
*/ */
/** /**
* \addtogroup uip6 * \file
* @{ * Header file for IPv6 Neighbor discovery (RFC 4861)
* \author Julien Abeille <jabeille@cisco.com>
* \author Mathilde Durvy <mdurvy@cisco.com>
*/ */
#ifndef UIP_ND6_H_ #ifndef UIP_ND6_H_

View file

@ -31,20 +31,20 @@
* *
*/ */
/**
* \addtogroup uip6
* @{
*/
/** /**
* \file * \file
* The uIP TCP/IPv6 stack code. * The uIP TCP/IPv6 stack code.
* *
* \author Adam Dunkels <adam@sics.se> * \author Adam Dunkels <adam@sics.se>
* \author Julien Abeille <jabeille@cisco.com> (IPv6 related code) * \author Julien Abeille <jabeille@cisco.com> (IPv6 related code)
* \author Mathilde Durvy <mdurvy@cisco.com> (IPv6 related code) * \author Mathilde Durvy <mdurvy@cisco.com> (IPv6 related code)
*/ */
/**
* \addtogroup uip6
* @{
*/
/* /*
* uIP is a small implementation of the IP, UDP and TCP protocols (as * uIP is a small implementation of the IP, UDP and TCP protocols (as
* well as some basic ICMP stuff). The implementation couples the IP, * 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 */ /** Host L2 address */
#if UIP_CONF_LL_802154 #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 * \brief Type of the next header in IPv6 header or extension headers
@ -141,8 +147,9 @@ uint8_t uip_ext_opt_offset = 0;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Buffers */ /* Buffers */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name Buffer defines /**
* @{ * \name Buffer defines
* @{
*/ */
#define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0]) #define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0])
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) #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 */ #endif /* UIP_CONF_IPV6_RPL */
#define UIP_ICMP6_ERROR_BUF ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len]) #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 */ /** Packet buffer for incoming and outgoing packets */
#ifndef UIP_CONF_EXTERNAL_BUFFER #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 /* The uip_flags variable is used for communication between the TCP/IP stack
@ -209,7 +220,8 @@ static uint16_t lastport;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* TCP */ /* TCP */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name TCP defines /**
* \name TCP defines
*@{ *@{
*/ */
/* Structures and definitions. */ /* Structures and definitions. */
@ -227,7 +239,8 @@ static uint16_t lastport;
#define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */ #define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */
/** @} */ /** @} */
/** \name TCP variables /**
* \name TCP variables
*@{ *@{
*/ */
#if UIP_TCP #if UIP_TCP
@ -248,7 +261,10 @@ static uint16_t tmp16;
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** @{ \name UDP variables */ /**
* \name UDP variables
* @{
*/
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if UIP_UDP #if UIP_UDP
struct uip_udp_conn *uip_udp_conn; 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 #if UIP_CONF_ICMP6
/** single possible icmpv6 "connection" */ /** single possible icmpv6 "connection" */

View file

@ -64,12 +64,13 @@ uint32_t anti_replay_get_counter(void);
/** /**
* \brief Initializes the anti-replay information about the sender * \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); void anti_replay_init_info(struct anti_replay_info *info);
/** /**
* \brief Checks if received frame was replayed * \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 * \retval 0 <-> received frame was not replayed
*/ */
int anti_replay_was_replayed(struct anti_replay_info *info); int anti_replay_was_replayed(struct anti_replay_info *info);

View file

@ -43,7 +43,7 @@
*/ */
/** /**
* \defgroup llsec802154 * \defgroup llsec802154 Link Layer Security Common Functionality
* *
* Common functionality of 802.15.4-compliant llsec_drivers. * Common functionality of 802.15.4-compliant llsec_drivers.
* *

View file

@ -43,7 +43,7 @@
*/ */
/** /**
* \defgroup noncoresec * \defgroup noncoresec LLSEC driver using a network-wide key (NONCORESEC)
* *
* Noncompromise-resilient 802.15.4 security * Noncompromise-resilient 802.15.4 security
* *

View file

@ -43,7 +43,7 @@
*/ */
/** /**
* \defgroup nullsec * \defgroup nullsec LLSEC driver with zero security (NULLSEC)
* *
* Insecure link layer security driver. * Insecure link layer security driver.
* *

View file

@ -44,7 +44,7 @@
*/ */
/** /**
* \addtogroup net 802.15.4 frame creation and parsing * \addtogroup net
* @{ * @{
*/ */

View file

@ -49,7 +49,7 @@
* The abc module sends packets to all local area neighbors. The abc * The abc module sends packets to all local area neighbors. The abc
* module adds no headers to outgoing packets. * module adds no headers to outgoing packets.
* *
* \section channels Channels * \section abc-channels Channels
* *
* The abc module uses 1 channel. * The abc module uses 1 channel.
* *

View file

@ -131,6 +131,7 @@ void announcement_remove(struct announcement *a);
* \brief Set the value of an announcement * \brief Set the value of an announcement
* \param a A pointer to a struct announcement that has * \param a A pointer to a struct announcement that has
* previously been registered * previously been registered
* \param value The new value
* *
* This function sets the value of an announcement that * This function sets the value of an announcement that
* has previously been registered with * has previously been registered with

View file

@ -50,7 +50,7 @@
* announcement. THe module announces the announcements that have been * announcement. THe module announces the announcements that have been
* registered with the \ref rimeannouncement "announcement module". * registered with the \ref rimeannouncement "announcement module".
* *
* \section channels Channels * \section bcast-announce-channels Channels
* *
* The broadcast announcement module uses 1 channel. * The broadcast announcement module uses 1 channel.
* *

View file

@ -56,7 +56,7 @@
* either directly or indirectly through any of the other * either directly or indirectly through any of the other
* communication primitives that are based on the broadcast primitive. * communication primitives that are based on the broadcast primitive.
* *
* \section channels Channels * \section broadcast-channels Channels
* *
* The broadcast module uses 1 channel. * The broadcast module uses 1 channel.
* *

View file

@ -49,7 +49,7 @@
* The collect module implements a hop-by-hop reliable data collection * The collect module implements a hop-by-hop reliable data collection
* mechanism. * mechanism.
* *
* \section channels Channels * \section collect-channels Channels
* *
* The collect module uses 2 channels; one for neighbor discovery and one * The collect module uses 2 channels; one for neighbor discovery and one
* for data packets. * for data packets.

View file

@ -84,7 +84,7 @@
* The polite broadcast module does not add any packet attributes to * The polite broadcast module does not add any packet attributes to
* outgoing packets apart from those added by the upper layer. * outgoing packets apart from those added by the upper layer.
* *
* \section channels Channels * \section ipolite-channels Channels
* *
* The ipolite module uses 1 channel. * The ipolite module uses 1 channel.
* *

View file

@ -50,7 +50,7 @@
* receiver somewhere in the network. * receiver somewhere in the network.
* *
* *
* \section channels Channels * \section mesh-channels Channels
* *
* The mesh module uses 3 channel; one for the multi-hop forwarding * The mesh module uses 3 channel; one for the multi-hop forwarding
* (\ref rimemultihop "multihop") and two for the route disovery (\ref * (\ref rimemultihop "multihop") and two for the route disovery (\ref

View file

@ -61,7 +61,7 @@
* process. * process.
* *
* *
* \section channels Channels * \section multihop-channels Channels
* *
* The multihop module uses 1 channel. * The multihop module uses 1 channel.
* *

View file

@ -50,7 +50,7 @@
* discovery mechanism. A callback is invoked for every incoming * discovery mechanism. A callback is invoked for every incoming
* neighbor discovery message. * neighbor discovery message.
* *
* \section channels Channels * \section neighbor-discovery-channels Channels
* *
* The neighbor-discovery module uses 1 channel. * The neighbor-discovery module uses 1 channel.
* *

View file

@ -65,7 +65,7 @@
* If the time to live reaches zero, the primitive does not forward * If the time to live reaches zero, the primitive does not forward
* the packet. * the packet.
* *
* \section channels Channels * \section netflood-channels Channels
* *
* The netflood module uses 1 channel. * The netflood module uses 1 channel.
* *

View file

@ -78,7 +78,7 @@ struct packetqueue {
* This structure holds the state of a packet queue. It is * This structure holds the state of a packet queue. It is
* an opaque structure with no user-visible elements. The * an opaque structure with no user-visible elements. The
* function packetqueue_queuebuf() is used to extract a * 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 * packetqueue_ptr() is used to extract the opaque pointer
* that was registered with the * that was registered with the
* packetqueue_enqueue_packetbuf() function. * packetqueue_enqueue_packetbuf() function.

View file

@ -50,7 +50,7 @@
* announcement. THe module announces the announcements that have been * announcement. THe module announces the announcements that have been
* registered with the \ref rimeannouncement "announcement module". * registered with the \ref rimeannouncement "announcement module".
* *
* \section channels Channels * \section polite-announcement-channels Channels
* *
* The polite announcement module uses 1 channel. * The polite announcement module uses 1 channel.
* *

View file

@ -84,7 +84,7 @@
* The polite broadcast module does not add any packet attributes to * The polite broadcast module does not add any packet attributes to
* outgoing packets apart from those added by the upper layer. * outgoing packets apart from those added by the upper layer.
* *
* \section channels Channels * \section polite-channels Channels
* *
* The polite module uses 1 channel. * The polite module uses 1 channel.
* *

View file

@ -56,7 +56,7 @@
* reliable single-hop primitive for the communication between two * reliable single-hop primitive for the communication between two
* single-hop neighbors. * single-hop neighbors.
* *
* \section channels Channels * \section rmh-channels Channels
* *
* The rmh module uses 1 channel. * The rmh module uses 1 channel.
* *

View file

@ -48,7 +48,7 @@
* *
* The route-discovery module does route discovery for Rime. * 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 * The ibc module uses 2 channels; one for the flooded route request
* packets and one for the unicast route replies. * packets and one for the unicast route replies.

View file

@ -49,7 +49,7 @@
* The rudolph0 module implements a single-hop reliable bulk data * The rudolph0 module implements a single-hop reliable bulk data
* transfer mechanism. * transfer mechanism.
* *
* \section channels Channels * \section rudolph0-channels Channels
* *
* The rudolph0 module uses 2 channels; one for data packets and one * The rudolph0 module uses 2 channels; one for data packets and one
* for NACK and repair packets. * for NACK and repair packets.

View file

@ -49,7 +49,7 @@
* The rudolph1 module implements a multi-hop reliable bulk data * The rudolph1 module implements a multi-hop reliable bulk data
* transfer mechanism. * transfer mechanism.
* *
* \section channels Channels * \section rudolph1-channels Channels
* *
* The rudolph1 module uses 2 channels; one for data transmissions and * The rudolph1 module uses 2 channels; one for data transmissions and
* one for NACKs and repair packets. * one for NACKs and repair packets.

View file

@ -49,7 +49,7 @@
* The rudolph2 module implements a single-hop reliable bulk data * The rudolph2 module implements a single-hop reliable bulk data
* transfer mechanism. * transfer mechanism.
* *
* \section channels Channels * \section rudolph2-channels Channels
* *
* The rudolph2 module uses 2 channels; one for data packets and one * The rudolph2 module uses 2 channels; one for data packets and one
* for NACK and repair packets. * for NACK and repair packets.

View file

@ -69,7 +69,7 @@
* callback. * callback.
* *
* *
* \section channels Channels * \section runicast-channels Channels
* *
* The runicast module uses 1 channel. * The runicast module uses 1 channel.
* *

View file

@ -51,7 +51,7 @@
* either the message is canceled or a new message is sent. Messages * either the message is canceled or a new message is sent. Messages
* sent with the stbroadcast module are not identified with a sender ID. * 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. * The stbroadcast module uses 1 channel.
* *

View file

@ -63,7 +63,7 @@
* number of retransmissions for a packet as a packet attribute on * number of retransmissions for a packet as a packet attribute on
* outgoing packets. * outgoing packets.
* *
* \section channels Channels * \section stunicast-channels Channels
* *
* The stunicast module uses 1 channel. * The stunicast module uses 1 channel.
* *

View file

@ -48,7 +48,7 @@
* *
* The trickle module sends a single packet to all nodes on the network. * 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. * The trickle module uses 1 channel.
* *

View file

@ -53,7 +53,7 @@
* single-hop receiver address attribute and discards the packet if * single-hop receiver address attribute and discards the packet if
* the address does not match the address of the node. * the address does not match the address of the node.
* *
* \section channels Channels * \section unicast-channels Channels
* *
* The unicast module uses 1 channel. * The unicast module uses 1 channel.
* *

View file

@ -64,7 +64,7 @@
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define RPL_DIO_GROUNDED 0x80 #define RPL_DIO_GROUNDED 0x80
#define RPL_DIO_MOP_SHIFT 3 #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 RPL_DIO_PREFERENCE_MASK 0x07
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])

View file

@ -76,9 +76,9 @@ rpl_set_mode(enum rpl_mode m)
switching to. */ switching to. */
if(m == RPL_MODE_MESH) { 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, 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. */ we are in feather mode. */
PRINTF("RPL: switching to mesh mode\n"); PRINTF("RPL: switching to mesh mode\n");
mode = m; mode = m;

View file

@ -133,7 +133,7 @@
* strings. * strings.
* *
* We need use two macros (CC_CONCAT and CC_CONCAT2) in order to allow * 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) #define CC_CONCAT(s1, s2) CC_CONCAT2(s1, s2)

View file

@ -57,7 +57,7 @@
* *
* \note The clock library need in many cases not be used * \note The clock library need in many cases not be used
* directly. Rather, the \ref timer "timer library", \ref etimer * 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 timer "Timer library"
* \sa \ref etimer "Event timers" * \sa \ref etimer "Event timers"

View file

@ -105,7 +105,7 @@ struct dsc {
* *
* \param prgname The name of the program on disk. * \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. * program.
* *
* \param icon A pointer to the CTK icon. * \param icon A pointer to the CTK icon.

View file

@ -267,7 +267,7 @@ do_event(void)
receiver = events[fevent].p; receiver = events[fevent].p;
/* Since we have seen the new event, we move pointer upwards /* 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; fevent = (fevent + 1) % PROCESS_CONF_NUMEVENTS;
--nevents; --nevents;
@ -337,7 +337,7 @@ process_post(struct process *p, process_event_t ev, process_data_t data)
if(p == PROCESS_BROADCAST) { 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)); printf("soft panic: event queue is full when broadcast event %d was posted from %s\n", ev, PROCESS_NAME_STRING(process_current));
} else { } 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 */ #endif /* DEBUG */
return PROCESS_ERR_FULL; return PROCESS_ERR_FULL;

View file

@ -335,7 +335,7 @@ struct process {
* *
* \param p A pointer to a process structure. * \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 * process
* *
*/ */

View file

@ -39,8 +39,8 @@ CROSS_COMPILE = arm-none-eabi-
CC = $(CROSS_COMPILE)gcc CC = $(CROSS_COMPILE)gcc
LD = $(CROSS_COMPILE)gcc LD = $(CROSS_COMPILE)gcc
AS = $(CROSS_COMPILE)gcc AS = $(CROSS_COMPILE)gcc
AR = $(CROSS_COMPILE)ar AR = $(CROSS_COMPILE)gcc-ar
NM = $(CROSS_COMPILE)nm NM = $(CROSS_COMPILE)gcc-nm
OBJCOPY = $(CROSS_COMPILE)objcopy OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump OBJDUMP = $(CROSS_COMPILE)objdump
STRIP = $(CROSS_COMPILE)strip STRIP = $(CROSS_COMPILE)strip

View file

@ -159,7 +159,7 @@ clock_set_seconds(unsigned long sec)
seconds = sec; seconds = sec;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /*
* Wait for a number of clock ticks. * Wait for a number of clock ticks.
*/ */
void void
@ -175,7 +175,7 @@ clock_wait(clock_time_t t)
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /*
* Delay the CPU for up to 65535*(4000000/F_CPU) microseconds. * 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. * 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 * 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 void
clock_delay_usec(uint16_t howlong) clock_delay_usec(uint16_t dt)
{ {
#if 0 #if 0
/* Accurate delay at any frequency, but introduces a 64 bit intermediate /* Accurate delay at any frequency, but introduces a 64 bit intermediate
* and has a 279 clock overhead. * and has a 279 clock overhead.
*/ */
if(howlong<=(uint16_t)(279000000UL/F_CPU)) return; if(dt<=(uint16_t)(279000000UL/F_CPU)) return;
howlong-=(uint16_t) (279000000UL/F_CPU); dt-=(uint16_t) (279000000UL/F_CPU);
my_delay_loop_2(((uint64_t)(howlong) * (uint64_t) F_CPU) / 4000000ULL); my_delay_loop_2(((uint64_t)(dt) * (uint64_t) F_CPU) / 4000000ULL);
/* Remaining numbers tweaked for the breakpoint CPU frequencies */ /* Remaining numbers tweaked for the breakpoint CPU frequencies */
/* Add other frequencies as necessary */ /* Add other frequencies as necessary */
#elif F_CPU>=16000000UL #elif F_CPU>=16000000UL
if(howlong<1) return; if(dt<1) return;
my_delay_loop_2((howlong*(uint16_t)(F_CPU/3250000))); my_delay_loop_2((dt*(uint16_t)(F_CPU/3250000)));
#elif F_CPU >= 12000000UL #elif F_CPU >= 12000000UL
if(howlong<2) return; if(dt<2) return;
howlong-=(uint16_t) (3*12000000/F_CPU); dt-=(uint16_t) (3*12000000/F_CPU);
my_delay_loop_2((howlong*(uint16_t)(F_CPU/3250000))); my_delay_loop_2((dt*(uint16_t)(F_CPU/3250000)));
#elif F_CPU >= 8000000UL #elif F_CPU >= 8000000UL
if(howlong<4) return; if(dt<4) return;
howlong-=(uint16_t) (3*8000000/F_CPU); dt-=(uint16_t) (3*8000000/F_CPU);
my_delay_loop_2((howlong*(uint16_t)(F_CPU/2000000))/2); my_delay_loop_2((dt*(uint16_t)(F_CPU/2000000))/2);
#elif F_CPU >= 4000000UL #elif F_CPU >= 4000000UL
if(howlong<5) return; if(dt<5) return;
howlong-=(uint16_t) (4*4000000/F_CPU); dt-=(uint16_t) (4*4000000/F_CPU);
my_delay_loop_2((howlong*(uint16_t)(F_CPU/2000000))/2); my_delay_loop_2((dt*(uint16_t)(F_CPU/2000000))/2);
#elif F_CPU >= 2000000UL #elif F_CPU >= 2000000UL
if(howlong<11) return; if(dt<11) return;
howlong-=(uint16_t) (10*2000000/F_CPU); dt-=(uint16_t) (10*2000000/F_CPU);
my_delay_loop_2((howlong*(uint16_t)(F_CPU/1000000))/4); my_delay_loop_2((dt*(uint16_t)(F_CPU/1000000))/4);
#elif F_CPU >= 1000000UL #elif F_CPU >= 1000000UL
if(howlong<=17) return; if(dt<=17) return;
howlong-=(uint16_t) (17*1000000/F_CPU); dt-=(uint16_t) (17*1000000/F_CPU);
my_delay_loop_2((howlong*(uint16_t)(F_CPU/1000000))/4); my_delay_loop_2((dt*(uint16_t)(F_CPU/1000000))/4);
#else #else
howlong >> 5; dt >> 5;
if (howlong < 1) return; if (dt < 1) return;
my_delay_loop_2(howlong); my_delay_loop_2(dt);
#endif #endif
} }
#if 0 #if 0
@ -250,7 +250,7 @@ clock_delay(unsigned int howlong)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**
* Delay up to 65535 milliseconds. * 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. * Neither interrupts nor the watchdog timer is disabled over the delay.
* Platforms are not required to implement this call. * Platforms are not required to implement this call.
@ -279,7 +279,7 @@ clock_delay_msec(uint16_t howlong)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**
* Adjust the system current clock time. * 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 * Typically used to add ticks after an MCU sleep
* clock_seconds will increment if necessary to reflect the tick addition. * clock_seconds will increment if necessary to reflect the tick addition.

View file

@ -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 count = 0; /* Uptime in ticks */
static volatile CC_AT_DATA clock_time_t seconds = 0; /* Uptime in secs */ 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 * Each iteration is ~1.0xy usec, so this function delays for roughly len usec
*/ */
void void
@ -68,7 +68,7 @@ clock_delay_usec(uint16_t len)
ENABLE_INTERRUPTS(); ENABLE_INTERRUPTS();
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /*
* Wait for a multiple of ~8 ms (a tick) * Wait for a multiple of ~8 ms (a tick)
*/ */
void void

View file

@ -136,16 +136,15 @@ clock_wait(clock_time_t i)
while(clock_time() - start < (clock_time_t)i); while(clock_time() - start < (clock_time_t)i);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /*
* \brief Arch-specific implementation of clock_delay_usec for the cc2538 * Arch-specific implementation of clock_delay_usec for the cc2538
* \param len Delay \e len uSecs
* *
* See clock_init() for GPT0 Timer A's configuration * See clock_init() for GPT0 Timer A's configuration
*/ */
void 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_TAILR) = dt;
REG(GPT_0_BASE | GPTIMER_CTL) |= GPTIMER_CTL_TAEN; REG(GPT_0_BASE | GPTIMER_CTL) |= GPTIMER_CTL_TAEN;
/* One-Shot mode: TAEN will be cleared when the timer reaches 0 */ /* One-Shot mode: TAEN will be cleared when the timer reaches 0 */

View file

@ -29,12 +29,21 @@
* OF THE POSSIBILITY OF SUCH DAMAGE. * 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 * \defgroup cc2538-cpu cc2538 CPU
* *
* cc2538 CPU-specific functions for the cc2538 core * CPU-specific functions for the cc2538 core
* @{ * @{
* *
* \file * \file
@ -60,6 +69,8 @@ unsigned long cpu_cpsie(void);
#endif /* CPU_H_ */ #endif /* CPU_H_ */
/** /**
* @}
* @}
* @} * @}
* @} * @}
*/ */

View file

@ -34,7 +34,7 @@
* *
* \defgroup cc2538-char-io cc2538 Character I/O * \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 * On the cc2538, character I/O can be directed over USB or UART. This is
* controlled by a series of configuration directives: * controlled by a series of configuration directives:

View file

@ -122,6 +122,7 @@ static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /** Snif */
#endif #endif
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static uint8_t rf_flags; static uint8_t rf_flags;
static uint8_t rf_channel = CC2538_RF_CHANNEL;
static int on(void); static int on(void);
static int off(void); static int off(void);
@ -186,10 +187,22 @@ set_channel(uint8_t channel)
} }
/* Changes to FREQCTRL take effect after the next recalibration */ /* 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 REG(RFCORE_XREG_FREQCTRL) = (CC2538_RF_CHANNEL_MIN
+ (channel - CC2538_RF_CHANNEL_MIN) * CC2538_RF_CHANNEL_SPACING); + (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; return (int8_t) channel;
} }
@ -445,7 +458,7 @@ init(void)
/* Set TX Power */ /* Set TX Power */
REG(RFCORE_XREG_TXPOWER) = CC2538_RF_TX_POWER; REG(RFCORE_XREG_TXPOWER) = CC2538_RF_TX_POWER;
set_channel(CC2538_RF_CHANNEL); set_channel(rf_channel);
/* Acknowledge RF interrupts, FIFOP only */ /* Acknowledge RF interrupts, FIFOP only */
REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP; 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 we were polled due to an RF error, reset the transceiver */
if(rf_flags & RF_MUST_RESET) { if(rf_flags & RF_MUST_RESET) {
uint8_t was_on;
rf_flags = 0; 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(); off();
init(); init();
if(was_on) {
/* switch back on */
on();
}
} }
} }

View file

@ -117,6 +117,20 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin);
/** \brief Set pins with PIN_MASK of port with PORT_BASE to value. /** \brief Set pins with PIN_MASK of port with PORT_BASE to value.
* \param PORT_BASE GPIO Port register offset * \param PORT_BASE GPIO Port register offset
* \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 * \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) \ #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)
@ -124,6 +138,12 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin);
/** \brief Read pins with PIN_MASK of port with PORT_BASE. /** \brief Read pins with PIN_MASK of port with PORT_BASE.
* \param PORT_BASE GPIO Port register offset * \param PORT_BASE GPIO Port register offset
* \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 * \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) \ #define GPIO_READ_PIN(PORT_BASE, PIN_MASK) \
REG(((PORT_BASE) | GPIO_DATA) + ((PIN_MASK) << 2)) REG(((PORT_BASE) | GPIO_DATA) + ((PIN_MASK) << 2))
@ -261,7 +281,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin);
/** /**
* \brief Converts a pin number to a pin mask * \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 * \return A pin mask which can be used as the PIN_MASK argument of the macros
* in this category * 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 * \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 * \return The base address for the registers corresponding to that port
* number. * number.
*/ */

View file

@ -34,7 +34,7 @@
* *
* \defgroup cc2538-ioc cc2538 I/O Control * \defgroup cc2538-ioc cc2538 I/O Control
* *
* cc2538 I/O Control Module * Driver for the cc2538 I/O Control Module
* @{ * @{
* *
* \file * \file

View file

@ -32,7 +32,9 @@
* \addtogroup cc2538 * \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 * \file

View file

@ -31,7 +31,7 @@
* @{ * @{
* *
* \file * \file
* Implementation of the cc2538 SPI peripheral * Implementation of the cc2538 SPI peripheral driver
*/ */
#include "contiki.h" #include "contiki.h"
#include "reg.h" #include "reg.h"
@ -52,7 +52,7 @@
/** /**
* \brief Initialize the SPI bus. * \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_CLK_PORT SPI_CLK_PIN
* SPI_MOSI_PORT SPI_MOSI_PIN * SPI_MOSI_PORT SPI_MOSI_PIN
* SPI_MISO_PORT SPI_MISO_PIN * SPI_MISO_PORT SPI_MISO_PIN
@ -126,7 +126,9 @@ spi_disable(void)
REG(SYS_CTRL_RCGCSSI) &= ~1; 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 */ /* Disable the SSI peripheral to configure it */
REG(SSI0_BASE + SSI_CR1) = 0; REG(SSI0_BASE + SSI_CR1) = 0;

View file

@ -32,7 +32,7 @@
* \addtogroup cc2538 * \addtogroup cc2538
* @{ * @{
* *
* \defgroup cc2538-sys-ctrl cc2538 System Control * \defgroup cc2538-sys-ctrl cc2538 System Control (SysCtrl)
* *
* Driver for the cc2538 System Control Module * Driver for the cc2538 System Control Module
* @{ * @{

View file

@ -560,12 +560,13 @@ void udma_init(void);
/** /**
* \brief Sets the channels source address * \brief Sets the channels source address
* \param channel The channel as a value in [0 , UDMA_CONF_MAX_CHANNEL] * \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); 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] * \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); void udma_set_channel_dst(uint8_t channel, uint32_t dst_end);

View file

@ -27,16 +27,13 @@
* SUCH DAMAGE. * 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 * \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_ #ifndef SPI_ARCH_H_
#define 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_ */ #endif /* SPI_ARCH_H_ */
/** /**
* @}
* @} * @}
*/ */

View file

@ -70,7 +70,7 @@ clock_delay_usec(uint16_t len)
ENABLE_INTERRUPTS(); ENABLE_INTERRUPTS();
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /*
* Wait for a multiple of ~8 ms (a tick) * Wait for a multiple of ~8 ms (a tick)
*/ */
void void

View file

@ -39,7 +39,7 @@ uart0_init()
#else #else
PERCFG &= ~PERCFG_U0CFG; /* alternative port 1 = P0.5-2 */ PERCFG &= ~PERCFG_U0CFG; /* alternative port 1 = P0.5-2 */
#ifdef UART0_RTSCTS #ifdef UART0_RTSCTS
P0SEL |= 0x20 | 0x10; /* peripheral select for TX and RX */ P0SEL |= 0x3C; /* peripheral select for RTS and CTS, TX, RX */
#else #else
P0SEL |= 0x0C; /* peripheral select for TX and RX */ P0SEL |= 0x0C; /* peripheral select for TX and RX */
P0 &= ~0x20; /* RTS down */ P0 &= ~0x20; /* RTS down */

View file

@ -97,7 +97,7 @@ clock_wait(clock_time_t t)
while ((signed long)(current_clock - endticks) < 0) {;} while ((signed long)(current_clock - endticks) < 0) {;}
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /*
* Delay the CPU for up to 65535 microseconds. * Delay the CPU for up to 65535 microseconds.
* Use the 250KHz MACA clock for longer delays to avoid interrupt effects. * 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! * 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); while(--i);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /*
* Delay the CPU for up to 65535 milliseconds. The watchdog is NOT disabled. * Delay the CPU for up to 65535 milliseconds. The watchdog is NOT disabled.
*/ */
void void
@ -127,7 +127,7 @@ clock_delay_msec(uint16_t howlong)
while(howlong--) clock_delay_usec(1000); while(howlong--) clock_delay_usec(1000);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /*
* Legacy delay. The original clock_delay for the msp430 used a granularity * 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. * of 2.83 usec. This approximates that delay for values up to 1456 usec.
* (The largest core call in leds.c uses 400). * (The largest core call in leds.c uses 400).
@ -139,7 +139,7 @@ clock_delay(unsigned int howlong)
clock_delay_usec((283*howlong)/100); clock_delay_usec((283*howlong)/100);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /*
* Adjust clock ticks after a cpu sleep. * Adjust clock ticks after a cpu sleep.
*/ */
void clock_adjust_ticks(clock_time_t howmany) { void clock_adjust_ticks(clock_time_t howmany) {

View file

@ -195,7 +195,7 @@ clock_delay(unsigned int i)
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /*
* Wait for a multiple of 10 ms. * Wait for a multiple of 10 ms.
* *
*/ */

View file

@ -192,7 +192,7 @@ clock_delay(unsigned int i)
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /*
* Wait for a multiple of 10 ms. * Wait for a multiple of 10 ms.
* *
*/ */

View file

@ -113,7 +113,7 @@ clock_delay(unsigned int i)
} }
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /*
* Wait for a multiple of 1 ms. * Wait for a multiple of 1 ms.
*/ */
void void

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,6 @@
/** /**
\defgroup buildsystem The Contiki build system \defgroup buildsystem The Contiki build system
.
The Contiki build system is designed to make it easy to compile The Contiki build system is designed to make it easy to compile
Contiki applications for either to a hardware platform or into a Contiki applications for either to a hardware platform or into a
simulation platform by simply supplying different parameters to the simulation platform by simply supplying different parameters to the
@ -18,18 +16,15 @@
builds an entire Contiki system as a program that runs on the builds an entire Contiki system as a program that runs on the
development system. After compiling the application for the development system. After compiling the application for the
<tt>native</tt> target it is possible to run the Contiki system with <tt>native</tt> target it is possible to run the Contiki system with
the application by running the file <tt>hello-world.native</tt>. To the application by running the file <tt>hello-world.native</tt>.
compile the application and a Contiki system for the \ref esb "ESB
platform" the command <tt>make TARGET=esb</tt> is used. This produces
a hello-world.esb file that can be loaded into an ESB board.
To compile the hello-world application into a stand-alone executable To compile the hello-world application into a stand-alone executable
that can be loaded into a running Contiki system, the command that can be loaded into a running Contiki system, the command
<tt>make hello-world.ce</tt> is used. To build an executable file for <tt>make hello-world.ce</tt> is used. To build an executable file for
the ESB platform, <tt>make TARGET=esb hello-world.ce</tt> is run. the Sky platform, <tt>make TARGET=sky hello-world.sky</tt> is run.
To avoid having to type <tt>TARGET=</tt> every time <tt>make</tt> is To avoid having to type <tt>TARGET=</tt> every time <tt>make</tt> is
run, it is possible to run <tt>make TARGET=esb savetarget</tt> to run, it is possible to run <tt>make TARGET=sky savetarget</tt> to
save the selected target as the default target platform for save the selected target as the default target platform for
subsequent invocations of <tt>make</tt>. A file called subsequent invocations of <tt>make</tt>. A file called
<tt>Makefile.target</tt> containing the currently saved target is <tt>Makefile.target</tt> containing the currently saved target is

View file

@ -93,8 +93,6 @@ Contiki is designed to run on many different \ref platform "platforms". It is al
possible to compile and build both the Contiki system and Contiki possible to compile and build both the Contiki system and Contiki
applications on many different development platforms. applications on many different development platforms.
See \ref esb-getting-started "Getting started with Contiki for the ESB platform
\section contiki-mainpage-building Building the Contiki system and its applications \section contiki-mainpage-building Building the Contiki system and its applications
The Contiki build system is designed to make it easy to compile The Contiki build system is designed to make it easy to compile

View file

@ -57,11 +57,6 @@
* \ingroup platform * \ingroup platform
*/ */
/**
* \addtogroup cc2538dk CC2538 Development Kit
* \ingroup platform
*/
/** /**
* \addtogroup cooja COOJA network simulator node * \addtogroup cooja COOJA network simulator node
* \ingroup platform * \ingroup platform

View file

@ -11,18 +11,18 @@ support on Atmel RAVEN hardware.
\section toc Table of contents \section toc Table of contents
\ref introduction<br> \ref tutorial-raven-introduction <br>
\ref hardware<br> \ref hardware <br>
\ref software<br> \ref software <br>
\ref overview<br> \ref overview <br>
\ref installation<br> \ref installation <br>
\ref running<br> \ref running <br>
\ref advanced<br> \ref advanced <br>
\ref issues<br> \ref issues <br>
\ref annex<br> \ref annex <br>
<HR> <HR>
\section introduction Introduction \section tutorial-raven-introduction Introduction
This tutorial explains how to run Contiki with IPv6 and 6lowpan This tutorial explains how to run Contiki with IPv6 and 6lowpan
support on Atmel RAVEN evaluation kit (ATAVRRZRAVEN) hardware. We support on Atmel RAVEN evaluation kit (ATAVRRZRAVEN) hardware. We
present basic example system architecture and application scenarios, present basic example system architecture and application scenarios,
@ -419,7 +419,7 @@ is the one to the file you just modified and click on "Program".
The third is to modify the default value in the code: The third is to modify the default value in the code:
\li Edit the file contiki-raven-main.c in the directory \li Edit the file contiki-raven-main.c in the directory
platform\avr-raven. You will see the MAC address set in a line like: platform\\avr-raven. You will see the MAC address set in a line like:
\code \code
/* Put default MAC address in EEPROM */ /* Put default MAC address in EEPROM */

View file

@ -66,7 +66,7 @@ This part of the code is very similar to the \ref ipreass "IPv4 fragmentation co
is not assumed to be a TCP packet. As a result, we use a different is not assumed to be a TCP packet. As a result, we use a different
%timer to time-out reassembly if all fragments have not been received %timer to time-out reassembly if all fragments have not been received
after #UIP_REASS_MAXAGE = 60s. after #UIP_REASS_MAXAGE = 60s.
\note Fragment reassembly is enabled if #UIP_CONF_REASSEMBLY is set to 1. \note Fragment reassembly is enabled if #UIP_REASSEMBLY is set to 1.
\note We can only reassemble packet of at most #UIP_LINK_MTU = 1280 \note We can only reassemble packet of at most #UIP_LINK_MTU = 1280
bytes as we do not have larger buffers. bytes as we do not have larger buffers.
@ -81,9 +81,9 @@ typedef union uip_ip6addr_t {
\endcode \endcode
We assume that each node has a <em>single interface</em> of type We assume that each node has a <em>single interface</em> of type
#uip_netif. #uip_ds6_netif_t.
Each interface can have up to #UIP_NETIF_MAX_ADDRESSES unicast IPv6 Each interface can have a configurable number of unicast IPv6
addresses including its link-local address. It also has a addresses including its link-local address. It also has a
solicited-node multicast address. We assume that the unicast solicited-node multicast address. We assume that the unicast
addresses are obtained via \ref autoconf "stateless address autoconfiguration" addresses are obtained via \ref autoconf "stateless address autoconfiguration"
@ -377,5 +377,7 @@ We pass all the tests for phase 2 except:
<HR> <HR>
@{
*/ */
/** @} */ /** @} */
/** @} */

View file

@ -29,10 +29,10 @@
* OF THE POSSIBILITY OF SUCH DAMAGE. * OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/** /**
* \addtogroup cc2538 * \addtogroup cc2538-platforms
* @{ * @{
* *
* \defgroup cc2538-examples cc2538dk Example Projects * \defgroup cc2538-examples cc2538 Example Projects
* @{ * @{
* *
* \defgroup cc2538-demo cc2538dk Demo Project * \defgroup cc2538-demo cc2538dk Demo Project

View file

@ -0,0 +1,10 @@
DEFINES+=PROJECT_CONF_H=\"project-conf.h\"
all: mqtt-demo
CONTIKI_WITH_IPV6 = 1
APPS += mqtt
CONTIKI=../../..
include $(CONTIKI)/Makefile.include

View file

@ -0,0 +1 @@
TARGET = cc2538dk

View file

@ -0,0 +1,62 @@
MQTT Demo
=========
The MQTT client can be used to:
* Publish sensor readings to an MQTT broker.
* Subscribe to a topic and receive commands from an MQTT broker
The demo will give some visual feedback with the green LED:
* Very fast blinking: Searching for a network
* Fast blinking: Connecting to broker
* Slow, long blinking: Sending a publish message
Publishing
----------
By default the example will attempt to publish readings to an MQTT broker
running on the IPv6 address specified as `MQTT_DEMO_BROKER_IP_ADDR` in
`project-conf.h`. This functionality was tested successfully with
[mosquitto](http://mosquitto.org/).
The publish messages include sensor readings but also some other information,
such as device uptime in seconds and a message sequence number. The demo will
publish to topic `iot-2/evt/status/fmt/json`. The device will connect using
client-id `d:quickstart:cc2538:<device-id>`, where `<device-id>` gets
constructed from the device's IEEE address.
Subscribing
-----------
You can also subscribe to topics and receive commands, but this will only
work if you use "Org ID" != 'quickstart'. To achieve this, you will need to
change 'Org ID' (`DEFAULT_ORG_ID`). In this scenario, the device will subscribe
to:
`iot-2/cmd/+/fmt/json`
You can then use this to toggle LEDs. To do this, you can for example
use mosquitto client to publish to `iot-2/cmd/leds/fmt/json`. So, to change
the state of an LED, you would do this:
`mosquitto_pub -h <broker IP> -m "1" -t iot-2/cmd/leds/fmt/json`
Where `broker IP` should be replaced with the IP address of your mosquitto
broker (the one where you device has subscribed). Replace `-m "1'` with `-m "0"`
to turn the LED back off.
Bear in mind that, even though the topic suggests that messages are of json
format, they are in fact not. This was done in order to avoid linking a json
parser into the firmware. This comment only applies to parsing incoming
messages, outgoing publish messages use proper json payload.
IBM Quickstart Service
----------------------
It is also possible to publish to IBM's quickstart service. To do so, you need
to undefine `MQTT_DEMO_BROKER_IP_ADDR`.
The device will then try to connect to IBM's quickstart over NAT64, so you will
need a NAT64 gateway in your network to make this work. A guide on how to
setup NAT64 is out of scope here.
If you want to use IBM's cloud service with a registered device, change
'Org ID' (`DEFAULT_ORG_ID`) and provide the 'Auth Token' (`DEFAULT_AUTH_TOKEN`),
which acts as a 'password', but bear in mind that it gets transported in clear
text.

View file

@ -0,0 +1,735 @@
/*
* 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 cc2538-examples
* @{
*
* \defgroup cc2538-mqtt-demo CC2538DK MQTT Demo Project
*
* Demonstrates MQTT functionality. Works with IBM Quickstart as well as
* mosquitto.
* @{
*
* \file
* An MQTT example for the cc2538dk platform
*/
/*---------------------------------------------------------------------------*/
#include "contiki-conf.h"
#include "rpl/rpl-private.h"
#include "mqtt.h"
#include "net/rpl/rpl.h"
#include "net/ip/uip.h"
#include "net/ipv6/uip-icmp6.h"
#include "net/ipv6/sicslowpan.h"
#include "sys/etimer.h"
#include "sys/ctimer.h"
#include "lib/sensors.h"
#include "dev/button-sensor.h"
#include "dev/leds.h"
#include "dev/adc-sensor.h"
#include <string.h>
/*---------------------------------------------------------------------------*/
/*
* IBM server: messaging.quickstart.internetofthings.ibmcloud.com
* (184.172.124.189) mapped in an NAT64 (prefix 64:ff9b::/96) IPv6 address
* Note: If not able to connect; lookup the IP address again as it may change.
*
* Alternatively, publish to a local MQTT broker (e.g. mosquitto) running on
* the node that hosts your border router
*/
#ifdef MQTT_DEMO_BROKER_IP_ADDR
static const char *broker_ip = MQTT_DEMO_BROKER_IP_ADDR;
#define DEFAULT_ORG_ID "mqtt-demo"
#else
static const char *broker_ip = "0064:ff9b:0000:0000:0000:0000:b8ac:7cbd";
#define DEFAULT_ORG_ID "quickstart"
#endif
/*---------------------------------------------------------------------------*/
/*
* A timeout used when waiting for something to happen (e.g. to connect or to
* disconnect)
*/
#define STATE_MACHINE_PERIODIC (CLOCK_SECOND >> 1)
/*---------------------------------------------------------------------------*/
/* Provide visible feedback via LEDS during various states */
/* When connecting to broker */
#define CONNECTING_LED_DURATION (CLOCK_SECOND >> 2)
/* Each time we try to publish */
#define PUBLISH_LED_ON_DURATION (CLOCK_SECOND)
/*---------------------------------------------------------------------------*/
/* Connections and reconnections */
#define RETRY_FOREVER 0xFF
#define RECONNECT_INTERVAL (CLOCK_SECOND * 2)
/*
* Number of times to try reconnecting to the broker.
* Can be a limited number (e.g. 3, 10 etc) or can be set to RETRY_FOREVER
*/
#define RECONNECT_ATTEMPTS RETRY_FOREVER
#define CONNECTION_STABLE_TIME (CLOCK_SECOND * 5)
static struct timer connection_life;
static uint8_t connect_attempt;
/*---------------------------------------------------------------------------*/
/* Various states */
static uint8_t state;
#define STATE_INIT 0
#define STATE_REGISTERED 1
#define STATE_CONNECTING 2
#define STATE_CONNECTED 3
#define STATE_PUBLISHING 4
#define STATE_DISCONNECTED 5
#define STATE_NEWCONFIG 6
#define STATE_CONFIG_ERROR 0xFE
#define STATE_ERROR 0xFF
/*---------------------------------------------------------------------------*/
#define CONFIG_ORG_ID_LEN 32
#define CONFIG_TYPE_ID_LEN 32
#define CONFIG_AUTH_TOKEN_LEN 32
#define CONFIG_EVENT_TYPE_ID_LEN 32
#define CONFIG_CMD_TYPE_LEN 8
#define CONFIG_IP_ADDR_STR_LEN 64
/*---------------------------------------------------------------------------*/
#define RSSI_MEASURE_INTERVAL_MAX 86400 /* secs: 1 day */
#define RSSI_MEASURE_INTERVAL_MIN 5 /* secs */
#define PUBLISH_INTERVAL_MAX 86400 /* secs: 1 day */
#define PUBLISH_INTERVAL_MIN 5 /* secs */
/*---------------------------------------------------------------------------*/
/* A timeout used when waiting to connect to a network */
#define NET_CONNECT_PERIODIC (CLOCK_SECOND >> 2)
#define NO_NET_LED_DURATION (NET_CONNECT_PERIODIC >> 1)
/*---------------------------------------------------------------------------*/
/* Default configuration values */
#define DEFAULT_TYPE_ID "cc2538"
#define DEFAULT_AUTH_TOKEN "AUTHZ"
#define DEFAULT_EVENT_TYPE_ID "status"
#define DEFAULT_SUBSCRIBE_CMD_TYPE "+"
#define DEFAULT_BROKER_PORT 1883
#define DEFAULT_PUBLISH_INTERVAL (30 * CLOCK_SECOND)
#define DEFAULT_KEEP_ALIVE_TIMER 60
#define DEFAULT_RSSI_MEAS_INTERVAL (CLOCK_SECOND * 30)
/*---------------------------------------------------------------------------*/
/* Take a sensor reading on button press */
#define PUBLISH_TRIGGER &button_sensor
/* Payload length of ICMPv6 echo requests used to measure RSSI with def rt */
#define ECHO_REQ_PAYLOAD_LEN 20
/*---------------------------------------------------------------------------*/
PROCESS_NAME(mqtt_demo_process);
AUTOSTART_PROCESSES(&mqtt_demo_process);
/*---------------------------------------------------------------------------*/
/**
* \brief Data structure declaration for the MQTT client configuration
*/
typedef struct mqtt_client_config {
char org_id[CONFIG_ORG_ID_LEN];
char type_id[CONFIG_TYPE_ID_LEN];
char auth_token[CONFIG_AUTH_TOKEN_LEN];
char event_type_id[CONFIG_EVENT_TYPE_ID_LEN];
char broker_ip[CONFIG_IP_ADDR_STR_LEN];
char cmd_type[CONFIG_CMD_TYPE_LEN];
clock_time_t pub_interval;
int def_rt_ping_interval;
uint16_t broker_port;
} mqtt_client_config_t;
/*---------------------------------------------------------------------------*/
/* Maximum TCP segment size for outgoing segments of our socket */
#define MAX_TCP_SEGMENT_SIZE 32
/*---------------------------------------------------------------------------*/
#define STATUS_LED LEDS_GREEN
/*---------------------------------------------------------------------------*/
/*
* Buffers for Client ID and Topic.
* Make sure they are large enough to hold the entire respective string
*
* d:quickstart:status:EUI64 is 32 bytes long
* iot-2/evt/status/fmt/json is 25 bytes
* We also need space for the null termination
*/
#define BUFFER_SIZE 64
static char client_id[BUFFER_SIZE];
static char pub_topic[BUFFER_SIZE];
static char sub_topic[BUFFER_SIZE];
/*---------------------------------------------------------------------------*/
/*
* The main MQTT buffers.
* We will need to increase if we start publishing more data.
*/
#define APP_BUFFER_SIZE 512
static struct mqtt_connection conn;
static char app_buffer[APP_BUFFER_SIZE];
/*---------------------------------------------------------------------------*/
#define QUICKSTART "quickstart"
/*---------------------------------------------------------------------------*/
static struct mqtt_message *msg_ptr = 0;
static struct etimer publish_periodic_timer;
static struct ctimer ct;
static char *buf_ptr;
static uint16_t seq_nr_value = 0;
/*---------------------------------------------------------------------------*/
/* Parent RSSI functionality */
static struct uip_icmp6_echo_reply_notification echo_reply_notification;
static struct etimer echo_request_timer;
static int def_rt_rssi = 0;
/*---------------------------------------------------------------------------*/
static mqtt_client_config_t conf;
/*---------------------------------------------------------------------------*/
PROCESS(mqtt_demo_process, "MQTT Demo");
/*---------------------------------------------------------------------------*/
int
ipaddr_sprintf(char *buf, uint8_t buf_len, const uip_ipaddr_t *addr)
{
uint16_t a;
uint8_t len = 0;
int i, f;
for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) {
a = (addr->u8[i] << 8) + addr->u8[i + 1];
if(a == 0 && f >= 0) {
if(f++ == 0) {
len += snprintf(&buf[len], buf_len - len, "::");
}
} else {
if(f > 0) {
f = -1;
} else if(i > 0) {
len += snprintf(&buf[len], buf_len - len, ":");
}
len += snprintf(&buf[len], buf_len - len, "%x", a);
}
}
return len;
}
/*---------------------------------------------------------------------------*/
static void
echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data,
uint16_t datalen)
{
if(uip_ip6addr_cmp(source, uip_ds6_defrt_choose())) {
def_rt_rssi = sicslowpan_get_last_rssi();
}
}
/*---------------------------------------------------------------------------*/
static void
publish_led_off(void *d)
{
leds_off(STATUS_LED);
}
/*---------------------------------------------------------------------------*/
static void
pub_handler(const char *topic, uint16_t topic_len, const uint8_t *chunk,
uint16_t chunk_len)
{
DBG("Pub Handler: topic='%s' (len=%u), chunk_len=%u\n", topic, topic_len,
chunk_len);
/* If we don't like the length, ignore */
if(topic_len != 23 || chunk_len != 1) {
printf("Incorrect topic or chunk len. Ignored\n");
return;
}
/* If the format != json, ignore */
if(strncmp(&topic[topic_len - 4], "json", 4) != 0) {
printf("Incorrect format\n");
}
if(strncmp(&topic[10], "leds", 4) == 0) {
if(chunk[0] == '1') {
leds_on(LEDS_RED);
} else if(chunk[0] == '0') {
leds_off(LEDS_RED);
}
return;
}
}
/*---------------------------------------------------------------------------*/
static void
mqtt_event(struct mqtt_connection *m, mqtt_event_t event, void *data)
{
switch(event) {
case MQTT_EVENT_CONNECTED: {
DBG("APP - Application has a MQTT connection\n");
timer_set(&connection_life, CONNECTION_STABLE_TIME);
state = STATE_CONNECTED;
break;
}
case MQTT_EVENT_DISCONNECTED: {
DBG("APP - MQTT Disconnect. Reason %u\n", *((mqtt_event_t *)data));
state = STATE_DISCONNECTED;
process_poll(&mqtt_demo_process);
break;
}
case MQTT_EVENT_PUBLISH: {
msg_ptr = data;
/* Implement first_flag in publish message? */
if(msg_ptr->first_chunk) {
msg_ptr->first_chunk = 0;
DBG("APP - Application received a publish on topic '%s'. Payload "
"size is %i bytes. Content:\n\n",
msg_ptr->topic, msg_ptr->payload_length);
}
pub_handler(msg_ptr->topic, strlen(msg_ptr->topic), msg_ptr->payload_chunk,
msg_ptr->payload_length);
break;
}
case MQTT_EVENT_SUBACK: {
DBG("APP - Application is subscribed to topic successfully\n");
break;
}
case MQTT_EVENT_UNSUBACK: {
DBG("APP - Application is unsubscribed to topic successfully\n");
break;
}
case MQTT_EVENT_PUBACK: {
DBG("APP - Publishing complete.\n");
break;
}
default:
DBG("APP - Application got a unhandled MQTT event: %i\n", event);
break;
}
}
/*---------------------------------------------------------------------------*/
static int
construct_pub_topic(void)
{
int len = snprintf(pub_topic, BUFFER_SIZE, "iot-2/evt/%s/fmt/json",
conf.event_type_id);
/* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */
if(len < 0 || len >= BUFFER_SIZE) {
printf("Pub Topic: %d, Buffer %d\n", len, BUFFER_SIZE);
return 0;
}
return 1;
}
/*---------------------------------------------------------------------------*/
static int
construct_sub_topic(void)
{
int len = snprintf(sub_topic, BUFFER_SIZE, "iot-2/cmd/%s/fmt/json",
conf.cmd_type);
/* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */
if(len < 0 || len >= BUFFER_SIZE) {
printf("Sub Topic: %d, Buffer %d\n", len, BUFFER_SIZE);
return 0;
}
return 1;
}
/*---------------------------------------------------------------------------*/
static int
construct_client_id(void)
{
int len = snprintf(client_id, BUFFER_SIZE, "d:%s:%s:%02x%02x%02x%02x%02x%02x",
conf.org_id, conf.type_id,
linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1],
linkaddr_node_addr.u8[2], linkaddr_node_addr.u8[5],
linkaddr_node_addr.u8[6], linkaddr_node_addr.u8[7]);
/* len < 0: Error. Len >= BUFFER_SIZE: Buffer too small */
if(len < 0 || len >= BUFFER_SIZE) {
printf("Client ID: %d, Buffer %d\n", len, BUFFER_SIZE);
return 0;
}
return 1;
}
/*---------------------------------------------------------------------------*/
static void
update_config(void)
{
if(construct_client_id() == 0) {
/* Fatal error. Client ID larger than the buffer */
state = STATE_CONFIG_ERROR;
return;
}
if(construct_sub_topic() == 0) {
/* Fatal error. Topic larger than the buffer */
state = STATE_CONFIG_ERROR;
return;
}
if(construct_pub_topic() == 0) {
/* Fatal error. Topic larger than the buffer */
state = STATE_CONFIG_ERROR;
return;
}
/* Reset the counter */
seq_nr_value = 0;
state = STATE_INIT;
/*
* Schedule next timer event ASAP
*
* If we entered an error state then we won't do anything when it fires.
*
* Since the error at this stage is a config error, we will only exit this
* error state if we get a new config.
*/
etimer_set(&publish_periodic_timer, 0);
return;
}
/*---------------------------------------------------------------------------*/
static int
init_config()
{
/* Populate configuration with default values */
memset(&conf, 0, sizeof(mqtt_client_config_t));
memcpy(conf.org_id, DEFAULT_ORG_ID, strlen(DEFAULT_ORG_ID));
memcpy(conf.type_id, DEFAULT_TYPE_ID, strlen(DEFAULT_TYPE_ID));
memcpy(conf.auth_token, DEFAULT_AUTH_TOKEN, strlen(DEFAULT_AUTH_TOKEN));
memcpy(conf.event_type_id, DEFAULT_EVENT_TYPE_ID,
strlen(DEFAULT_EVENT_TYPE_ID));
memcpy(conf.broker_ip, broker_ip, strlen(broker_ip));
memcpy(conf.cmd_type, DEFAULT_SUBSCRIBE_CMD_TYPE, 1);
conf.broker_port = DEFAULT_BROKER_PORT;
conf.pub_interval = DEFAULT_PUBLISH_INTERVAL;
conf.def_rt_ping_interval = DEFAULT_RSSI_MEAS_INTERVAL;
return 1;
}
/*---------------------------------------------------------------------------*/
static void
subscribe(void)
{
/* Publish MQTT topic in IBM quickstart format */
mqtt_status_t status;
status = mqtt_subscribe(&conn, NULL, sub_topic, MQTT_QOS_LEVEL_0);
DBG("APP - Subscribing!\n");
if(status == MQTT_STATUS_OUT_QUEUE_FULL) {
DBG("APP - Tried to subscribe but command queue was full!\n");
}
}
/*---------------------------------------------------------------------------*/
static void
publish(void)
{
/* Publish MQTT topic in IBM quickstart format */
int len;
int remaining = APP_BUFFER_SIZE;
int16_t value;
seq_nr_value++;
buf_ptr = app_buffer;
len = snprintf(buf_ptr, remaining,
"{"
"\"d\":{"
"\"myName\":\"%s\","
"\"Seq #\":%d,"
"\"Uptime (sec)\":%lu",
BOARD_STRING, seq_nr_value, clock_seconds());
if(len < 0 || len >= remaining) {
printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len);
return;
}
remaining -= len;
buf_ptr += len;
/* Put our Default route's string representation in a buffer */
char def_rt_str[64];
memset(def_rt_str, 0, sizeof(def_rt_str));
ipaddr_sprintf(def_rt_str, sizeof(def_rt_str), uip_ds6_defrt_choose());
len = snprintf(buf_ptr, remaining, ",\"Def Route\":\"%s\",\"RSSI (dBm)\":%d",
def_rt_str, def_rt_rssi);
if(len < 0 || len >= remaining) {
printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len);
return;
}
remaining -= len;
buf_ptr += len;
value = adc_sensor.value(ADC_SENSOR_TEMP);
len = snprintf(buf_ptr, remaining, ",\"On-Chip Temp (mC)\":%d",
25000 + ((value >> 4) - 1422) * 10000 / 42);
if(len < 0 || len >= remaining) {
printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len);
return;
}
remaining -= len;
buf_ptr += len;
value = adc_sensor.value(ADC_SENSOR_VDD_3);
len = snprintf(buf_ptr, remaining, ",\"VDD3 (mV)\":%d",
value * (3 * 1190) / (2047 << 4));
if(len < 0 || len >= remaining) {
printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len);
return;
}
remaining -= len;
buf_ptr += len;
len = snprintf(buf_ptr, remaining, "}}");
if(len < 0 || len >= remaining) {
printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len);
return;
}
mqtt_publish(&conn, NULL, pub_topic, (uint8_t *)app_buffer,
strlen(app_buffer), MQTT_QOS_LEVEL_0, MQTT_RETAIN_OFF);
DBG("APP - Publish!\n");
}
/*---------------------------------------------------------------------------*/
static void
connect_to_broker(void)
{
/* Connect to MQTT server */
mqtt_connect(&conn, conf.broker_ip, conf.broker_port,
conf.pub_interval * 3);
state = STATE_CONNECTING;
}
/*---------------------------------------------------------------------------*/
static void
ping_parent(void)
{
if(uip_ds6_get_global(ADDR_PREFERRED) == NULL) {
return;
}
uip_icmp6_send(uip_ds6_defrt_choose(), ICMP6_ECHO_REQUEST, 0,
ECHO_REQ_PAYLOAD_LEN);
}
/*---------------------------------------------------------------------------*/
static void
state_machine(void)
{
switch(state) {
case STATE_INIT:
/* If we have just been configured register MQTT connection */
mqtt_register(&conn, &mqtt_demo_process, client_id, mqtt_event,
MAX_TCP_SEGMENT_SIZE);
/*
* If we are not using the quickstart service (thus we are an IBM
* registered device), we need to provide user name and password
*/
if(strncasecmp(conf.org_id, QUICKSTART, strlen(conf.org_id)) != 0) {
if(strlen(conf.auth_token) == 0) {
printf("User name set, but empty auth token\n");
state = STATE_ERROR;
break;
} else {
mqtt_set_username_password(&conn, "use-token-auth",
conf.auth_token);
}
}
/* _register() will set auto_reconnect. We don't want that. */
conn.auto_reconnect = 0;
connect_attempt = 1;
state = STATE_REGISTERED;
DBG("Init\n");
/* Continue */
case STATE_REGISTERED:
if(uip_ds6_get_global(ADDR_PREFERRED) != NULL) {
/* Registered and with a public IP. Connect */
DBG("Registered. Connect attempt %u\n", connect_attempt);
ping_parent();
connect_to_broker();
} else {
leds_on(STATUS_LED);
ctimer_set(&ct, NO_NET_LED_DURATION, publish_led_off, NULL);
}
etimer_set(&publish_periodic_timer, NET_CONNECT_PERIODIC);
return;
break;
case STATE_CONNECTING:
leds_on(STATUS_LED);
ctimer_set(&ct, CONNECTING_LED_DURATION, publish_led_off, NULL);
/* Not connected yet. Wait */
DBG("Connecting (%u)\n", connect_attempt);
break;
case STATE_CONNECTED:
/* Don't subscribe unless we are a registered device */
if(strncasecmp(conf.org_id, QUICKSTART, strlen(conf.org_id)) == 0) {
DBG("Using 'quickstart': Skipping subscribe\n");
state = STATE_PUBLISHING;
}
/* Continue */
case STATE_PUBLISHING:
/* If the timer expired, the connection is stable. */
if(timer_expired(&connection_life)) {
/*
* Intentionally using 0 here instead of 1: We want RECONNECT_ATTEMPTS
* attempts if we disconnect after a successful connect
*/
connect_attempt = 0;
}
if(mqtt_ready(&conn) && conn.out_buffer_sent) {
/* Connected. Publish */
if(state == STATE_CONNECTED) {
subscribe();
state = STATE_PUBLISHING;
} else {
leds_on(STATUS_LED);
ctimer_set(&ct, PUBLISH_LED_ON_DURATION, publish_led_off, NULL);
publish();
}
etimer_set(&publish_periodic_timer, conf.pub_interval);
DBG("Publishing\n");
/* Return here so we don't end up rescheduling the timer */
return;
} else {
/*
* Our publish timer fired, but some MQTT packet is already in flight
* (either not sent at all, or sent but not fully ACKd).
*
* This can mean that we have lost connectivity to our broker or that
* simply there is some network delay. In both cases, we refuse to
* trigger a new message and we wait for TCP to either ACK the entire
* packet after retries, or to timeout and notify us.
*/
DBG("Publishing... (MQTT state=%d, q=%u)\n", conn.state,
conn.out_queue_full);
}
break;
case STATE_DISCONNECTED:
DBG("Disconnected\n");
if(connect_attempt < RECONNECT_ATTEMPTS ||
RECONNECT_ATTEMPTS == RETRY_FOREVER) {
/* Disconnect and backoff */
clock_time_t interval;
mqtt_disconnect(&conn);
connect_attempt++;
interval = connect_attempt < 3 ? RECONNECT_INTERVAL << connect_attempt :
RECONNECT_INTERVAL << 3;
DBG("Disconnected. Attempt %u in %lu ticks\n", connect_attempt, interval);
etimer_set(&publish_periodic_timer, interval);
state = STATE_REGISTERED;
return;
} else {
/* Max reconnect attempts reached. Enter error state */
state = STATE_ERROR;
DBG("Aborting connection after %u attempts\n", connect_attempt - 1);
}
break;
case STATE_CONFIG_ERROR:
/* Idle away. The only way out is a new config */
printf("Bad configuration.\n");
return;
case STATE_ERROR:
default:
leds_on(STATUS_LED);
/*
* 'default' should never happen.
*
* If we enter here it's because of some error. Stop timers. The only thing
* that can bring us out is a new config event
*/
printf("Default case: State=0x%02x\n", state);
return;
}
/* If we didn't return so far, reschedule ourselves */
etimer_set(&publish_periodic_timer, STATE_MACHINE_PERIODIC);
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(mqtt_demo_process, ev, data)
{
PROCESS_BEGIN();
printf("MQTT Demo Process\n");
if(init_config() != 1) {
PROCESS_EXIT();
}
update_config();
def_rt_rssi = 0x8000000;
uip_icmp6_echo_reply_callback_add(&echo_reply_notification,
echo_reply_handler);
etimer_set(&echo_request_timer, conf.def_rt_ping_interval);
/* Main loop */
while(1) {
PROCESS_YIELD();
if(ev == sensors_event && data == PUBLISH_TRIGGER) {
if(state == STATE_ERROR) {
connect_attempt = 1;
state = STATE_REGISTERED;
}
}
if((ev == PROCESS_EVENT_TIMER && data == &publish_periodic_timer) ||
ev == PROCESS_EVENT_POLL ||
(ev == sensors_event && data == PUBLISH_TRIGGER)) {
state_machine();
}
if(ev == PROCESS_EVENT_TIMER && data == &echo_request_timer) {
ping_parent();
etimer_set(&echo_request_timer, conf.def_rt_ping_interval);
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
/**
* @}
* @}
*/

Some files were not shown because too many files have changed in this diff Show more