Merge branch 'master' of git://github.com/contiki-os/contiki into ds6_period_configurable

This commit is contained in:
Jens Dede 2014-04-18 13:33:01 +02:00
commit 446208dc1c
107 changed files with 8338 additions and 1318 deletions

3
.gitmodules vendored
View file

@ -1,3 +1,6 @@
[submodule "tools/mspsim"] [submodule "tools/mspsim"]
path = tools/mspsim path = tools/mspsim
url = https://github.com/contiki-os/mspsim.git url = https://github.com/contiki-os/mspsim.git
[submodule "tools/cc2538-bsl"]
path = tools/cc2538-bsl
url = https://github.com/JelmerT/cc2538-bsl.git

View file

@ -29,7 +29,7 @@ before_script:
## Clone and build cc65 when testing 6502 ports ## Clone and build cc65 when testing 6502 ports
- "[ ${BUILD_ARCH:-0} = 6502 ] && git clone \ - "[ ${BUILD_ARCH:-0} = 6502 ] && git clone \
https://github.com/oliverschmidt/cc65 /tmp/cc65 && \ https://github.com/cc65/cc65 /tmp/cc65 && \
make -C /tmp/cc65 bin apple2enh atarixl c64 c128 && sudo make -C /tmp/cc65 avail && \ make -C /tmp/cc65 bin apple2enh atarixl c64 c128 && sudo make -C /tmp/cc65 avail && \
export CC65_HOME=/tmp/cc65/ && cc65 --version || true" export CC65_HOME=/tmp/cc65/ && cc65 --version || true"

View file

@ -153,7 +153,7 @@ CFLAGS += ${addprefix -I,$(SOURCEDIRS) $(CONTIKI)}
### Check for a git repo and pass version if found ### Check for a git repo and pass version if found
### git.exe in Windows cmd shells may require no stderr redirection ### git.exe in Windows cmd shells may require no stderr redirection
#RELSTR=${shell git describe --tags} #RELSTR=${shell git describe --tags}
RELSTR=${shell git describe --tags 2>/dev/null} RELSTR=${shell git --git-dir ${CONTIKI}/.git describe --tags 2>/dev/null}
ifneq ($(RELSTR),) ifneq ($(RELSTR),)
CFLAGS += -DCONTIKI_VERSION_STRING=\"Contiki-$(RELSTR)\" CFLAGS += -DCONTIKI_VERSION_STRING=\"Contiki-$(RELSTR)\"
endif endif

View file

@ -116,6 +116,13 @@ struct jsontree_array {
sizeof(jsontree_pair_##name)/sizeof(struct jsontree_pair), \ sizeof(jsontree_pair_##name)/sizeof(struct jsontree_pair), \
jsontree_pair_##name } jsontree_pair_##name }
#define JSONTREE_ARRAY(name, count) \
static struct jsontree_value *jsontree_value##name[count]; \
static struct jsontree_array name = { \
JSON_TYPE_ARRAY, \
count, \
jsontree_value##name }
void jsontree_setup(struct jsontree_context *js_ctx, void jsontree_setup(struct jsontree_context *js_ctx,
struct jsontree_value *root, int (* putchar)(int)); struct jsontree_value *root, int (* putchar)(int));
void jsontree_reset(struct jsontree_context *js_ctx); void jsontree_reset(struct jsontree_context *js_ctx);

View file

@ -1155,6 +1155,7 @@ cfs_write(int fd, const void *buf, unsigned size)
int i; int i;
struct log_param lp; struct log_param lp;
cfs_offset_t bytes_left; cfs_offset_t bytes_left;
int8_t need_dummy_write;
const char dummy[1] = { 0xff }; const char dummy[1] = { 0xff };
#endif #endif
@ -1188,6 +1189,7 @@ cfs_write(int fd, const void *buf, unsigned size)
#else #else
if(FILE_MODIFIED(file) || fdp->offset < file->end) { if(FILE_MODIFIED(file) || fdp->offset < file->end) {
#endif #endif
need_dummy_write = 0;
for(bytes_left = size; bytes_left > 0;) { for(bytes_left = size; bytes_left > 0;) {
lp.offset = fdp->offset; lp.offset = fdp->offset;
lp.buf = buf; lp.buf = buf;
@ -1212,13 +1214,19 @@ cfs_write(int fd, const void *buf, unsigned size)
occur while writing log records. */ occur while writing log records. */
if(fdp->offset > file->end) { if(fdp->offset > file->end) {
file->end = fdp->offset; file->end = fdp->offset;
need_dummy_write = 1;
} }
} }
} }
if(fdp->offset > file->end) { if(need_dummy_write) {
/* Update the original file's end with a dummy write. */ /*
COFFEE_WRITE(dummy, 1, absolute_offset(file->page, fdp->offset)); * A log record has been written at an offset beyond the original
* extent's end. Consequently, we need to write a dummy value at the
* corresponding end offset in the original extent to ensure that
* the correct file size is calculated when opening the file again.
*/
COFFEE_WRITE(dummy, 1, absolute_offset(file->page, fdp->offset - 1));
} }
} else { } else {
#endif /* COFFEE_MICRO_LOGS */ #endif /* COFFEE_MICRO_LOGS */

View file

@ -54,6 +54,9 @@
#include "net/ip/psock.h" #include "net/ip/psock.h"
#include "net/ip/udp-socket.h"
#include "net/ip/tcp-socket.h"
#include "net/rime/rime.h" #include "net/rime/rime.h"
#include "net/netstack.h" #include "net/netstack.h"

View file

@ -82,10 +82,11 @@ void spi_init(void);
} while(0) } while(0)
/* Flush the SPI read register */ /* Flush the SPI read register */
#ifndef SPI_FLUSH
#define SPI_FLUSH() \ #define SPI_FLUSH() \
do { \ do { \
SPI_RXBUF; \ SPI_RXBUF; \
} while(0); } while(0);
#endif
#endif /* SPI_H_ */ #endif /* SPI_H_ */

365
core/net/ip/tcp-socket.c Normal file
View file

@ -0,0 +1,365 @@
/*
* Copyright (c) 2012-2014, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "contiki.h"
#include "contiki-net.h"
#include "lib/list.h"
#include "tcp-socket.h"
#include <stdio.h>
#include <string.h>
#define MIN(a, b) ((a) < (b) ? (a) : (b))
LIST(socketlist);
/*---------------------------------------------------------------------------*/
PROCESS(tcp_socket_process, "TCP socket process");
/*---------------------------------------------------------------------------*/
static void
call_event(struct tcp_socket *s, tcp_socket_event_t event)
{
if(s != NULL && s->event_callback != NULL) {
s->event_callback(s, s->ptr, event);
}
}
/*---------------------------------------------------------------------------*/
static void
senddata(struct tcp_socket *s)
{
int len;
if(s->output_data_len > 0) {
len = MIN(s->output_data_len, uip_mss());
s->output_data_send_nxt = len;
uip_send(s->output_data_ptr, len);
}
}
/*---------------------------------------------------------------------------*/
static void
acked(struct tcp_socket *s)
{
if(s->output_data_len > 0) {
/* Copy the data in the outputbuf down and update outputbufptr and
outputbuf_lastsent */
if(s->output_data_send_nxt > 0) {
memcpy(&s->output_data_ptr[0],
&s->output_data_ptr[s->output_data_send_nxt],
s->output_data_maxlen - s->output_data_send_nxt);
}
if(s->output_data_len < s->output_data_send_nxt) {
printf("tcp: acked assertion failed s->output_data_len (%d) < s->output_data_send_nxt (%d)\n",
s->output_data_len,
s->output_data_send_nxt);
}
s->output_data_len -= s->output_data_send_nxt;
s->output_data_send_nxt = 0;
call_event(s, TCP_SOCKET_DATA_SENT);
}
}
/*---------------------------------------------------------------------------*/
static void
newdata(struct tcp_socket *s)
{
uint16_t len, copylen, bytesleft;
uint8_t *dataptr;
len = uip_datalen();
dataptr = uip_appdata;
/* We have a segment with data coming in. We copy as much data as
possible into the input buffer and call the input callback
function. The input callback returns the number of bytes that
should be retained in the buffer, or zero if all data should be
consumed. If there is data to be retained, the highest bytes of
data are copied down into the input buffer. */
do {
copylen = MIN(len, s->input_data_maxlen);
memcpy(s->input_data_ptr, dataptr, copylen);
if(s->input_callback) {
bytesleft = s->input_callback(s, s->ptr,
s->input_data_ptr, copylen);
} else {
bytesleft = 0;
}
if(bytesleft > 0) {
printf("tcp: newdata, bytesleft > 0 (%d) not implemented\n", bytesleft);
}
dataptr += copylen;
len -= copylen;
} while(len > 0);
}
/*---------------------------------------------------------------------------*/
static void
relisten(struct tcp_socket *s)
{
if(s != NULL && s->listen_port != 0) {
s->flags |= TCP_SOCKET_FLAGS_LISTENING;
}
}
/*---------------------------------------------------------------------------*/
static void
appcall(void *state)
{
struct tcp_socket *s = state;
if(uip_connected()) {
/* Check if this connection originated in a local listen
socket. We do this by checking the state pointer - if NULL,
this is an incoming listen connection. If so, we need to
connect the socket to the uip_conn and call the event
function. */
if(s == NULL) {
for(s = list_head(socketlist);
s != NULL;
s = list_item_next(s)) {
if((s->flags & TCP_SOCKET_FLAGS_LISTENING) != 0 &&
s->listen_port != 0 &&
s->listen_port == uip_htons(uip_conn->lport)) {
s->flags &= ~TCP_SOCKET_FLAGS_LISTENING;
tcp_markconn(uip_conn, s);
call_event(s, TCP_SOCKET_CONNECTED);
break;
}
}
} else {
call_event(s, TCP_SOCKET_CONNECTED);
}
if(s == NULL) {
uip_abort();
} else {
if(uip_newdata()) {
newdata(s);
}
senddata(s);
}
return;
}
if(uip_timedout()) {
call_event(s, TCP_SOCKET_TIMEDOUT);
relisten(s);
}
if(uip_aborted()) {
call_event(s, TCP_SOCKET_ABORTED);
relisten(s);
}
if(s == NULL) {
uip_abort();
return;
}
if(uip_acked()) {
acked(s);
}
if(uip_newdata()) {
newdata(s);
}
if(uip_rexmit() ||
uip_newdata() ||
uip_acked()) {
senddata(s);
} else if(uip_poll()) {
senddata(s);
}
if(s->output_data_len == 0 && s->flags & TCP_SOCKET_FLAGS_CLOSING) {
s->flags &= ~TCP_SOCKET_FLAGS_CLOSING;
uip_close();
tcp_markconn(uip_conn, NULL);
call_event(s, TCP_SOCKET_CLOSED);
relisten(s);
}
if(uip_closed()) {
tcp_markconn(uip_conn, NULL);
call_event(s, TCP_SOCKET_CLOSED);
relisten(s);
}
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(tcp_socket_process, ev, data)
{
PROCESS_BEGIN();
while(1) {
PROCESS_WAIT_EVENT();
if(ev == tcpip_event) {
appcall(data);
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
static void
init(void)
{
static uint8_t inited = 0;
if(!inited) {
list_init(socketlist);
process_start(&tcp_socket_process, NULL);
inited = 1;
}
}
/*---------------------------------------------------------------------------*/
int
tcp_socket_register(struct tcp_socket *s, void *ptr,
uint8_t *input_databuf, int input_databuf_len,
uint8_t *output_databuf, int output_databuf_len,
tcp_socket_data_callback_t input_callback,
tcp_socket_event_callback_t event_callback)
{
init();
if(s == NULL) {
return -1;
}
s->ptr = ptr;
s->input_data_ptr = input_databuf;
s->input_data_maxlen = input_databuf_len;
s->output_data_ptr = output_databuf;
s->output_data_maxlen = output_databuf_len;
s->input_callback = input_callback;
s->event_callback = event_callback;
list_add(socketlist, s);
s->listen_port = 0;
s->flags = TCP_SOCKET_FLAGS_NONE;
return 1;
}
/*---------------------------------------------------------------------------*/
int
tcp_socket_connect(struct tcp_socket *s,
uip_ipaddr_t *ipaddr,
uint16_t port)
{
if(s == NULL) {
return -1;
}
PROCESS_CONTEXT_BEGIN(&tcp_socket_process);
s->c = tcp_connect(ipaddr, uip_htons(port), s);
PROCESS_CONTEXT_END();
if(s->c == NULL) {
return -1;
} else {
return 1;
}
}
/*---------------------------------------------------------------------------*/
int
tcp_socket_listen(struct tcp_socket *s,
uint16_t port)
{
if(s == NULL) {
return -1;
}
s->listen_port = port;
PROCESS_CONTEXT_BEGIN(&tcp_socket_process);
tcp_listen(uip_htons(port));
PROCESS_CONTEXT_END();
s->flags |= TCP_SOCKET_FLAGS_LISTENING;
return 1;
}
/*---------------------------------------------------------------------------*/
int
tcp_socket_unlisten(struct tcp_socket *s)
{
if(s == NULL) {
return -1;
}
PROCESS_CONTEXT_BEGIN(&tcp_socket_process);
tcp_unlisten(uip_htons(s->listen_port));
PROCESS_CONTEXT_END();
s->listen_port = 0;
s->flags &= ~TCP_SOCKET_FLAGS_LISTENING;
return 1;
}
/*---------------------------------------------------------------------------*/
int
tcp_socket_send(struct tcp_socket *s,
const uint8_t *data, int datalen)
{
int len;
if(s == NULL) {
return -1;
}
len = MIN(datalen, s->output_data_maxlen - s->output_data_len);
memcpy(&s->output_data_ptr[s->output_data_len], data, len);
s->output_data_len += len;
return len;
}
/*---------------------------------------------------------------------------*/
int
tcp_socket_send_str(struct tcp_socket *s,
const char *str)
{
return tcp_socket_send(s, (const uint8_t *)str, strlen(str));
}
/*---------------------------------------------------------------------------*/
int
tcp_socket_close(struct tcp_socket *s)
{
if(s == NULL) {
return -1;
}
s->flags |= TCP_SOCKET_FLAGS_CLOSING;
return 1;
}
/*---------------------------------------------------------------------------*/
int
tcp_socket_unregister(struct tcp_socket *s)
{
if(s == NULL) {
return -1;
}
tcp_socket_unlisten(s);
if(s->c != NULL) {
tcp_attach(s->c, NULL);
}
list_remove(socketlist, s);
return 1;
}
/*---------------------------------------------------------------------------*/

268
core/net/ip/tcp-socket.h Normal file
View file

@ -0,0 +1,268 @@
/*
* Copyright (c) 2012-2014, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TCP_SOCKET_H
#define TCP_SOCKET_H
struct tcp_socket;
typedef enum {
TCP_SOCKET_CONNECTED,
TCP_SOCKET_CLOSED,
TCP_SOCKET_TIMEDOUT,
TCP_SOCKET_ABORTED,
TCP_SOCKET_DATA_SENT
} tcp_socket_event_t;
/**
* \brief TCP data callback function
* \param s A pointer to a TCP socket
* \param ptr A user-defined pointer
* \param input_data_ptr A pointer to the incoming data
* \param input_data_len The length of the incoming data
* \return The function should return the number of bytes to leave in the input buffer
*
* The TCP socket input callback function gets
* called whenever there is new data on the socket. The
* function can choose to either consume the data
* directly, or leave it in the buffer for later. The
* function must return the amount of data to leave in the
* buffer. I.e., if the callback function consumes all
* incoming data, it should return 0.
*/
typedef int (* tcp_socket_data_callback_t)(struct tcp_socket *s,
void *ptr,
const uint8_t *input_data_ptr,
int input_data_len);
/**
* \brief TCP event callback function
* \param s A pointer to a TCP socket
* \param ptr A user-defined pointer
* \param event The event number
*
* The TCP socket event callback function gets
* called whenever there is an event on a socket, such as
* the socket getting connected or closed.
*/
typedef void (* tcp_socket_event_callback_t)(struct tcp_socket *s,
void *ptr,
tcp_socket_event_t event);
struct tcp_socket {
struct tcp_socket *next;
tcp_socket_data_callback_t input_callback;
tcp_socket_event_callback_t event_callback;
void *ptr;
struct process *p;
uint8_t *input_data_ptr;
uint8_t *output_data_ptr;
uint16_t input_data_maxlen;
uint16_t input_data_len;
uint16_t output_data_maxlen;
uint16_t output_data_len;
uint16_t output_data_send_nxt;
uint8_t flags;
uint16_t listen_port;
struct uip_conn *c;
};
enum {
TCP_SOCKET_FLAGS_NONE = 0x00,
TCP_SOCKET_FLAGS_LISTENING = 0x01,
TCP_SOCKET_FLAGS_CLOSING = 0x02,
};
/**
* \brief Register a TCP socket
* \param s A pointer to a TCP socket
* \param ptr A user-defined pointer that will be sent to callbacks for this socket
* \param input_databuf A pointer to a memory area this socket will use for input data
* \param input_databuf_len The size of the input data buffer
* \param output_databuf A pointer to a memory area this socket will use for outgoing data
* \param output_databuf_len The size of the output data buffer
* \param data_callback A pointer to the data callback function for this socket
* \param event_callback A pointer to the event callback function for this socket
* \retval -1 If an error occurs
* \retval 1 If the operation succeeds.
*
* This function registers a TCP socket. The function sets
* up the output and input buffers for the socket and
* callback pointers.
*
* TCP sockets use input and output buffers for incoming
* and outgoing data. The memory for these buffers must be
* allocated by the caller. The size of the buffers
* determine the amount of data that can be received and
* sent, and the principle is that the application that
* sets up the TCP socket will know roughly how large
* these buffers should be. The rule of thumb is that the
* input buffer should be large enough to hold the largest
* application layer message that the application will
* receive and the output buffer should be large enough to
* hold the largest application layer message the
* application will send.
*
* TCP throttles incoming data so that if the input buffer
* is filled, the connection will halt until the
* application has read out the data from the input
* buffer.
*
*/
int tcp_socket_register(struct tcp_socket *s, void *ptr,
uint8_t *input_databuf, int input_databuf_len,
uint8_t *output_databuf, int output_databuf_len,
tcp_socket_data_callback_t data_callback,
tcp_socket_event_callback_t event_callback);
/**
* \brief Connect a TCP socket to a remote host
* \param s A pointer to a TCP socket that must have been previously registered with tcp_socket_register()
* \param ipaddr The IP address of the remote host
* \param port The TCP port number, in host byte order, of the remote host
* \retval -1 If an error occurs
* \retval 1 If the operation succeeds.
*
* This function connects a TCP socket to a remote host.
*
* When the socket has connected, the event callback will
* get called with the TCP_SOCKET_CONNECTED event. If the
* remote host does not accept the connection, the
* TCP_SOCKET_ABORTED will be sent to the callback. If the
* connection times out before conecting to the remote
* host, the TCP_SOCKET_TIMEDOUT event is sent to the
* callback.
*
*/
int tcp_socket_connect(struct tcp_socket *s,
uip_ipaddr_t *ipaddr,
uint16_t port);
/**
* \brief Start listening on a specific port
* \param s A pointer to a TCP socket that must have been previously registered with tcp_socket_register()
* \param port The TCP port number, in host byte order, of the remote host
* \retval -1 If an error occurs
* \retval 1 If the operation succeeds.
*
* This function causes the TCP socket to start listening
* on the given TCP port.
*
* Several sockets can listen on the same port. If a
* remote host connects to the port, one of the listening
* sockets will get connected and the event callback will
* be called with the TCP_SOCKET_CONNECTED event. When the
* connection closes, the socket will go back to listening
* for new connections.
*
*/
int tcp_socket_listen(struct tcp_socket *s,
uint16_t port);
/**
* \brief Stop listening for new connections
* \param s A pointer to a TCP socket that must have been previously registered with tcp_socket_register()
* \retval -1 If an error occurs
* \retval 1 If the operation succeeds.
*
* This function causes a listening TCP socket to stop
* listen. The socket must previously been put into listen
* mode with tcp_socket_listen().
*
*/
int tcp_socket_unlisten(struct tcp_socket *s);
/**
* \brief Send data on a connected TCP socket
* \param s A pointer to a TCP socket that must have been previously registered with tcp_socket_register()
* \param dataptr A pointer to the data to be sent
* \param datalen The length of the data to be sent
* \retval -1 If an error occurs
* \return The number of bytes that were successfully sent
*
* This function sends data over a connected TCP
* socket. The data is placed in the output buffer and
* sent to the remote host as soon as possiblce. When the
* data has been acknowledged by the remote host, the
* event callback is sent with the TCP_SOCKET_DATA_SENT
* event.
*/
int tcp_socket_send(struct tcp_socket *s,
const uint8_t *dataptr,
int datalen);
/**
* \brief Send a string on a connected TCP socket
* \param s A pointer to a TCP socket that must have been previously registered with tcp_socket_register()
* \param strptr A pointer to the string to be sent
* \retval -1 If an error occurs
* \return The number of bytes that were successfully sent
*
* This is a convenience function for sending strings on a
* TCP socket. The function calls tcp_socket_send() to
* send the string.
*/
int tcp_socket_send_str(struct tcp_socket *s,
const char *strptr);
/**
* \brief Close a connected TCP socket
* \param s A pointer to a TCP socket that must have been previously registered with tcp_socket_register()
* \retval -1 If an error occurs
* \retval 1 If the operation succeeds.
*
* This function closes a connected TCP socket. When the
* socket has been successfully closed, the event callback
* is called with the TCP_SOCKET_CLOSED event.
*
*/
int tcp_socket_close(struct tcp_socket *s);
/**
* \brief Unregister a registered socket
* \param s A pointer to a TCP socket that must have been previously registered with tcp_socket_register()
* \retval -1 If an error occurs
* \retval 1 If the operation succeeds.
*
* This function unregisters a previously registered
* socket. This must be done if the process will be
* unloaded from memory. If the TCP socket is connected,
* the connection will be reset.
*
*/
int tcp_socket_unregister(struct tcp_socket *s);
#endif /* TCP_SOCKET_H */

199
core/net/ip/udp-socket.c Normal file
View file

@ -0,0 +1,199 @@
/*
* Copyright (c) 2012-2014, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "contiki-net.h"
#include "udp-socket.h"
#include <string.h>
PROCESS(udp_socket_process, "UDP socket process");
static uint8_t buf[UIP_BUFSIZE];
#define UIP_IP_BUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
/*---------------------------------------------------------------------------*/
static void
init(void)
{
static uint8_t inited = 0;
if(!inited) {
inited = 1;
process_start(&udp_socket_process, NULL);
}
}
/*---------------------------------------------------------------------------*/
int
udp_socket_register(struct udp_socket *c,
void *ptr,
udp_socket_input_callback_t input_callback)
{
init();
if(c == NULL) {
return -1;
}
c->ptr = ptr;
c->input_callback = input_callback;
c->p = PROCESS_CURRENT();
PROCESS_CONTEXT_BEGIN(&udp_socket_process);
c->udp_conn = udp_new(NULL, 0, c);
PROCESS_CONTEXT_END();
if(c->udp_conn == NULL) {
return -1;
}
return 1;
}
/*---------------------------------------------------------------------------*/
int
udp_socket_close(struct udp_socket *c)
{
if(c == NULL) {
return -1;
}
if(c->udp_conn != NULL) {
uip_udp_remove(c->udp_conn);
return 1;
}
return -1;
}
/*---------------------------------------------------------------------------*/
int
udp_socket_bind(struct udp_socket *c,
uint16_t local_port)
{
if(c == NULL || c->udp_conn == NULL) {
return -1;
}
udp_bind(c->udp_conn, UIP_HTONS(local_port));
return 1;
}
/*---------------------------------------------------------------------------*/
int
udp_socket_connect(struct udp_socket *c,
uip_ipaddr_t *remote_addr,
uint16_t remote_port)
{
if(c == NULL || c->udp_conn == NULL) {
return -1;
}
if(remote_addr != NULL) {
uip_ipaddr_copy(&c->udp_conn->ripaddr, remote_addr);
}
c->udp_conn->rport = UIP_HTONS(remote_port);
return 1;
}
/*---------------------------------------------------------------------------*/
int
udp_socket_send(struct udp_socket *c,
const void *data, uint16_t datalen)
{
if(c == NULL || c->udp_conn == NULL) {
return -1;
}
uip_udp_packet_send(c->udp_conn, data, datalen);
return datalen;
}
/*---------------------------------------------------------------------------*/
int
udp_socket_sendto(struct udp_socket *c,
const void *data, uint16_t datalen,
const uip_ipaddr_t *to,
uint16_t port)
{
if(c == NULL || c->udp_conn == NULL) {
return -1;
}
if(c->udp_conn != NULL) {
uip_udp_packet_sendto(c->udp_conn, data, datalen,
to, UIP_HTONS(port));
return datalen;
}
return -1;
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(udp_socket_process, ev, data)
{
struct udp_socket *c;
PROCESS_BEGIN();
while(1) {
PROCESS_WAIT_EVENT();
if(ev == tcpip_event) {
/* An appstate pointer is passed to use from the IP stack
through the 'data' pointer. We registered this appstate when
we did the udp_new() call in udp_socket_register() as the
struct udp_socket pointer. So we extract this
pointer and use it when calling the reception callback. */
c = (struct udp_socket *)data;
/* Defensive coding: although the appstate *should* be non-null
here, we make sure to avoid the program crashing on us. */
if(c != NULL) {
/* If we were called because of incoming data, we should call
the reception callback. */
if(uip_newdata()) {
/* Copy the data from the uIP data buffer into our own
buffer to avoid the uIP buffer being messed with by the
callee. */
memcpy(buf, uip_appdata, uip_datalen());
/* Call the client process. We use the PROCESS_CONTEXT
mechanism to temporarily switch process context to the
client process. */
if(c->input_callback != NULL) {
PROCESS_CONTEXT_BEGIN(c->p);
c->input_callback(c, c->ptr,
&(UIP_IP_BUF->srcipaddr),
UIP_HTONS(UIP_IP_BUF->srcport),
&(UIP_IP_BUF->destipaddr),
UIP_HTONS(UIP_IP_BUF->destport),
buf, uip_datalen());
PROCESS_CONTEXT_END();
}
}
}
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/
/** @} */

193
core/net/ip/udp-socket.h Normal file
View file

@ -0,0 +1,193 @@
/*
* Copyright (c) 2012-2014, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef UDP_SOCKET_H
#define UDP_SOCKET_H
#include "net/ip/uip.h"
struct udp_socket;
/**
* \brief A UDP socket callback function
* \param c A pointer to the struct udp_socket that received the data
* \param ptr An opaque pointer that was specified when the UDP socket was registered with udp_socket_register()
* \param source_addr The IP address from which the datagram was sent
* \param source_port The UDP port number, in host byte order, from which the datagram was sent
* \param dest_addr The IP address that this datagram was sent to
* \param dest_port The UDP port number, in host byte order, that the datagram was sent to
* \param data A pointer to the data contents of the UDP datagram
* \param datalen The length of the data being pointed to by the data pointer
*
* Each UDP socket has a callback function that is
* registered as part of the call to
* udp_socket_register(). The callback function gets
* called every time a UDP packet is received.
*/
typedef void (* udp_socket_input_callback_t)(struct udp_socket *c,
void *ptr,
const uip_ipaddr_t *source_addr,
uint16_t source_port,
const uip_ipaddr_t *dest_addr,
uint16_t dest_port,
const uint8_t *data,
uint16_t datalen);
struct udp_socket {
udp_socket_input_callback_t input_callback;
void *ptr;
struct process *p;
struct uip_udp_conn *udp_conn;
};
/**
* \brief Register a UDP socket
* \param c A pointer to the struct udp_socket that should be registered
* \param ptr An opaque pointer that will be passed to callbacks
* \param receive_callback A function pointer to the callback function that will be called when data arrives
* \retval -1 The registration failed
* \retval 1 The registration succeeded
*
* This function registers the UDP socket with the
* system. A UDP socket must be registered before any data
* can be sent or received over the socket.
*
* The caller must allocate memory for the struct
* udp_socket that is to be registered.
*
* A UDP socket can begin to receive data by calling
* udp_socket_bind().
*
*/
int udp_socket_register(struct udp_socket *c,
void *ptr,
udp_socket_input_callback_t receive_callback);
/**
* \brief Bind a UDP socket to a local port
* \param c A pointer to the struct udp_socket that should be bound to a local port
* \param local_port The UDP port number, in host byte order, to bind the UDP socket to
* \retval -1 Binding the UDP socket to the local port failed
* \retval 1 Binding the UDP socket to the local port succeeded
*
* This function binds the UDP socket to a local port so
* that it will begin to receive data that arrives on the
* specified port. A UDP socket will receive data
* addressed to the specified port number on any IP
* address of the host.
*
* A UDP socket that is bound to a local port will use
* this port number as a source port in outgoing UDP
* messages.
*
*/
int udp_socket_bind(struct udp_socket *c,
uint16_t local_port);
/**
* \brief Bind a UDP socket to a remote address and port
* \param c A pointer to the struct udp_socket that should be connected
* \param remote_addr The IP address of the remote host, or NULL if the UDP socket should only be connected to a specific port
* \param remote_port The UDP port number, in host byte order, to which the UDP socket should be connected
* \retval -1 Connecting the UDP socket failed
* \retval 1 Connecting the UDP socket succeeded
*
* This function connects the UDP socket to a specific
* remote port and optional remote IP address. When a UDP
* socket is connected to a remote port and address, it
* will only receive packets that are sent from the remote
* port and address. When sending data over a connected
* UDP socket, the data will be sent to the connected
* remote address.
*
* A UDP socket can be connected to a remote port, but not
* a remote IP address, by providing a NULL parameter as
* the remote_addr parameter. This lets the UDP socket
* receive data from any IP address on the specified port.
*
*/
int udp_socket_connect(struct udp_socket *c,
uip_ipaddr_t *remote_addr,
uint16_t remote_port);
/**
* \brief Send data on a UDP socket
* \param c A pointer to the struct udp_socket on which the data should be sent
* \param data A pointer to the data that should be sent
* \param datalen The length of the data to be sent
* \return The number of bytes sent, or -1 if an error occurred
*
* This function sends data over a UDP socket. The UDP
* socket must have been connected to a remote address and
* port with udp_socket_connect().
*
*/
int udp_socket_send(struct udp_socket *c,
const void *data, uint16_t datalen);
/**
* \brief Send data on a UDP socket to a specific address and port
* \param c A pointer to the struct udp_socket on which the data should be sent
* \param data A pointer to the data that should be sent
* \param datalen The length of the data to be sent
* \param addr The IP address to which the data should be sent
* \param port The UDP port number, in host byte order, to which the data should be sent
* \return The number of bytes sent, or -1 if an error occurred
*
* This function sends data over a UDP socket to a
* specific address and port.
*
* The UDP socket does not have to be connected to use
* this function.
*
*/
int udp_socket_sendto(struct udp_socket *c,
const void *data, uint16_t datalen,
const uip_ipaddr_t *addr, uint16_t port);
/**
* \brief Close a UDP socket
* \param c A pointer to the struct udp_socket to be closed
* \retval -1 If closing the UDP socket failed
* \retval 1 If closing the UDP socket succeeded
*
* This function closes a UDP socket that has previously
* been registered with udp_socket_register(). All
* registered UDP sockets must be closed before exiting
* the process that registered them, or undefined behavior
* may occur.
*
*/
int udp_socket_close(struct udp_socket *c);
#endif /* UDP_SOCKET_H */

View file

@ -42,6 +42,7 @@
extern uint16_t uip_slen; extern uint16_t uip_slen;
#include "net/ip/uip-udp-packet.h" #include "net/ip/uip-udp-packet.h"
#include "net/ipv6/multicast/uip-mcast6.h"
#include <string.h> #include <string.h>
@ -57,6 +58,14 @@ uip_udp_packet_send(struct uip_udp_conn *c, const void *data, int len)
len > UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN? len > UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN?
UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN: len); UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN: len);
uip_process(UIP_UDP_SEND_CONN); uip_process(UIP_UDP_SEND_CONN);
#if UIP_CONF_IPV6_MULTICAST
/* Let the multicast engine process the datagram before we send it */
if(uip_is_addr_mcast_routable(&uip_udp_conn->ripaddr)) {
UIP_MCAST6.out();
}
#endif /* UIP_IPV6_MULTICAST */
#if UIP_CONF_IPV6 #if UIP_CONF_IPV6
tcpip_ipv6_output(); tcpip_ipv6_output();
#else #else

View file

@ -2093,6 +2093,35 @@ CCIF extern uip_lladdr_t uip_lladdr;
#define uip_is_addr_mcast(a) \ #define uip_is_addr_mcast(a) \
(((a)->u8[0]) == 0xFF) (((a)->u8[0]) == 0xFF)
/**
* \brief is address a global multicast address (FFxE::/16),
* a is of type uip_ip6addr_t*
* */
#define uip_is_addr_mcast_global(a) \
((((a)->u8[0]) == 0xFF) && \
(((a)->u8[1] & 0x0F) == 0x0E))
/**
* \brief is address a non-routable multicast address.
* Scopes 1 (interface-local) and 2 (link-local) are non-routable
* See RFC4291 and draft-ietf-6man-multicast-scopes
* a is of type uip_ip6addr_t*
* */
#define uip_is_addr_mcast_non_routable(a) \
((((a)->u8[0]) == 0xFF) && \
(((a)->u8[1] & 0x0F) <= 0x02))
/**
* \brief is address a routable multicast address.
* Scope 3 (Realm-Local) or higher are routable
* Realm-Local scope is defined in draft-ietf-6man-multicast-scopes
* See RFC4291 and draft-ietf-6man-multicast-scopes
* a is of type uip_ip6addr_t*
* */
#define uip_is_addr_mcast_routable(a) \
((((a)->u8[0]) == 0xFF) && \
(((a)->u8[1] & 0x0F) > 0x02))
/** /**
* \brief is group-id of multicast address a * \brief is group-id of multicast address a
* the all nodes group-id * the all nodes group-id

View file

@ -0,0 +1,114 @@
README file for Contiki's IPv6 multicast core
Author: George Oikonomou
What does it do
===============
These files, alongside some core modifications, add support for IPv6 multicast
to contiki's uIPv6 engine.
Currently, two modes are supported:
* 'Stateless Multicast RPL Forwarding' (SMRF)
RPL in MOP 3 handles group management as per the RPL docs,
SMRF is a lightweight engine which handles datagram forwarding.
SMRF is documented here:
http://dx.doi.org/10.1007/s11277-013-1250-5
and here:
http://dx.doi.org/10.1109/PerComW.2012.6197494
* 'Multicast Forwarding with Trickle' according to the algorithm described
in the internet draft:
http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast
The version of this draft that's currently implementated is documented
in `roll-tm.h`
More engines can (and hopefully will) be added in the future. The first
addition is most likely going to be an updated implementation of MPL
The Big Gotcha
==============
Currently we only support traffic originating and destined inside a single 6LoWPAN
To be able to send multicast traffic from the internet to 6LoWPAN nodes or the other
way round, we need border routers or other gateway devices to be able to achieve
the following:
* Add/Remove Trickle Multicast, RPL or other HBHO headers as necessary for datagrams
entering / exiting the 6LoWPAN
* Advertise multicast group membership to the internet (e.g. with MLD)
These are currently not implemented and are in the ToDo list. Contributions welcome.
Where to Start
==============
The best place in `examples/ipv6/multicast`
There is a cooja example demonstrating basic functionality
How to Use
==========
Look in `core/net/ipv6/multicast/uip-mcast6-engines.h` for a list of supported
multicast engines.
To turn on multicast support, add this line in your `project-` or `contiki-conf.h`
#define UIP_MCAST6_CONF_ENGINE xyz
where xyz is a value from `uip-mcast6-engines.h`
To disable:
#define UIP_MCAST6_CONF_ENGINE 0
You also need to make sure the multicast code gets built. Your example's
(or platform's) Makefile should include this:
MODULES += core/net/ipv6/multicast
How to extend
=============
Let's assume you want to write an engine called foo.
The multicast API defines a multicast engine driver in a fashion similar to
the various NETSTACK layer drivers. This API defines functions for basic
multicast operations (init, in, out).
In order to extend multicast with a new engine, perform the following steps:
- Open `uip-mcast6-engines.h` and assign a unique integer code to your engine
#define UIP_MCAST6_ENGINE_FOO xyz
- Include your engine's `foo.h`
- In `foo.c`, implement:
* `init()`
* `in()`
* `out()`
* Define your driver like so:
`const struct uip_mcast6_driver foo_driver = { ... }`
- If you want to maintain stats:
* Standard multicast stats are maintained in `uip_mcast6_stats`. Don't access
this struct directly, use the macros provided in `uip-mcast6-stats.h` instead
* You can add your own stats extensions. To do so, declare your own stats
struct in your engine's module, e.g `struct foo_stats`
* When you initialise the stats module with `UIP_MCAST6_STATS_INIT`, pass
a pointer to your stats variable as the macro's argument.
An example of how to extend multicast stats, look at the ROLL TM engine
- Open `uip-mcast6.h` and add a section in the `#if` spree. This aims to
configure the uIPv6 core. More specifically, you need to:
* Specify if you want to put RPL in MOP3 by defining
`RPL_CONF_MULTICAST`: 1: MOP 3, 0: non-multicast MOP
* Define your engine details
#define UIP_MCAST6 foo_driver
#define UIP_MCAST6_STATS foo_stats
typedef struct foo_stats uip_mcast6_stats_t;
* Optionally, add a configuration check block to stop builds when the
configuration is not sane.
If you need your engine to perform operations not supported by the generic
UIP_MCAST6 API, you will have to hook those in the uip core manually. As an
example, see how the core is modified so that it can deliver ICMPv6 datagrams
to the ROLL TM engine.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,224 @@
/*
* Copyright (c) 2011, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* Header file for 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.
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#ifndef ROLL_TM_H_
#define ROLL_TM_H_
#include "contiki-conf.h"
#include "net/ipv6/multicast/uip-mcast6-stats.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
/* Protocol Constants */
/*---------------------------------------------------------------------------*/
#define ROLL_TM_VER 1 /* Supported Draft Version */
#define ROLL_TM_ICMP_CODE 0 /* ICMPv6 code field */
#define ROLL_TM_IP_HOP_LIMIT 0xFF /* Hop limit for ICMP messages */
#define ROLL_TM_INFINITE_REDUNDANCY 0xFF
#define ROLL_TM_DGRAM_OUT 0
#define ROLL_TM_DGRAM_IN 1
/*
* The draft does not currently specify a default number for the trickle
* interval nor a way to derive it. Examples however hint at 100 msec.
*
* In draft terminology, we use an 'aggressive' policy (M=0) and a conservative
* one (M=1).
*
* When experimenting with the two policies on the sky platform,
* an interval of 125ms proves to be way too low: When we have traffic,
* doublings happen after the interval end and periodics fire after point T
* within the interval (and sometimes even after interval end). When traffic
* settles down, the code compensates the offsets.
*
* We consider 125, 250ms etc because they are nice divisors of 1 sec
* (quotient is power of two). For some machines (e.g sky/msp430,
* sensinode/cc243x), this is also a nice number of clock ticks
*
* After experimentation, the values of Imin leading to best performance are:
* ContikiMAC: Imin=64 (500ms)
* Null RDC: imin=16 (125ms)
*/
/* Configuration for Timer with M=0 (aggressive) */
#ifdef ROLL_TM_CONF_IMIN_0
#define ROLL_TM_IMIN_0 ROLL_TM_CONF_IMIN_0
#else
#define ROLL_TM_IMIN_0 32 /* 250 msec */
#endif
#ifdef ROLL_TM_CONF_IMAX_0
#define ROLL_TM_IMAX_0 ROLL_TM_CONF_IMAX_0
#else
#define ROLL_TM_IMAX_0 1 /* Imax = 500ms */
#endif
#ifdef ROLL_TM_CONF_K_0
#define ROLL_TM_K_0 ROLL_TM_CONF_K_0
#else
#define ROLL_TM_K_0 ROLL_TM_INFINITE_REDUNDANCY
#endif
#ifdef ROLL_TM_CONF_T_ACTIVE_0
#define ROLL_TM_T_ACTIVE_0 ROLL_TM_CONF_T_ACTIVE_0
#else
#define ROLL_TM_T_ACTIVE_0 3
#endif
#ifdef ROLL_TM_CONF_T_DWELL_0
#define ROLL_TM_T_DWELL_0 ROLL_TM_CONF_T_DWELL_0
#else
#define ROLL_TM_T_DWELL_0 11
#endif
/* Configuration for Timer with M=1 (conservative) */
#ifdef ROLL_TM_CONF_IMIN_1
#define ROLL_TM_IMIN_1 ROLL_TM_CONF_IMIN_1
#else
#define ROLL_TM_IMIN_1 64 /* 500 msec */
#endif
#ifdef ROLL_TM_CONF_IMAX_1
#define ROLL_TM_IMAX_1 ROLL_TM_CONF_IMAX_1
#else
#define ROLL_TM_IMAX_1 9 /* Imax = 256 secs */
#endif
#ifdef ROLL_TM_CONF_K_1
#define ROLL_TM_K_1 ROLL_TM_CONF_K_1
#else
#define ROLL_TM_K_1 1
#endif
#ifdef ROLL_TM_CONF_T_ACTIVE_1
#define ROLL_TM_T_ACTIVE_1 ROLL_TM_CONF_T_ACTIVE_1
#else
#define ROLL_TM_T_ACTIVE_1 3
#endif
#ifdef ROLL_TM_CONF_T_DWELL_1
#define ROLL_TM_T_DWELL_1 ROLL_TM_CONF_T_DWELL_1
#else
#define ROLL_TM_T_DWELL_1 12
#endif
/*---------------------------------------------------------------------------*/
/* Configuration */
/*---------------------------------------------------------------------------*/
/*
* Number of Sliding Windows
* In essence: How many unique sources of simultaneous multicast traffic do we
* want to support for our lowpan
* If a node is seeding two multicast streams, parametrized on different M
* values, then this seed will occupy two different sliding windows
*/
#ifdef ROLL_TM_CONF_WINS
#define ROLL_TM_WINS ROLL_TM_CONF_WINS
#else
#define ROLL_TM_WINS 2
#endif
/*---------------------------------------------------------------------------*/
/*
* Maximum Number of Buffered Multicast Messages
* This buffer is shared across all Seed IDs, therefore a new very active Seed
* may eventually occupy all slots. It would make little sense (if any) to
* define support for fewer buffered messages than seeds*2
*/
#ifdef ROLL_TM_CONF_BUFF_NUM
#define ROLL_TM_BUFF_NUM ROLL_TM_CONF_BUFF_NUM
#else
#define ROLL_TM_BUFF_NUM 6
#endif
/*---------------------------------------------------------------------------*/
/*
* Use Short Seed IDs [short: 2, long: 16 (default)]
* It can be argued that we should (and it would be easy to) support both at
* the same time but the draft doesn't list this as a MUST so we opt for
* code/ram savings
*/
#ifdef ROLL_TM_CONF_SHORT_SEEDS
#define ROLL_TM_SHORT_SEEDS ROLL_TM_CONF_SHORT_SEEDS
#else
#define ROLL_TM_SHORT_SEEDS 0
#endif
/*---------------------------------------------------------------------------*/
/*
* Destination address for our ICMPv6 advertisements. The draft gives us a
* choice between LL all-nodes or LL all-routers
*
* We use allrouters unless a conf directive chooses otherwise
*/
#ifdef ROLL_TM_CONF_DEST_ALL_NODES
#define ROLL_TM_DEST_ALL_NODES ROLL_TM_CONF_DEST_ALL_NODES
#else
#define ROLL_TM_DEST_ALL_NODES 0
#endif
/*---------------------------------------------------------------------------*/
/*
* M param for our outgoing messages
* By default, we set the M bit (conservative). Define this as 0 to clear the
* M bit in our outgoing messages (aggressive)
*/
#ifdef ROLL_TM_CONF_SET_M_BIT
#define ROLL_TM_SET_M_BIT ROLL_TM_CONF_SET_M_BIT
#else
#define ROLL_TM_SET_M_BIT 1
#endif
/*---------------------------------------------------------------------------*/
/* Stats datatype */
/*---------------------------------------------------------------------------*/
struct roll_tm_stats {
UIP_MCAST6_STATS_DATATYPE icmp_in;
UIP_MCAST6_STATS_DATATYPE icmp_out;
UIP_MCAST6_STATS_DATATYPE icmp_bad;
};
#endif /* ROLL_TM_H_ */

View file

@ -0,0 +1,211 @@
/*
* Copyright (c) 2010, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* This file implements 'Stateless Multicast RPL Forwarding' (SMRF)
*
* It will only work in RPL networks in MOP 3 "Storing with Multicast"
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#include "contiki.h"
#include "contiki-net.h"
#include "net/ipv6/multicast/uip-mcast6.h"
#include "net/ipv6/multicast/uip-mcast6-route.h"
#include "net/ipv6/multicast/uip-mcast6-stats.h"
#include "net/ipv6/multicast/smrf.h"
#include "net/rpl/rpl.h"
#include "net/netstack.h"
#include <string.h>
#define DEBUG DEBUG_NONE
#include "net/ip/uip-debug.h"
#if UIP_CONF_IPV6
/*---------------------------------------------------------------------------*/
/* Macros */
/*---------------------------------------------------------------------------*/
/* CCI */
#define SMRF_FWD_DELAY() NETSTACK_RDC.channel_check_interval()
/* Number of slots in the next 500ms */
#define SMRF_INTERVAL_COUNT ((CLOCK_SECOND >> 2) / fwd_delay)
/*---------------------------------------------------------------------------*/
/* Internal Data */
/*---------------------------------------------------------------------------*/
static struct ctimer mcast_periodic;
static uint8_t mcast_len;
static uip_buf_t mcast_buf;
static uint8_t fwd_delay;
static uint8_t fwd_spread;
/*---------------------------------------------------------------------------*/
/* uIPv6 Pointers */
/*---------------------------------------------------------------------------*/
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
/*---------------------------------------------------------------------------*/
static void
mcast_fwd(void *p)
{
memcpy(uip_buf, &mcast_buf, mcast_len);
uip_len = mcast_len;
UIP_IP_BUF->ttl--;
tcpip_output(NULL);
uip_len = 0;
}
/*---------------------------------------------------------------------------*/
static uint8_t
in()
{
rpl_dag_t *d; /* Our DODAG */
uip_ipaddr_t *parent_ipaddr; /* Our pref. parent's IPv6 address */
const uip_lladdr_t *parent_lladdr; /* Our pref. parent's LL address */
/*
* Fetch a pointer to the LL address of our preferred parent
*
* ToDo: This rpl_get_any_dag() call is a dirty replacement of the previous
* rpl_get_dag(RPL_DEFAULT_INSTANCE);
* so that things can compile with the new RPL code. This needs updated to
* read instance ID from the RPL HBHO and use the correct parent accordingly
*/
d = rpl_get_any_dag();
if(!d) {
UIP_MCAST6_STATS_ADD(mcast_dropped);
return UIP_MCAST6_DROP;
}
/* Retrieve our preferred parent's LL address */
parent_ipaddr = rpl_get_parent_ipaddr(d->preferred_parent);
parent_lladdr = uip_ds6_nbr_lladdr_from_ipaddr(parent_ipaddr);
if(parent_lladdr == NULL) {
UIP_MCAST6_STATS_ADD(mcast_dropped);
return UIP_MCAST6_DROP;
}
/*
* We accept a datagram if it arrived from our preferred parent, discard
* otherwise.
*/
if(memcmp(parent_lladdr, packetbuf_addr(PACKETBUF_ADDR_SENDER),
UIP_LLADDR_LEN)) {
PRINTF("SMRF: Routable in but SMRF ignored it\n");
UIP_MCAST6_STATS_ADD(mcast_dropped);
return UIP_MCAST6_DROP;
}
if(UIP_IP_BUF->ttl <= 1) {
UIP_MCAST6_STATS_ADD(mcast_dropped);
return UIP_MCAST6_DROP;
}
UIP_MCAST6_STATS_ADD(mcast_in_all);
UIP_MCAST6_STATS_ADD(mcast_in_unique);
/* If we have an entry in the mcast routing table, something with
* a higher RPL rank (somewhere down the tree) is a group member */
if(uip_mcast6_route_lookup(&UIP_IP_BUF->destipaddr)) {
/* If we enter here, we will definitely forward */
UIP_MCAST6_STATS_ADD(mcast_fwd);
/*
* Add a delay (D) of at least SMRF_FWD_DELAY() to compensate for how
* contikimac handles broadcasts. We can't start our TX before the sender
* has finished its own.
*/
fwd_delay = SMRF_FWD_DELAY();
/* Finalise D: D = min(SMRF_FWD_DELAY(), SMRF_MIN_FWD_DELAY) */
#if SMRF_MIN_FWD_DELAY
if(fwd_delay < SMRF_MIN_FWD_DELAY) {
fwd_delay = SMRF_MIN_FWD_DELAY;
}
#endif
if(fwd_delay == 0) {
/* No delay required, send it, do it now, why wait? */
UIP_IP_BUF->ttl--;
tcpip_output(NULL);
UIP_IP_BUF->ttl++; /* Restore before potential upstack delivery */
} else {
/* Randomise final delay in [D , D*Spread], step D */
fwd_spread = SMRF_INTERVAL_COUNT;
if(fwd_spread > SMRF_MAX_SPREAD) {
fwd_spread = SMRF_MAX_SPREAD;
}
if(fwd_spread) {
fwd_delay = fwd_delay * (1 + ((random_rand() >> 11) % fwd_spread));
}
memcpy(&mcast_buf, uip_buf, uip_len);
mcast_len = uip_len;
ctimer_set(&mcast_periodic, fwd_delay, mcast_fwd, NULL);
}
PRINTF("SMRF: %u bytes: fwd in %u [%u]\n",
uip_len, fwd_delay, fwd_spread);
}
/* Done with this packet unless we are a member of the mcast group */
if(!uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) {
PRINTF("SMRF: Not a group member. No further processing\n");
return UIP_MCAST6_DROP;
} else {
PRINTF("SMRF: Ours. Deliver to upper layers\n");
UIP_MCAST6_STATS_ADD(mcast_in_ours);
return UIP_MCAST6_ACCEPT;
}
}
/*---------------------------------------------------------------------------*/
static void
init()
{
UIP_MCAST6_STATS_INIT(NULL);
uip_mcast6_route_init();
}
/*---------------------------------------------------------------------------*/
static void
out()
{
return;
}
/*---------------------------------------------------------------------------*/
const struct uip_mcast6_driver smrf_driver = {
"SMRF",
init,
out,
in,
};
/*---------------------------------------------------------------------------*/
#endif /* UIP_CONF_IPV6 */

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2011, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* Header file for 'Stateless Multicast RPL Forwarding' (SMRF)
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#ifndef SMRF_H_
#define SMRF_H_
#include "contiki-conf.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
/* Configuration */
/*---------------------------------------------------------------------------*/
/* Fmin */
#ifdef SMRF_CONF_MIN_FWD_DELAY
#define SMRF_MIN_FWD_DELAY SMRF_CONF_MIN_FWD_DELAY
#else
#define SMRF_MIN_FWD_DELAY 4
#endif
/* Max Spread */
#ifdef SMRF_CONF_MAX_SPREAD
#define SMRF_MAX_SPREAD SMRF_CONF_MAX_SPREAD
#else
#define SMRF_MAX_SPREAD 4
#endif
/*---------------------------------------------------------------------------*/
/* Stats datatype */
/*---------------------------------------------------------------------------*/
struct smrf_stats {
uint16_t mcast_in_unique;
uint16_t mcast_in_all; /* At layer 3 */
uint16_t mcast_in_ours; /* Unique and we are a group member */
uint16_t mcast_fwd; /* Forwarded by us but we are not the seed */
uint16_t mcast_out; /* We are the seed */
uint16_t mcast_bad;
uint16_t mcast_dropped;
};
#endif /* SMRF_H_ */

View file

@ -0,0 +1,50 @@
/*
* Copyright (c) 2011, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* Header file with definition of multicast engine constants
*
* When writing a new engine, add it here with a unique number and
* then modify uip-mcast6.h accordingly
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#ifndef UIP_MCAST6_ENGINES_H_
#define UIP_MCAST6_ENGINES_H_
#define UIP_MCAST6_ENGINE_NONE 0 /* Selecting this disables mcast */
#define UIP_MCAST6_ENGINE_SMRF 1
#define UIP_MCAST6_ENGINE_ROLL_TM 2
#endif /* UIP_MCAST6_ENGINES_H_ */

View file

@ -0,0 +1,133 @@
/*
* Copyright (c) 2011, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the 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.
*/
/**
* \file
* Multicast routing table manipulation
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#include "contiki.h"
#include "lib/list.h"
#include "lib/memb.h"
#include "net/ip/uip.h"
#include "net/ipv6/multicast/uip-mcast6-route.h"
#include <stdint.h>
#include <string.h>
#if UIP_CONF_IPV6
/*---------------------------------------------------------------------------*/
/* Size of the multicast routing table */
#ifdef UIP_MCAST6_ROUTE_CONF_ROUTES
#define UIP_MCAST6_ROUTE_ROUTES UIP_MCAST6_ROUTE_CONF_ROUTES
#else
#define UIP_MCAST6_ROUTE_ROUTES 1
#endif /* UIP_CONF_DS6_MCAST_ROUTES */
/*---------------------------------------------------------------------------*/
LIST(mcast_route_list);
MEMB(mcast_route_memb, uip_mcast6_route_t, UIP_MCAST6_ROUTE_ROUTES);
static uip_mcast6_route_t *locmcastrt;
/*---------------------------------------------------------------------------*/
uip_mcast6_route_t *
uip_mcast6_route_lookup(uip_ipaddr_t *group)
{
locmcastrt = NULL;
for(locmcastrt = list_head(mcast_route_list);
locmcastrt != NULL;
locmcastrt = list_item_next(locmcastrt)) {
if(uip_ipaddr_cmp(&locmcastrt->group, group)) {
return locmcastrt;
}
}
return NULL;
}
/*---------------------------------------------------------------------------*/
uip_mcast6_route_t *
uip_mcast6_route_add(uip_ipaddr_t *group)
{
/* _lookup must return NULL, i.e. the prefix does not exist in our table */
locmcastrt = uip_mcast6_route_lookup(group);
if(locmcastrt == NULL) {
/* Allocate an entry and add the group to the list */
locmcastrt = memb_alloc(&mcast_route_memb);
if(locmcastrt == NULL) {
return NULL;
}
list_add(mcast_route_list, locmcastrt);
}
/* Reaching here means we either found the prefix or allocated a new one */
uip_ipaddr_copy(&(locmcastrt->group), group);
return locmcastrt;
}
/*---------------------------------------------------------------------------*/
void
uip_mcast6_route_rm(uip_mcast6_route_t *route)
{
/* Make sure it's actually in the list */
for(locmcastrt = list_head(mcast_route_list);
locmcastrt != NULL;
locmcastrt = list_item_next(locmcastrt)) {
if(locmcastrt == route) {
list_remove(mcast_route_list, route);
memb_free(&mcast_route_memb, route);
return;
}
}
}
/*---------------------------------------------------------------------------*/
uip_mcast6_route_t *
uip_mcast6_route_list_head(void)
{
return list_head(mcast_route_list);
}
/*---------------------------------------------------------------------------*/
int
uip_mcast6_route_count(void)
{
return list_length(mcast_route_list);
}
/*---------------------------------------------------------------------------*/
void
uip_mcast6_route_init()
{
memb_init(&mcast_route_memb);
list_init(mcast_route_list);
}
/*---------------------------------------------------------------------------*/
#endif /* UIP_CONF_IPV6 */

View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2011, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the 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.
*/
/**
* \file
* Multicast routing table manipulation
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#ifndef UIP_MCAST6_ROUTE_H_
#define UIP_MCAST6_ROUTE_H_
#include "contiki.h"
#include "net/ip/uip.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
/** \brief An entry in the multicast routing table */
typedef struct uip_mcast6_route {
struct uip_mcast6_route *next;
uip_ipaddr_t group;
uint32_t lifetime; /* seconds */
void *dag; /* Pointer to an rpl_dag_t struct */
} uip_mcast6_route_t;
/*---------------------------------------------------------------------------*/
/** \name Multicast Routing Table Manipulation */
/** @{ */
uip_mcast6_route_t *uip_mcast6_route_lookup(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);
int uip_mcast6_route_count(void);
uip_mcast6_route_t *uip_mcast6_route_list_head(void);
/*---------------------------------------------------------------------------*/
/**
* \brief Multicast routing table init routine
*
* Multicast routing tables are not necessarily required by all
* multicast engines. For instance, trickle multicast does not rely on
* the existence of a routing table. Therefore, this function here
* should be invoked by each engine's init routine only if the relevant
* functionality is required. This is also why this function should not
* get hooked into the uip-ds6 core.
*/
void uip_mcast6_route_init(void);
/** @} */
#endif /* UIP_MCAST6_ROUTE_H_ */

View file

@ -0,0 +1,49 @@
/*
* Copyright (c) 2014, University of Bristol - http://www.bris.ac.uk
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
* IPv6 multicast forwarding stats maintenance
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#include "net/ipv6/multicast/uip-mcast6-stats.h"
#include <string.h>
/*---------------------------------------------------------------------------*/
uip_mcast6_stats_t uip_mcast6_stats;
/*---------------------------------------------------------------------------*/
void
uip_mcast6_stats_init(void *stats)
{
memset(&uip_mcast6_stats, 0, sizeof(uip_mcast6_stats));
uip_mcast6_stats.engine_stats = stats;
}
/*---------------------------------------------------------------------------*/

View file

@ -0,0 +1,91 @@
/*
* Copyright (c) 2014, University of Bristol - http://www.bris.ac.uk
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file
* Header file for IPv6 multicast forwarding stats maintenance
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#ifndef UIP_MCAST6_STATS_H_
#define UIP_MCAST6_STATS_H_
/*---------------------------------------------------------------------------*/
#include "contiki-conf.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
/* The platform can override the stats datatype */
#ifdef UIP_MCAST6_CONF_STATS_DATATYPE
#define UIP_MCAST6_STATS_DATATYPE UIP_MCAST6_CONF_STATS_DATATYPE
#else
#define UIP_MCAST6_STATS_DATATYPE uint16_t
#endif
/*---------------------------------------------------------------------------*/
#ifdef UIP_MCAST6_CONF_STATS
#define UIP_MCAST6_STATS UIP_MCAST6_CONF_STATS
#else
#define UIP_MCAST6_STATS 0
#endif
/*---------------------------------------------------------------------------*/
/* Stats datatype */
/*---------------------------------------------------------------------------*/
typedef struct uip_mcast6_stats {
UIP_MCAST6_STATS_DATATYPE mcast_in_unique;
UIP_MCAST6_STATS_DATATYPE mcast_in_all; /* At layer 3 */
UIP_MCAST6_STATS_DATATYPE mcast_in_ours; /* Unique and we are a group member */
UIP_MCAST6_STATS_DATATYPE mcast_fwd; /* Forwarded by us but we are not the seed */
UIP_MCAST6_STATS_DATATYPE mcast_out; /* We are the seed */
UIP_MCAST6_STATS_DATATYPE mcast_bad;
UIP_MCAST6_STATS_DATATYPE mcast_dropped;
void *engine_stats; /* Opaque pointer to an engine's additional stats */
} uip_mcast6_stats_t;
/*---------------------------------------------------------------------------*/
/* Access macros */
/*---------------------------------------------------------------------------*/
#if UIP_MCAST6_STATS
/* Don't access this variable directly, use the macros below */
extern uip_mcast6_stats_t uip_mcast6_stats;
#define UIP_MCAST6_STATS_ADD(x) uip_mcast6_stats.x++
#define UIP_MCAST6_STATS_GET(x) uip_mcast6_stats.x
#define UIP_MCAST6_STATS_INIT(s) uip_mcast6_stats_init(s)
#else /* UIP_MCAST6_STATS */
#define UIP_MCAST6_STATS_ADD(x)
#define UIP_MCAST6_STATS_GET(x) 0
#define UIP_MCAST6_STATS_INIT(s)
#endif /* UIP_MCAST6_STATS */
/*---------------------------------------------------------------------------*/
/**
* \brief Initialise multicast stats
* \param stats A pointer to a struct holding an engine's additional statistics
*/
void uip_mcast6_stats_init(void *stats);
/*---------------------------------------------------------------------------*/
#endif /* UIP_MCAST6_STATS_H_ */

View file

@ -0,0 +1,162 @@
/*
* Copyright (c) 2011, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* This header file contains configuration directives for uIPv6
* multicast support.
*
* We currently support 2 engines:
* - 'Stateless Multicast RPL Forwarding' (SMRF)
* RPL does group management as per the RPL docs, SMRF handles datagram
* forwarding
* - 'Multicast Forwarding with Trickle' according to the algorithm described
* in the internet draft:
* http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#ifndef UIP_MCAST6_H_
#define UIP_MCAST6_H_
#include "contiki-conf.h"
#include "net/ipv6/multicast/uip-mcast6-engines.h"
#include "net/ipv6/multicast/uip-mcast6-route.h"
#include "net/ipv6/multicast/smrf.h"
#include "net/ipv6/multicast/roll-tm.h"
#include <string.h>
/*---------------------------------------------------------------------------*/
/* Constants */
/*---------------------------------------------------------------------------*/
#define UIP_MCAST6_DROP 0
#define UIP_MCAST6_ACCEPT 1
/*---------------------------------------------------------------------------*/
/* Multicast Address Scopes (RFC 4291 & draft-ietf-6man-multicast-scopes) */
#define UIP_MCAST6_SCOPE_INTERFACE 0x01
#define UIP_MCAST6_SCOPE_LINK_LOCAL 0x02
#define UIP_MCAST6_SCOPE_REALM_LOCAL 0x03 /* draft-ietf-6man-multicast-scopes */
#define UIP_MCAST6_SCOPE_ADMIN_LOCAL 0x04
#define UIP_MCAST6_SCOPE_SITE_LOCAL 0x05
#define UIP_MCAST6_SCOPE_ORG_LOCAL 0x08
#define UIP_MCAST6_SCOPE_GLOBAL 0x0E
/*---------------------------------------------------------------------------*/
/* Choose an engine or turn off based on user configuration */
/*---------------------------------------------------------------------------*/
#ifdef UIP_MCAST6_CONF_ENGINE
#define UIP_MCAST6_ENGINE UIP_MCAST6_CONF_ENGINE
#else
#define UIP_MCAST6_ENGINE UIP_MCAST6_ENGINE_NONE
#endif
/*---------------------------------------------------------------------------*/
/*
* Multicast API. Similar to NETSTACK, each engine must define a driver and
* populate the fields with suitable function pointers
*/
struct uip_mcast6_driver {
char *name;
/** Initialize the multicast engine */
void (* init)(void);
/**
* \brief Process an outgoing datagram with a multicast IPv6 destination
* address
*
* This may be needed if the multicast engine needs to, for example,
* add IPv6 extension headers to the datagram, cache it, decide it
* needs dropped etc.
*
* It is sometimes desirable to let the engine handle datagram
* dispatch instead of letting the networking core do it. If the
* engine decides to send the datagram itself, it must afterwards
* set uip_len = 0 to prevent the networking core from sending too
*/
void (* out)(void);
/**
* \brief Process an incoming multicast datagram and determine whether it
* should be delivered up the stack or not.
*
* \return 0: Drop, 1: Deliver
*
* When a datagram with a multicast destination address is received,
* the forwarding logic in core is bypassed. Instead, we let the
* multicast engine handle forwarding internally if and as necessary.
* This function is where forwarding logic must be hooked in.
*
* Once the engine is done with forwarding, it must signal via the
* return value whether the datagram needs delivered up the network
* stack.
*/
uint8_t (* in)(void);
};
/*---------------------------------------------------------------------------*/
/**
* \brief Get a multicast address' scope.
* a is of type uip_ip6addr_t*
*/
#define uip_mcast6_get_address_scope(a) ((a)->u8[1] & 0x0F)
/*---------------------------------------------------------------------------*/
/* Configure multicast and core/net to play nicely with the selected engine */
#if UIP_MCAST6_ENGINE
/* Enable Multicast hooks in the uip6 core */
#define UIP_CONF_IPV6_MULTICAST 1
#if UIP_MCAST6_ENGINE == UIP_MCAST6_ENGINE_ROLL_TM
#define RPL_CONF_MULTICAST 0 /* Not used by trickle */
#define UIP_CONF_IPV6_ROLL_TM 1 /* ROLL Trickle ICMP type support */
#define UIP_MCAST6 roll_tm_driver
#elif UIP_MCAST6_ENGINE == UIP_MCAST6_ENGINE_SMRF
#define RPL_CONF_MULTICAST 1
#define UIP_MCAST6 smrf_driver
#else
#error "Multicast Enabled with an Unknown Engine."
#error "Check the value of UIP_MCAST6_CONF_ENGINE in conf files."
#endif
#endif /* UIP_MCAST6_ENGINE */
extern const struct uip_mcast6_driver UIP_MCAST6;
/*---------------------------------------------------------------------------*/
/* Configuration Checks */
/*---------------------------------------------------------------------------*/
#if RPL_CONF_MULTICAST && (!UIP_CONF_IPV6_RPL)
#error "The selected Multicast mode requires UIP_CONF_IPV6_RPL != 0"
#error "Check the value of UIP_CONF_IPV6_RPL in conf files."
#endif
/*---------------------------------------------------------------------------*/
#endif /* UIP_MCAST6_H_ */

View file

@ -512,6 +512,10 @@ uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
} }
} }
} }
#if UIP_IPV6_MULTICAST
} else if(uip_is_addr_mcast_routable(dst)) {
matchaddr = uip_ds6_get_global(ADDR_PREFERRED);
#endif
} else { } else {
matchaddr = uip_ds6_get_link_local(ADDR_PREFERRED); matchaddr = uip_ds6_get_link_local(ADDR_PREFERRED);
} }

View file

@ -74,10 +74,53 @@
static uip_ipaddr_t tmp_ipaddr; static uip_ipaddr_t tmp_ipaddr;
LIST(echo_reply_callback_list); LIST(echo_reply_callback_list);
/*---------------------------------------------------------------------------*/
/* List of input handlers */
LIST(input_handler_list);
/*---------------------------------------------------------------------------*/
static uip_icmp6_input_handler_t *
input_handler_lookup(uint8_t type, uint8_t icode)
{
uip_icmp6_input_handler_t *handler = NULL;
for(handler = list_head(input_handler_list);
handler != NULL;
handler = list_item_next(handler)) {
if(handler->type == type &&
(handler->icode == icode ||
handler->icode == UIP_ICMP6_HANDLER_CODE_ANY)) {
return handler;
}
}
return NULL;
}
/*---------------------------------------------------------------------------*/
uint8_t
uip_icmp6_input(uint8_t type, uint8_t icode)
{
uip_icmp6_input_handler_t *handler = input_handler_lookup(type, icode);
if(handler == NULL) {
return UIP_ICMP6_INPUT_ERROR;
}
if(handler->handler == NULL) {
return UIP_ICMP6_INPUT_ERROR;
}
handler->handler();
return UIP_ICMP6_INPUT_SUCCESS;
}
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_icmp6_echo_request_input(void) uip_icmp6_register_input_handler(uip_icmp6_input_handler_t *handler)
{
list_add(input_handler_list, handler);
}
/*---------------------------------------------------------------------------*/
static void
echo_request_input(void)
{ {
#if UIP_CONF_IPV6_RPL #if UIP_CONF_IPV6_RPL
uint8_t temp_ext_len; uint8_t temp_ext_len;
@ -275,8 +318,8 @@ uip_icmp6_send(const uip_ipaddr_t *dest, int type, int code, int payload_len)
tcpip_ipv6_output(); tcpip_ipv6_output();
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void static void
uip_icmp6_echo_reply_input(void) echo_reply_input(void)
{ {
int ttl; int ttl;
uip_ipaddr_t sender; uip_ipaddr_t sender;
@ -343,6 +386,8 @@ uip_icmp6_echo_reply_input(void)
} }
} }
} }
uip_len = 0;
return; return;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -362,5 +407,18 @@ uip_icmp6_echo_reply_callback_rm(struct uip_icmp6_echo_reply_notification *n)
list_remove(echo_reply_callback_list, n); list_remove(echo_reply_callback_list, n);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
UIP_ICMP6_HANDLER(echo_request_handler, ICMP6_ECHO_REQUEST,
UIP_ICMP6_HANDLER_CODE_ANY, echo_request_input);
UIP_ICMP6_HANDLER(echo_reply_handler, ICMP6_ECHO_REPLY,
UIP_ICMP6_HANDLER_CODE_ANY, echo_reply_input);
/*---------------------------------------------------------------------------*/
void
uip_icmp6_init()
{
/* Register Echo Request and Reply handlers */
uip_icmp6_register_input_handler(&echo_request_handler);
uip_icmp6_register_input_handler(&echo_reply_handler);
}
/*---------------------------------------------------------------------------*/
/** @} */ /** @} */
#endif /* UIP_CONF_IPV6 */ #endif /* UIP_CONF_IPV6 */

View file

@ -65,6 +65,11 @@
#define ICMP6_REDIRECT 137 /**< Redirect */ #define ICMP6_REDIRECT 137 /**< Redirect */
#define ICMP6_RPL 155 /**< RPL */ #define ICMP6_RPL 155 /**< RPL */
#define ICMP6_PRIV_EXP_100 100 /**< Private Experimentation */
#define ICMP6_PRIV_EXP_101 101 /**< Private Experimentation */
#define ICMP6_PRIV_EXP_200 200 /**< Private Experimentation */
#define ICMP6_PRIV_EXP_201 201 /**< Private Experimentation */
#define ICMP6_ROLL_TM ICMP6_PRIV_EXP_200 /**< ROLL Trickle Multicast */
/** @} */ /** @} */
@ -104,24 +109,6 @@ typedef struct uip_icmp6_error{
/** \name ICMPv6 RFC4443 Message processing and sending */ /** \name ICMPv6 RFC4443 Message processing and sending */
/** @{ */ /** @{ */
/** \
* brief Process an echo request
*
* Perform a few checks, then send an Echo reply. The reply is
* built here.
*/
void
uip_icmp6_echo_request_input(void);
/** \
* brief Process an echo reply
*
* Perform a few checks, then call applications to inform that an echo
* reply has been received.
*/
void
uip_icmp6_echo_reply_input(void);
/** /**
* \brief Send an icmpv6 error message * \brief Send an icmpv6 error message
* \param type type of the error message * \param type type of the error message
@ -187,8 +174,66 @@ uip_icmp6_echo_reply_callback_add(struct uip_icmp6_echo_reply_notification *n,
void void
uip_icmp6_echo_reply_callback_rm(struct uip_icmp6_echo_reply_notification *n); uip_icmp6_echo_reply_callback_rm(struct uip_icmp6_echo_reply_notification *n);
/* Generic ICMPv6 input handers */
typedef struct uip_icmp6_input_handler {
struct uip_icmp6_input_handler *next;
uint8_t type;
uint8_t icode;
void (*handler)(void);
} uip_icmp6_input_handler_t;
#define UIP_ICMP6_INPUT_SUCCESS 0
#define UIP_ICMP6_INPUT_ERROR 1
#define UIP_ICMP6_HANDLER_CODE_ANY 0xFF /* Handle all codes for this type */
/*
* Initialise a variable of type uip_icmp6_input_handler, to be used later as
* the argument to uip_icmp6_register_input_handler
*
* The function pointer stored in this variable will get called and will be
* expected to handle incoming ICMPv6 datagrams of the specified type/code
*
* If code has a value of UIP_ICMP6_HANDLER_CODE_ANY, the same function
* will handle all codes for this type. In other words, the ICMPv6
* message's code is "don't care"
*/
#define UIP_ICMP6_HANDLER(name, type, code, func) \
static uip_icmp6_input_handler_t name = { NULL, type, code, func }
/**
* \brief Handle an incoming ICMPv6 message
* \param type The ICMPv6 message type
* \param icode The ICMPv6 message code
* \return Success: UIP_ICMP6_INPUT_SUCCESS, Error: UIP_ICMP6_INPUT_ERROR
*
* Generic handler for unknown ICMPv6 types. It will lookup for a registered
* function capable of handing this message type. The function must have first
* been registered with uip_icmp6_register_input_handler. The function is in
* charge of setting uip_len to 0, otherwise the uIPv6 core will attempt to
* send whatever remains in the UIP_IP_BUF.
*
* A return value of UIP_ICMP6_INPUT_ERROR means that a handler could not be
* invoked. This is most likely because the ICMPv6 type does not have a valid
* handler associated with it.
* UIP_ICMP6_INPUT_SUCCESS signifies that a handler was found for this ICMPv6
* type and that it was invoked. It does NOT provide any indication whatsoever
* regarding whether the handler itself succeeded.
*/
uint8_t uip_icmp6_input(uint8_t type, uint8_t icode);
/**
* \brief Register a handler which can handle a specific ICMPv6 message type
* \param handler A pointer to the handler
*/
void uip_icmp6_register_input_handler(uip_icmp6_input_handler_t *handler);
/**
* \brief Initialise the uIP ICMPv6 core
*/
void uip_icmp6_init(void);
/** @} */ /** @} */

View file

@ -126,8 +126,6 @@ static uip_ds6_prefix_t *prefix; /** Pointer to a prefix list entry */
static uip_ds6_nbr_t *nbr; /** Pointer to a nbr cache entry*/ static uip_ds6_nbr_t *nbr; /** Pointer to a nbr cache entry*/
static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */ static uip_ds6_defrt_t *defrt; /** Pointer to a router list entry */
static uip_ds6_addr_t *addr; /** Pointer to an interface address */ static uip_ds6_addr_t *addr; /** Pointer to an interface address */
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
/* create a llao */ /* create a llao */
static void static void
@ -143,8 +141,8 @@ create_llao(uint8_t *llao, uint8_t type) {
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
void static void
uip_nd6_ns_input(void) ns_input(void)
{ {
uint8_t flags; uint8_t flags;
PRINTF("Received NS from "); PRINTF("Received NS from ");
@ -388,12 +386,26 @@ uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
PRINTF("\n"); PRINTF("\n");
return; return;
} }
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
void /**
uip_nd6_na_input(void) * Neighbor Advertisement Processing
*
* we might have to send a pkt that had been buffered while address
* resolution was performed (if we support buffering, see UIP_CONF_QUEUE_PKT)
*
* As per RFC 4861, on link layer that have addresses, TLLAO options MUST be
* included when responding to multicast solicitations, SHOULD be included in
* response to unicast (here we assume it is for now)
*
* NA can be received after sending NS for DAD, Address resolution or NUD. Can
* be unsolicited as well.
* It can trigger update of the state of the neighbor in the neighbor cache,
* router in the router list.
* If the NS was for DAD, it means DAD failed
*
*/
static void
na_input(void)
{ {
uint8_t is_llchange; uint8_t is_llchange;
uint8_t is_router; uint8_t is_router;
@ -548,8 +560,8 @@ discard:
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
#if UIP_ND6_SEND_RA #if UIP_ND6_SEND_RA
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void static void
uip_nd6_rs_input(void) rs_input(void)
{ {
PRINTF("Received RS from"); PRINTF("Received RS from");
@ -761,11 +773,18 @@ uip_nd6_rs_output(void)
PRINTF("\n"); PRINTF("\n");
return; return;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/*
* Process a Router Advertisement
*
* - Possible actions when receiving a RA: add router to router list,
* recalculate reachable time, update link hop limit, update retrans timer.
* - If MTU option: update MTU.
* - If SLLAO option: update entry in neighbor cache
* - If prefix option: start autoconf, add prefix to prefix list
*/
void void
uip_nd6_ra_input(void) ra_input(void)
{ {
PRINTF("Received RA from"); PRINTF("Received RA from");
PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
@ -969,6 +988,52 @@ discard:
return; return;
} }
#endif /* !UIP_CONF_ROUTER */ #endif /* !UIP_CONF_ROUTER */
/*------------------------------------------------------------------*/
/* ICMPv6 input handlers */
#if UIP_ND6_SEND_NA
UIP_ICMP6_HANDLER(ns_input_handler, ICMP6_NS, UIP_ICMP6_HANDLER_CODE_ANY,
ns_input);
UIP_ICMP6_HANDLER(na_input_handler, ICMP6_NA, UIP_ICMP6_HANDLER_CODE_ANY,
na_input);
#endif
#if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
UIP_ICMP6_HANDLER(rs_input_handler, ICMP6_RS, UIP_ICMP6_HANDLER_CODE_ANY,
rs_input);
#endif
#if !UIP_CONF_ROUTER
UIP_ICMP6_HANDLER(ra_input_handler, ICMP6_RA, UIP_ICMP6_HANDLER_CODE_ANY,
ra_input);
#endif
/*---------------------------------------------------------------------------*/
void
uip_nd6_init()
{
#if UIP_ND6_SEND_NA
/* Only handle NSs if we are prepared to send out NAs */
uip_icmp6_register_input_handler(&ns_input_handler);
/*
* Only handle NAs if we are prepared to send out NAs.
* This is perhaps logically incorrect, but this condition was present in
* uip_process and we keep it until proven wrong
*/
uip_icmp6_register_input_handler(&na_input_handler);
#endif
#if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
/* Only accept RS if we are a router and happy to send out RAs */
uip_icmp6_register_input_handler(&rs_input_handler);
#endif
#if !UIP_CONF_ROUTER
/* Only process RAs if we are not a router */
uip_icmp6_register_input_handler(&ra_input_handler);
#endif
}
/*---------------------------------------------------------------------------*/
/** @} */ /** @} */
#endif /* UIP_CONF_IPV6 */ #endif /* UIP_CONF_IPV6 */

View file

@ -337,34 +337,8 @@ uip_nd6_ns_input(void);
void void
uip_nd6_ns_output(uip_ipaddr_t *src, uip_ipaddr_t *dest, uip_ipaddr_t *tgt); uip_nd6_ns_output(uip_ipaddr_t *src, uip_ipaddr_t *dest, uip_ipaddr_t *tgt);
/**
* \brief Process a Neighbor Advertisement
*
* we might have to send a pkt that had been buffered while address
* resolution was performed (if we support buffering, see UIP_CONF_QUEUE_PKT)
*
* As per RFC 4861, on link layer that have addresses, TLLAO options MUST be
* included when responding to multicast solicitations, SHOULD be included in
* response to unicast (here we assume it is for now)
*
* NA can be received after sending NS for DAD, Address resolution or NUD. Can
* be unsolicited as well.
* It can trigger update of the state of the neighbor in the neighbor cache,
* router in the router list.
* If the NS was for DAD, it means DAD failed
*
*/
void
uip_nd6_na_input(void);
#if UIP_CONF_ROUTER #if UIP_CONF_ROUTER
#if UIP_ND6_SEND_RA #if UIP_ND6_SEND_RA
/**
* \brief Process a Router Solicitation
*
*/
void uip_nd6_rs_input(void);
/** /**
* \brief send a Router Advertisement * \brief send a Router Advertisement
* *
@ -388,17 +362,9 @@ void uip_nd6_ra_output(uip_ipaddr_t *dest);
void uip_nd6_rs_output(void); void uip_nd6_rs_output(void);
/** /**
* * \brief Initialise the uIP ND core
* \brief process a Router Advertisement
*
* - Possible actions when receiving a RA: add router to router list,
* recalculate reachable time, update link hop limit, update retrans timer.
* - If MTU option: update MTU.
* - If SLLAO option: update entry in neighbor cache
* - If prefix option: start autoconf, add prefix to prefix list
*/ */
void void uip_nd6_init(void);
uip_nd6_ra_input(void);
/** @} */ /** @} */

View file

@ -75,6 +75,7 @@
#include "net/ipv6/uip-icmp6.h" #include "net/ipv6/uip-icmp6.h"
#include "net/ipv6/uip-nd6.h" #include "net/ipv6/uip-nd6.h"
#include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-ds6.h"
#include "net/ipv6/multicast/uip-mcast6.h"
#include <string.h> #include <string.h>
@ -410,6 +411,8 @@ uip_init(void)
{ {
uip_ds6_init(); uip_ds6_init();
uip_icmp6_init();
uip_nd6_init();
#if UIP_TCP #if UIP_TCP
for(c = 0; c < UIP_LISTENPORTS; ++c) { for(c = 0; c < UIP_LISTENPORTS; ++c) {
@ -429,6 +432,10 @@ uip_init(void)
uip_udp_conns[c].lport = 0; uip_udp_conns[c].lport = 0;
} }
#endif /* UIP_UDP */ #endif /* UIP_UDP */
#if UIP_CONF_IPV6_MULTICAST
UIP_MCAST6.init();
#endif
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if UIP_TCP && UIP_ACTIVE_OPEN #if UIP_TCP && UIP_ACTIVE_OPEN
@ -1151,6 +1158,28 @@ uip_process(uint8_t flag)
} }
} }
/*
* Process Packets with a routable multicast destination:
* - We invoke the multicast engine and let it do its thing
* (cache, forward etc).
* - We never execute the datagram forwarding logic in this file here. When
* the engine returns, forwarding has been handled if and as required.
* - Depending on the return value, we either discard or deliver up the stack
*
* All multicast engines must hook in here. After this function returns, we
* expect UIP_BUF to be unmodified
*/
#if UIP_CONF_IPV6_MULTICAST
if(uip_is_addr_mcast_routable(&UIP_IP_BUF->destipaddr)) {
if(UIP_MCAST6.in() == UIP_MCAST6_ACCEPT) {
/* Deliver up the stack */
goto process;
} else {
/* Don't deliver up the stack */
goto drop;
}
}
#endif /* UIP_IPV6_CONF_MULTICAST */
/* TBD Some Parameter problem messages */ /* TBD Some Parameter problem messages */
if(!uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr) && if(!uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr) &&
@ -1220,6 +1249,10 @@ uip_process(uint8_t flag)
uip_ext_bitmap = 0; uip_ext_bitmap = 0;
#endif /* UIP_CONF_ROUTER */ #endif /* UIP_CONF_ROUTER */
#if UIP_CONF_IPV6_MULTICAST
process:
#endif
while(1) { while(1) {
switch(*uip_next_hdr){ switch(*uip_next_hdr){
#if UIP_TCP #if UIP_TCP
@ -1389,61 +1422,17 @@ uip_process(uint8_t flag)
UIP_ICMP6_APPCALL(UIP_ICMP_BUF->type); UIP_ICMP6_APPCALL(UIP_ICMP_BUF->type);
#endif /*UIP_CONF_ICMP6*/ #endif /*UIP_CONF_ICMP6*/
switch(UIP_ICMP_BUF->type) { /*
case ICMP6_NS: * Search generic input handlers.
#if UIP_ND6_SEND_NA * The handler is in charge of setting uip_len to 0
uip_nd6_ns_input(); */
#else /* UIP_ND6_SEND_NA */ if(uip_icmp6_input(UIP_ICMP_BUF->type,
UIP_STAT(++uip_stat.icmp.drop); UIP_ICMP_BUF->icode) == UIP_ICMP6_INPUT_ERROR) {
uip_len = 0; PRINTF("Unknown ICMPv6 message type/code %d\n", UIP_ICMP_BUF->type);
#endif /* UIP_ND6_SEND_NA */
break;
case ICMP6_NA:
#if UIP_ND6_SEND_NA
uip_nd6_na_input();
#else /* UIP_ND6_SEND_NA */
UIP_STAT(++uip_stat.icmp.drop);
uip_len = 0;
#endif /* UIP_ND6_SEND_NA */
break;
case ICMP6_RS:
#if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
uip_nd6_rs_input();
#else /* UIP_CONF_ROUTER && UIP_ND6_SEND_RA */
UIP_STAT(++uip_stat.icmp.drop); UIP_STAT(++uip_stat.icmp.drop);
UIP_STAT(++uip_stat.icmp.typeerr);
UIP_LOG("icmp6: unknown ICMPv6 message.");
uip_len = 0; uip_len = 0;
#endif /* UIP_CONF_ROUTER && UIP_ND6_SEND_RA */
break;
case ICMP6_RA:
#if UIP_CONF_ROUTER
UIP_STAT(++uip_stat.icmp.drop);
uip_len = 0;
#else /* UIP_CONF_ROUTER */
uip_nd6_ra_input();
#endif /* UIP_CONF_ROUTER */
break;
#if UIP_CONF_IPV6_RPL
case ICMP6_RPL:
uip_rpl_input();
break;
#endif /* UIP_CONF_IPV6_RPL */
case ICMP6_ECHO_REQUEST:
uip_icmp6_echo_request_input();
break;
case ICMP6_ECHO_REPLY:
/** Call echo reply input function. */
uip_icmp6_echo_reply_input();
PRINTF("Received an icmp6 echo reply\n");
UIP_STAT(++uip_stat.icmp.recv);
uip_len = 0;
break;
default:
PRINTF("Unknown icmp6 message type %d\n", UIP_ICMP_BUF->type);
UIP_STAT(++uip_stat.icmp.drop);
UIP_STAT(++uip_stat.icmp.typeerr);
UIP_LOG("icmp6: unknown ICMP message.");
uip_len = 0;
break;
} }
if(uip_len > 0) { if(uip_len > 0) {

View file

@ -212,16 +212,17 @@ packet_sent(void *ptr, int status, int num_transmissions)
switch(status) { switch(status) {
case MAC_TX_OK: case MAC_TX_OK:
case MAC_TX_NOACK: case MAC_TX_NOACK:
n->transmissions++; n->transmissions += num_transmissions;
break; break;
case MAC_TX_COLLISION: case MAC_TX_COLLISION:
n->collisions++; n->collisions += num_transmissions;
break; break;
case MAC_TX_DEFERRED: case MAC_TX_DEFERRED:
n->deferrals++; n->deferrals += num_transmissions;
break; break;
} }
/* Find out what packet this callback refers to */
for(q = list_head(n->queued_packet_list); for(q = list_head(n->queued_packet_list);
q != NULL; q = list_item_next(q)) { q != NULL; q = list_item_next(q)) {
if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) == if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) ==

View file

@ -38,6 +38,7 @@
* Logic for Directed Acyclic Graphs in RPL. * Logic for Directed Acyclic Graphs in RPL.
* *
* \author Joakim Eriksson <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se> * \author Joakim Eriksson <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se>
* Contributors: George Oikonomou <oikonomou@users.sourceforge.net> (multicast)
*/ */
@ -46,6 +47,7 @@
#include "net/ip/uip.h" #include "net/ip/uip.h"
#include "net/ipv6/uip-nd6.h" #include "net/ipv6/uip-nd6.h"
#include "net/nbr-table.h" #include "net/nbr-table.h"
#include "net/ipv6/multicast/uip-mcast6.h"
#include "lib/list.h" #include "lib/list.h"
#include "lib/memb.h" #include "lib/memb.h"
#include "sys/ctimer.h" #include "sys/ctimer.h"
@ -985,7 +987,7 @@ rpl_add_dag(uip_ipaddr_t *from, rpl_dio_t *dio)
instance->dio_redundancy != dio->dag_redund || instance->dio_redundancy != dio->dag_redund ||
instance->default_lifetime != dio->default_lifetime || instance->default_lifetime != dio->default_lifetime ||
instance->lifetime_unit != dio->lifetime_unit) { instance->lifetime_unit != dio->lifetime_unit) {
PRINTF("RPL: DIO for DAG instance %u uncompatible with previos DIO\n", PRINTF("RPL: DIO for DAG instance %u incompatible with previous DIO\n",
dio->instance_id); dio->instance_id);
rpl_remove_parent(p); rpl_remove_parent(p);
dag->used = 0; dag->used = 0;
@ -1147,7 +1149,13 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
rpl_dag_t *dag, *previous_dag; rpl_dag_t *dag, *previous_dag;
rpl_parent_t *p; rpl_parent_t *p;
#if RPL_CONF_MULTICAST
/* If the root is advertising MOP 2 but we support MOP 3 we can still join
* In that scenario, we suppress DAOs for multicast targets */
if(dio->mop < RPL_MOP_STORING_NO_MULTICAST) {
#else
if(dio->mop != RPL_MOP_DEFAULT) { if(dio->mop != RPL_MOP_DEFAULT) {
#endif
PRINTF("RPL: Ignoring a DIO with an unsupported MOP: %d\n", dio->mop); PRINTF("RPL: Ignoring a DIO with an unsupported MOP: %d\n", dio->mop);
return; return;
} }
@ -1163,7 +1171,7 @@ rpl_process_dio(uip_ipaddr_t *from, rpl_dio_t *dio)
RPL_LOLLIPOP_INCREMENT(dag->version); RPL_LOLLIPOP_INCREMENT(dag->version);
rpl_reset_dio_timer(instance); rpl_reset_dio_timer(instance);
} else { } else {
PRINTF("RPL: Global Repair\n"); PRINTF("RPL: Global repair\n");
if(dio->prefix_info.length != 0) { if(dio->prefix_info.length != 0) {
if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) { if(dio->prefix_info.flags & UIP_ND6_RA_FLAG_AUTONOMOUS) {
PRINTF("RPL : Prefix announced in DIO\n"); PRINTF("RPL : Prefix announced in DIO\n");

View file

@ -40,6 +40,7 @@
* \author Joakim Eriksson <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se> * \author Joakim Eriksson <joakime@sics.se>, Nicolas Tsiftes <nvt@sics.se>
* Contributors: Niclas Finne <nfi@sics.se>, Joel Hoglund <joel@sics.se>, * Contributors: Niclas Finne <nfi@sics.se>, Joel Hoglund <joel@sics.se>,
* Mathieu Pouillot <m.pouillot@watteco.com> * Mathieu Pouillot <m.pouillot@watteco.com>
* George Oikonomou <oikonomou@users.sourceforge.net> (multicast)
*/ */
#include "net/ip/tcpip.h" #include "net/ip/tcpip.h"
@ -49,6 +50,7 @@
#include "net/ipv6/uip-icmp6.h" #include "net/ipv6/uip-icmp6.h"
#include "net/rpl/rpl-private.h" #include "net/rpl/rpl-private.h"
#include "net/packetbuf.h" #include "net/packetbuf.h"
#include "net/ipv6/multicast/uip-mcast6.h"
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
@ -86,6 +88,15 @@ static uint8_t dao_sequence = RPL_LOLLIPOP_INIT;
extern rpl_of_t RPL_OF; extern rpl_of_t RPL_OF;
#if RPL_CONF_MULTICAST
static uip_mcast6_route_t *mcast_group;
#endif
/*---------------------------------------------------------------------------*/
/* Initialise RPL ICMPv6 message handlers */
UIP_ICMP6_HANDLER(dis_handler, ICMP6_RPL, RPL_CODE_DIS, dis_input);
UIP_ICMP6_HANDLER(dio_handler, ICMP6_RPL, RPL_CODE_DIO, dio_input);
UIP_ICMP6_HANDLER(dao_handler, ICMP6_RPL, RPL_CODE_DAO, dao_input);
UIP_ICMP6_HANDLER(dao_ack_handler, ICMP6_RPL, RPL_CODE_DAO_ACK, dao_ack_input);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static int static int
get_global_addr(uip_ipaddr_t *addr) get_global_addr(uip_ipaddr_t *addr)
@ -163,6 +174,7 @@ dis_input(void)
} }
} }
} }
uip_len = 0;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
@ -171,12 +183,14 @@ dis_output(uip_ipaddr_t *addr)
unsigned char *buffer; unsigned char *buffer;
uip_ipaddr_t tmpaddr; uip_ipaddr_t tmpaddr;
/* DAG Information Solicitation - 2 bytes reserved */ /*
/* 0 1 2 */ * DAG Information Solicitation - 2 bytes reserved
/* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 */ * 0 1 2
/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
/* | Flags | Reserved | Option(s)... */ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
/* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ * | Flags | Reserved | Option(s)...
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
buffer = UIP_ICMP_PAYLOAD; buffer = UIP_ICMP_PAYLOAD;
buffer[0] = buffer[1] = 0; buffer[0] = buffer[1] = 0;
@ -236,7 +250,7 @@ dio_input(void)
PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
PRINTF("\n"); PRINTF("\n");
} else { } else {
PRINTF("RPL: Out of Memory, dropping DIO from "); PRINTF("RPL: Out of memory, dropping DIO from ");
PRINT6ADDR(&from); PRINT6ADDR(&from);
PRINTF(", "); PRINTF(", ");
PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTLLADDR((uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
@ -378,7 +392,7 @@ dio_input(void)
break; break;
case RPL_OPTION_PREFIX_INFO: case RPL_OPTION_PREFIX_INFO:
if(len != 32) { if(len != 32) {
PRINTF("RPL: DAG prefix info not ok, len != 32\n"); PRINTF("RPL: Invalid DAG prefix info, len != 32\n");
RPL_STAT(rpl_stats.malformed_msgs++); RPL_STAT(rpl_stats.malformed_msgs++);
return; return;
} }
@ -402,6 +416,8 @@ dio_input(void)
#endif #endif
rpl_process_dio(&from, &dio); rpl_process_dio(&from, &dio);
uip_len = 0;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
@ -415,7 +431,7 @@ dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr)
#endif /* !RPL_LEAF_ONLY */ #endif /* !RPL_LEAF_ONLY */
#if RPL_LEAF_ONLY #if RPL_LEAF_ONLY
/* In leaf mode, we send DIO message only as unicasts in response to /* In leaf mode, we only send DIO messages as unicasts in response to
unicast DIS messages. */ unicast DIS messages. */
if(uc_addr == NULL) { if(uc_addr == NULL) {
PRINTF("RPL: LEAF ONLY have multicast addr: skip dio_output\n"); PRINTF("RPL: LEAF ONLY have multicast addr: skip dio_output\n");
@ -578,10 +594,11 @@ dao_input(void)
int len; int len;
int i; int i;
int learned_from; int learned_from;
rpl_parent_t *p; rpl_parent_t *parent;
uip_ds6_nbr_t *nbr; uip_ds6_nbr_t *nbr;
prefixlen = 0; prefixlen = 0;
parent = NULL;
uip_ipaddr_copy(&dao_sender_addr, &UIP_IP_BUF->srcipaddr); uip_ipaddr_copy(&dao_sender_addr, &UIP_IP_BUF->srcipaddr);
@ -611,15 +628,41 @@ dao_input(void)
sequence = buffer[pos++]; sequence = buffer[pos++];
dag = instance->current_dag; dag = instance->current_dag;
/* Is the DAGID present? */ /* Is the DAG ID present? */
if(flags & RPL_DAO_D_FLAG) { if(flags & RPL_DAO_D_FLAG) {
if(memcmp(&dag->dag_id, &buffer[pos], sizeof(dag->dag_id))) { if(memcmp(&dag->dag_id, &buffer[pos], sizeof(dag->dag_id))) {
PRINTF("RPL: Ignoring a DAO for a DAG different from ours\n"); PRINTF("RPL: Ignoring a DAO for a DAG different from ours\n");
return; return;
} }
pos += 16; pos += 16;
} else { }
/* Perhaps, there are verification to do but ... */
learned_from = uip_is_addr_mcast(&dao_sender_addr) ?
RPL_ROUTE_FROM_MULTICAST_DAO : RPL_ROUTE_FROM_UNICAST_DAO;
PRINTF("RPL: DAO from %s\n",
learned_from == RPL_ROUTE_FROM_UNICAST_DAO? "unicast": "multicast");
if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) {
/* Check whether this is a DAO forwarding loop. */
parent = rpl_find_parent(dag, &dao_sender_addr);
/* check if this is a new DAO registration with an "illegal" rank */
/* if we already route to this node it is likely */
if(parent != NULL &&
DAG_RANK(parent->rank, instance) < DAG_RANK(dag->rank, instance)) {
PRINTF("RPL: Loop detected when receiving a unicast DAO from a node with a lower rank! (%u < %u)\n",
DAG_RANK(parent->rank, instance), DAG_RANK(dag->rank, instance));
parent->rank = INFINITE_RANK;
parent->updated = 1;
return;
}
/* If we get the DAO from our parent, we also have a loop. */
if(parent != NULL && parent == dag->preferred_parent) {
PRINTF("RPL: Loop detected when receiving a unicast DAO from our parent\n");
parent->rank = INFINITE_RANK;
parent->updated = 1;
return;
}
} }
/* Check if there are any RPL options present. */ /* Check if there are any RPL options present. */
@ -654,6 +697,17 @@ dao_input(void)
PRINT6ADDR(&prefix); PRINT6ADDR(&prefix);
PRINTF("\n"); PRINTF("\n");
#if RPL_CONF_MULTICAST
if(uip_is_addr_mcast_global(&prefix)) {
mcast_group = uip_mcast6_route_add(&prefix);
if(mcast_group) {
mcast_group->dag = dag;
mcast_group->lifetime = RPL_LIFETIME(instance, lifetime);
}
goto fwd_dao;
}
#endif
rep = uip_ds6_route_lookup(&prefix); rep = uip_ds6_route_lookup(&prefix);
if(lifetime == RPL_ZERO_LIFETIME) { if(lifetime == RPL_ZERO_LIFETIME) {
@ -687,34 +741,6 @@ dao_input(void)
return; return;
} }
learned_from = uip_is_addr_mcast(&dao_sender_addr) ?
RPL_ROUTE_FROM_MULTICAST_DAO : RPL_ROUTE_FROM_UNICAST_DAO;
PRINTF("RPL: DAO from %s\n",
learned_from == RPL_ROUTE_FROM_UNICAST_DAO? "unicast": "multicast");
if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) {
/* Check whether this is a DAO forwarding loop. */
p = rpl_find_parent(dag, &dao_sender_addr);
/* check if this is a new DAO registration with an "illegal" rank */
/* if we already route to this node it is likely */
if(p != NULL &&
DAG_RANK(p->rank, instance) < DAG_RANK(dag->rank, instance)) {
PRINTF("RPL: Loop detected when receiving a unicast DAO from a node with a lower rank! (%u < %u)\n",
DAG_RANK(p->rank, instance), DAG_RANK(dag->rank, instance));
p->rank = INFINITE_RANK;
p->updated = 1;
return;
}
/* If we get the DAO from our parent, we also have a loop. */
if(p != NULL && p == dag->preferred_parent) {
PRINTF("RPL: Loop detected when receiving a unicast DAO from our parent\n");
p->rank = INFINITE_RANK;
p->updated = 1;
return;
}
}
PRINTF("RPL: adding DAO route\n"); PRINTF("RPL: adding DAO route\n");
if((nbr = uip_ds6_nbr_lookup(&dao_sender_addr)) == NULL) { if((nbr = uip_ds6_nbr_lookup(&dao_sender_addr)) == NULL) {
@ -740,7 +766,7 @@ dao_input(void)
PRINTF("RPL: Neighbor already in neighbor cache\n"); PRINTF("RPL: Neighbor already in neighbor cache\n");
} }
rpl_lock_parent(p); rpl_lock_parent(parent);
rep = rpl_add_route(dag, &prefix, prefixlen, &dao_sender_addr); rep = rpl_add_route(dag, &prefix, prefixlen, &dao_sender_addr);
if(rep == NULL) { if(rep == NULL) {
@ -752,6 +778,10 @@ dao_input(void)
rep->state.lifetime = RPL_LIFETIME(instance, lifetime); rep->state.lifetime = RPL_LIFETIME(instance, lifetime);
rep->state.learned_from = learned_from; rep->state.learned_from = learned_from;
#if RPL_CONF_MULTICAST
fwd_dao:
#endif
if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) { if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) {
if(dag->preferred_parent != NULL && if(dag->preferred_parent != NULL &&
rpl_get_parent_ipaddr(dag->preferred_parent) != NULL) { rpl_get_parent_ipaddr(dag->preferred_parent) != NULL) {
@ -765,6 +795,7 @@ dao_input(void)
dao_ack_output(instance, &dao_sender_addr, sequence); dao_ack_output(instance, &dao_sender_addr, sequence);
} }
} }
uip_len = 0;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
@ -894,6 +925,7 @@ dao_ack_input(void)
PRINT6ADDR(&UIP_IP_BUF->srcipaddr); PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
PRINTF("\n"); PRINTF("\n");
#endif /* DEBUG */ #endif /* DEBUG */
uip_len = 0;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
@ -916,27 +948,12 @@ dao_ack_output(rpl_instance_t *instance, uip_ipaddr_t *dest, uint8_t sequence)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uip_rpl_input(void) rpl_icmp6_register_handlers()
{ {
PRINTF("Received an RPL control message\n"); uip_icmp6_register_input_handler(&dis_handler);
switch(UIP_ICMP_BUF->icode) { uip_icmp6_register_input_handler(&dio_handler);
case RPL_CODE_DIO: uip_icmp6_register_input_handler(&dao_handler);
dio_input(); uip_icmp6_register_input_handler(&dao_ack_handler);
break;
case RPL_CODE_DIS:
dis_input();
break;
case RPL_CODE_DAO:
dao_input();
break;
case RPL_CODE_DAO_ACK:
dao_ack_input();
break;
default:
PRINTF("RPL: received an unknown ICMP6 code (%u)\n", UIP_ICMP_BUF->icode);
break;
}
uip_len = 0;
} }
/*---------------------------------------------------------------------------*/
#endif /* UIP_CONF_IPV6 */ #endif /* UIP_CONF_IPV6 */

View file

@ -104,7 +104,7 @@ calculate_path_metric(rpl_parent_t *p)
} }
static void static void
reset(rpl_dag_t *sag) reset(rpl_dag_t *dag)
{ {
PRINTF("RPL: Reset MRHOF\n"); PRINTF("RPL: Reset MRHOF\n");
} }

View file

@ -44,6 +44,7 @@
#include "sys/clock.h" #include "sys/clock.h"
#include "sys/ctimer.h" #include "sys/ctimer.h"
#include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-ds6.h"
#include "net/ipv6/multicast/uip-mcast6.h"
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \brief Is IPv6 address addr the link-local, all-RPL-nodes /** \brief Is IPv6 address addr the link-local, all-RPL-nodes
@ -177,8 +178,24 @@
#ifdef RPL_CONF_MOP #ifdef RPL_CONF_MOP
#define RPL_MOP_DEFAULT RPL_CONF_MOP #define RPL_MOP_DEFAULT RPL_CONF_MOP
#else /* RPL_CONF_MOP */
#if RPL_CONF_MULTICAST
#define RPL_MOP_DEFAULT RPL_MOP_STORING_MULTICAST
#else #else
#define RPL_MOP_DEFAULT RPL_MOP_STORING_NO_MULTICAST #define RPL_MOP_DEFAULT RPL_MOP_STORING_NO_MULTICAST
#endif /* UIP_IPV6_MULTICAST_RPL */
#endif /* RPL_CONF_MOP */
/* Emit a pre-processor error if the user configured multicast with bad MOP */
#if RPL_CONF_MULTICAST && (RPL_MOP_DEFAULT != RPL_MOP_STORING_MULTICAST)
#error "RPL Multicast requires RPL_MOP_DEFAULT==3. Check contiki-conf.h"
#endif
/* Multicast Route Lifetime as a multiple of the lifetime unit */
#ifdef RPL_CONF_MCAST_LIFETIME
#define RPL_MCAST_LIFETIME RPL_CONF_MCAST_LIFETIME
#else
#define RPL_MCAST_LIFETIME 3
#endif #endif
/* /*
@ -186,7 +203,7 @@
* whose integer part can be obtained by dividing the value by * whose integer part can be obtained by dividing the value by
* RPL_DAG_MC_ETX_DIVISOR. * RPL_DAG_MC_ETX_DIVISOR.
*/ */
#define RPL_DAG_MC_ETX_DIVISOR 128 #define RPL_DAG_MC_ETX_DIVISOR 256
/* DIS related */ /* DIS related */
#define RPL_DIS_SEND 1 #define RPL_DIS_SEND 1
@ -272,6 +289,7 @@ void dio_output(rpl_instance_t *, uip_ipaddr_t *uc_addr);
void dao_output(rpl_parent_t *, uint8_t lifetime); void dao_output(rpl_parent_t *, uint8_t lifetime);
void dao_output_target(rpl_parent_t *, uip_ipaddr_t *, uint8_t lifetime); void dao_output_target(rpl_parent_t *, uip_ipaddr_t *, uint8_t lifetime);
void dao_ack_output(rpl_instance_t *, uip_ipaddr_t *, uint8_t); void dao_ack_output(rpl_instance_t *, uip_ipaddr_t *, uint8_t);
void rpl_icmp6_register_handlers(void);
/* RPL logic functions. */ /* RPL logic functions. */
void rpl_join_dag(uip_ipaddr_t *from, rpl_dio_t *dio); void rpl_join_dag(uip_ipaddr_t *from, rpl_dio_t *dio);

View file

@ -41,6 +41,7 @@
#include "contiki-conf.h" #include "contiki-conf.h"
#include "net/rpl/rpl-private.h" #include "net/rpl/rpl-private.h"
#include "net/ipv6/multicast/uip-mcast6.h"
#include "lib/random.h" #include "lib/random.h"
#include "sys/ctimer.h" #include "sys/ctimer.h"
@ -69,7 +70,7 @@ handle_periodic_timer(void *ptr)
rpl_recalculate_ranks(); rpl_recalculate_ranks();
/* handle DIS */ /* handle DIS */
#ifdef RPL_DIS_SEND #if RPL_DIS_SEND
next_dis++; next_dis++;
if(rpl_get_any_dag() == NULL && next_dis >= RPL_DIS_INTERVAL) { if(rpl_get_any_dag() == NULL && next_dis >= RPL_DIS_INTERVAL) {
next_dis = 0; next_dis = 0;
@ -220,6 +221,10 @@ static void
handle_dao_timer(void *ptr) handle_dao_timer(void *ptr)
{ {
rpl_instance_t *instance; rpl_instance_t *instance;
#if RPL_CONF_MULTICAST
uip_mcast6_route_t *mcast_route;
uint8_t i;
#endif
instance = (rpl_instance_t *)ptr; instance = (rpl_instance_t *)ptr;
@ -234,6 +239,31 @@ handle_dao_timer(void *ptr)
PRINTF("RPL: handle_dao_timer - sending DAO\n"); PRINTF("RPL: handle_dao_timer - sending DAO\n");
/* Set the route lifetime to the default value. */ /* Set the route lifetime to the default value. */
dao_output(instance->current_dag->preferred_parent, instance->default_lifetime); dao_output(instance->current_dag->preferred_parent, instance->default_lifetime);
#if RPL_CONF_MULTICAST
/* Send DAOs for multicast prefixes only if the instance is in MOP 3 */
if(instance->mop == RPL_MOP_STORING_MULTICAST) {
/* Send a DAO for own multicast addresses */
for(i = 0; i < UIP_DS6_MADDR_NB; i++) {
if(uip_ds6_if.maddr_list[i].isused
&& uip_is_addr_mcast_global(&uip_ds6_if.maddr_list[i].ipaddr)) {
dao_output_target(instance->current_dag->preferred_parent,
&uip_ds6_if.maddr_list[i].ipaddr, RPL_MCAST_LIFETIME);
}
}
/* Iterate over multicast routes and send DAOs */
mcast_route = uip_mcast6_route_list_head();
while(mcast_route != NULL) {
/* Don't send if it's also our own address, done that already */
if(uip_ds6_maddr_lookup(&mcast_route->group) == NULL) {
dao_output_target(instance->current_dag->preferred_parent,
&mcast_route->group, RPL_MCAST_LIFETIME);
}
mcast_route = list_item_next(mcast_route);
}
}
#endif
} else { } else {
PRINTF("RPL: No suitable DAO parent\n"); PRINTF("RPL: No suitable DAO parent\n");
} }

View file

@ -43,7 +43,9 @@
#include "net/ip/uip.h" #include "net/ip/uip.h"
#include "net/ip/tcpip.h" #include "net/ip/tcpip.h"
#include "net/ipv6/uip-ds6.h" #include "net/ipv6/uip-ds6.h"
#include "net/ipv6/uip-icmp6.h"
#include "net/rpl/rpl-private.h" #include "net/rpl/rpl-private.h"
#include "net/ipv6/multicast/uip-mcast6.h"
#define DEBUG DEBUG_NONE #define DEBUG DEBUG_NONE
#include "net/ip/uip-debug.h" #include "net/ip/uip-debug.h"
@ -105,6 +107,9 @@ rpl_purge_routes(void)
uip_ds6_route_t *r; uip_ds6_route_t *r;
uip_ipaddr_t prefix; uip_ipaddr_t prefix;
rpl_dag_t *dag; rpl_dag_t *dag;
#if RPL_CONF_MULTICAST
uip_mcast6_route_t *mcast_route;
#endif
/* First pass, decrement lifetime */ /* First pass, decrement lifetime */
r = uip_ds6_route_head(); r = uip_ds6_route_head();
@ -146,12 +151,29 @@ rpl_purge_routes(void)
r = uip_ds6_route_next(r); r = uip_ds6_route_next(r);
} }
} }
#if RPL_CONF_MULTICAST
mcast_route = uip_mcast6_route_list_head();
while(mcast_route != NULL) {
if(mcast_route->lifetime <= 1) {
uip_mcast6_route_rm(mcast_route);
mcast_route = uip_mcast6_route_list_head();
} else {
mcast_route->lifetime--;
mcast_route = list_item_next(mcast_route);
}
}
#endif
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
rpl_remove_routes(rpl_dag_t *dag) rpl_remove_routes(rpl_dag_t *dag)
{ {
uip_ds6_route_t *r; uip_ds6_route_t *r;
#if RPL_CONF_MULTICAST
uip_mcast6_route_t *mcast_route;
#endif
r = uip_ds6_route_head(); r = uip_ds6_route_head();
@ -163,6 +185,19 @@ rpl_remove_routes(rpl_dag_t *dag)
r = uip_ds6_route_next(r); r = uip_ds6_route_next(r);
} }
} }
#if RPL_CONF_MULTICAST
mcast_route = uip_mcast6_route_list_head();
while(mcast_route != NULL) {
if(mcast_route->dag == dag) {
uip_mcast6_route_rm(mcast_route);
mcast_route = uip_mcast6_route_list_head();
} else {
mcast_route = list_item_next(mcast_route);
}
}
#endif
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
@ -266,6 +301,7 @@ rpl_init(void)
rpl_dag_init(); rpl_dag_init();
rpl_reset_periodic_timer(); rpl_reset_periodic_timer();
rpl_icmp6_register_handlers();
/* add rpl multicast address */ /* add rpl multicast address */
uip_create_linklocal_rplnodes_mcast(&rplmaddr); uip_create_linklocal_rplnodes_mcast(&rplmaddr);
@ -274,6 +310,8 @@ rpl_init(void)
#if RPL_CONF_STATS #if RPL_CONF_STATS
memset(&rpl_stats, 0, sizeof(rpl_stats)); memset(&rpl_stats, 0, sizeof(rpl_stats));
#endif #endif
RPL_OF.reset(NULL);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#endif /* UIP_CONF_IPV6 */ #endif /* UIP_CONF_IPV6 */

View file

@ -189,6 +189,9 @@ struct rpl_of {
rpl_ocp_t ocp; rpl_ocp_t ocp;
}; };
typedef struct rpl_of rpl_of_t; typedef struct rpl_of rpl_of_t;
/* Declare the selected objective function. */
extern rpl_of_t RPL_OF;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Instance */ /* Instance */
struct rpl_instance { struct rpl_instance {

View file

@ -67,5 +67,5 @@ AR = ar65
ASFLAGS = -t $(TARGET) ASFLAGS = -t $(TARGET)
CFLAGS += -t $(TARGET) -Or -W -unused-param CFLAGS += -t $(TARGET) -Or -W -unused-param
LDFLAGS = $(STARTADDR_FLAG) -t $(TARGET) -m contiki-$(TARGET).map -D __STACKSIZE__=0x200 LDFLAGS = -t $(TARGET) -m contiki-$(TARGET).map -D __STACKSIZE__=0x200
AROPTS = a AROPTS = a

View file

@ -2,7 +2,7 @@
==== ====
The cpu/6502/ directory is used for targeting 6502-based machines using the The cpu/6502/ directory is used for targeting 6502-based machines using the
cc65 compiler [http://oliverschmidt.github.io/cc65/](http://oliverschmidt.github.io/cc65/). cc65 compiler [http://cc65.github.io/cc65/](http://cc65.github.io/cc65/).
The Contiki network configuration for 6502-based targets is loaded from a The Contiki network configuration for 6502-based targets is loaded from a
binary configuration file (by default named contiki.cfg). It has the following binary configuration file (by default named contiki.cfg). It has the following

View file

@ -11,7 +11,7 @@ static struct {
} drivers[] = { } drivers[] = {
#ifdef __APPLE2__ #ifdef __APPLE2__
{"Uthernet", 0xC080, "cs8900a.eth" }, {"Uthernet", 0xC080, "cs8900a.eth" },
{"Uthernet II", 0xC080, "w5100.eth" }, {"Uthernet II", 0xC084, "w5100.eth" },
{"LANceGS", 0xC080, "lan91c96.eth"} {"LANceGS", 0xC080, "lan91c96.eth"}
#endif #endif
#ifdef __ATARI__ #ifdef __ATARI__

View file

@ -202,8 +202,8 @@ fixup11:ora data ; Lobyte
; Calculate and set physical address ; Calculate and set physical address
jsr set_addrphysical jsr set_addrphysical
; Move physical address shadow to $F000-$FFFF ; Move physical address shadow to $E000-$FFFF
ora #>$F000 ora #>$8000
tax tax
; Read MAC raw 2byte packet size header ; Read MAC raw 2byte packet size header

View file

@ -3,6 +3,7 @@ CPP = arm-none-eabi-cpp
LD = arm-none-eabi-gcc LD = arm-none-eabi-gcc
AR = arm-none-eabi-ar AR = arm-none-eabi-ar
OBJCOPY = arm-none-eabi-objcopy OBJCOPY = arm-none-eabi-objcopy
OBJDUMP = arm-none-eabi-objdump
NM = arm-none-eabi-nm NM = arm-none-eabi-nm
ifndef SOURCE_LDSCRIPT ifndef SOURCE_LDSCRIPT
@ -19,6 +20,7 @@ LDFLAGS += -T $(LDSCRIPT)
LDFLAGS += -Wl,--gc-sections,--sort-section=alignment LDFLAGS += -Wl,--gc-sections,--sort-section=alignment
LDFLAGS += -Wl,-Map=$(@:.elf=-$(TARGET).map),--cref,--no-warn-mismatch LDFLAGS += -Wl,-Map=$(@:.elf=-$(TARGET).map),--cref,--no-warn-mismatch
OBJCOPY_FLAGS += -O binary --gap-fill 0xff OBJCOPY_FLAGS += -O binary --gap-fill 0xff
OBJDUMP_FLAGS += --disassemble --source --disassembler-options=force-thumb
### Are we building with code size optimisations? ### Are we building with code size optimisations?
ifeq ($(SMALL),1) ifeq ($(SMALL),1)
@ -46,7 +48,7 @@ CONTIKI_CPU_DIRS += ../cc253x/usb/common ../cc253x/usb/common/cdc-acm
### CPU-dependent source files ### CPU-dependent source files
CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c uart.c watchdog.c CONTIKI_CPU_SOURCEFILES += clock.c rtimer-arch.c uart.c watchdog.c
CONTIKI_CPU_SOURCEFILES += nvic.c cpu.c sys-ctrl.c gpio.c ioc.c spi.c CONTIKI_CPU_SOURCEFILES += nvic.c cpu.c sys-ctrl.c gpio.c ioc.c spi.c adc.c
CONTIKI_CPU_SOURCEFILES += cc2538-rf.c udma.c lpm.c CONTIKI_CPU_SOURCEFILES += cc2538-rf.c udma.c lpm.c
CONTIKI_CPU_SOURCEFILES += dbg.c ieee-addr.c CONTIKI_CPU_SOURCEFILES += dbg.c ieee-addr.c
CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c CONTIKI_CPU_SOURCEFILES += slip-arch.c slip.c
@ -82,6 +84,9 @@ CUSTOM_RULE_LINK=1
%.bin: %.elf %.bin: %.elf
$(OBJCOPY) $(OBJCOPY_FLAGS) $< $@ $(OBJCOPY) $(OBJCOPY_FLAGS) $< $@
%.lst: %.elf
$(OBJDUMP) $(OBJDUMP_FLAGS) $< > $@
### We don't really need the .hex and .bin for the .$(TARGET) but let's make ### We don't really need the .hex and .bin for the .$(TARGET) but let's make
### sure they get built ### sure they get built
%.$(TARGET): %.elf %.hex %.bin %.$(TARGET): %.elf %.hex %.bin

View file

@ -38,7 +38,11 @@
* *
* To implement the clock functionality, we use the SysTick peripheral on the * To implement the clock functionality, we use the SysTick peripheral on the
* cortex-M3. We run the system clock at 16 MHz and we set the SysTick to give * cortex-M3. We run the system clock at 16 MHz and we set the SysTick to give
* us 128 interrupts / sec * us 128 interrupts / sec. However, the Sleep Timer counter value is used for
* the number of elapsed ticks in order to avoid a significant time drift caused
* by PM1/2. Contrary to the Sleep Timer, the SysTick peripheral is indeed
* frozen during PM1/2, so adjusting upon wake-up a tick counter based on this
* peripheral would hardly be accurate.
* @{ * @{
* *
* \file * \file
@ -52,14 +56,15 @@
#include "dev/sys-ctrl.h" #include "dev/sys-ctrl.h"
#include "sys/energest.h" #include "sys/energest.h"
#include "sys/etimer.h"
#include "sys/rtimer.h"
#include <stdint.h> #include <stdint.h>
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#define RTIMER_CLOCK_TICK_RATIO (RTIMER_SECOND / CLOCK_SECOND)
#define RELOAD_VALUE (125000 - 1) /** Fire 128 times / sec */ #define RELOAD_VALUE (125000 - 1) /** Fire 128 times / sec */
static volatile clock_time_t count; static volatile uint64_t rt_ticks_startup = 0, rt_ticks_epoch = 0;
static volatile unsigned long secs = 0;
static volatile uint8_t second_countdown = CLOCK_SECOND;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**
* \brief Arch-specific implementation of clock_init for the cc2538 * \brief Arch-specific implementation of clock_init for the cc2538
@ -75,8 +80,6 @@ static volatile uint8_t second_countdown = CLOCK_SECOND;
void void
clock_init(void) clock_init(void)
{ {
count = 0;
REG(SYSTICK_STRELOAD) = RELOAD_VALUE; REG(SYSTICK_STRELOAD) = RELOAD_VALUE;
/* System clock source, Enable */ /* System clock source, Enable */
@ -109,19 +112,19 @@ clock_init(void)
CCIF clock_time_t CCIF clock_time_t
clock_time(void) clock_time(void)
{ {
return count; return rt_ticks_startup / RTIMER_CLOCK_TICK_RATIO;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
clock_set_seconds(unsigned long sec) clock_set_seconds(unsigned long sec)
{ {
secs = sec; rt_ticks_epoch = (uint64_t)sec * RTIMER_SECOND;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
CCIF unsigned long CCIF unsigned long
clock_seconds(void) clock_seconds(void)
{ {
return secs; return rt_ticks_epoch / RTIMER_SECOND;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
@ -160,63 +163,84 @@ clock_delay(unsigned int i)
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**
* \brief Adjust the clock by moving it forward by a number of ticks * \brief Update the software clock ticks and seconds
* \param ticks The number of ticks *
* This function is used to update the software tick counters whenever the
* system clock might have changed, which can occur upon a SysTick ISR or upon
* wake-up from PM1/2.
*
* For the software clock ticks counter, the Sleep Timer counter value is used
* as the base tick value, and extended to a 64-bit value thanks to a detection
* of wraparounds.
*
* For the seconds counter, the changes of the Sleep Timer counter value are
* added to the reference time, which is either the startup time or the value
* passed to clock_set_seconds().
*
* This function polls the etimer process if an etimer has expired.
*/
static void
update_ticks(void)
{
rtimer_clock_t now;
uint64_t prev_rt_ticks_startup, cur_rt_ticks_startup;
uint32_t cur_rt_ticks_startup_hi;
now = RTIMER_NOW();
prev_rt_ticks_startup = rt_ticks_startup;
cur_rt_ticks_startup_hi = prev_rt_ticks_startup >> 32;
if(now < (rtimer_clock_t)prev_rt_ticks_startup) {
cur_rt_ticks_startup_hi++;
}
cur_rt_ticks_startup = (uint64_t)cur_rt_ticks_startup_hi << 32 | now;
rt_ticks_startup = cur_rt_ticks_startup;
rt_ticks_epoch += cur_rt_ticks_startup - prev_rt_ticks_startup;
/*
* Inform the etimer library that the system clock has changed and that an
* etimer might have expired.
*/
if(etimer_pending()) {
etimer_request_poll();
}
}
/*---------------------------------------------------------------------------*/
/**
* \brief Adjust the clock following missed SysTick ISRs
* *
* This function is useful when coming out of PM1/2, during which the system * This function is useful when coming out of PM1/2, during which the system
* clock is stopped. We adjust the clock by moving it forward by a number of * clock is stopped. We adjust the clock counters like after any SysTick ISR.
* ticks equal to the deep sleep duration. We update the seconds counter if
* we have to and we also do some housekeeping so that the next second will
* increment when it is meant to.
* *
* \note This function is only meant to be used by lpm_exit(). Applications * \note This function is only meant to be used by lpm_exit(). Applications
* should really avoid calling this * should really avoid calling this
*/ */
void void
clock_adjust(clock_time_t ticks) clock_adjust(void)
{ {
/* Halt the SysTick while adjusting */ /* Halt the SysTick while adjusting */
REG(SYSTICK_STCTRL) &= ~SYSTICK_STCTRL_ENABLE; REG(SYSTICK_STCTRL) &= ~SYSTICK_STCTRL_ENABLE;
/* Moving forward by more than a second? */ update_ticks();
secs += ticks >> 7;
/* Increment tick count */
count += ticks;
/*
* Update internal second countdown so that next second change will actually
* happen when it's meant to happen.
*/
second_countdown -= ticks;
if(second_countdown == 0 || second_countdown > 128) {
secs++;
second_countdown -= 128;
}
/* Re-Start the SysTick */ /* Re-Start the SysTick */
REG(SYSTICK_STCTRL) |= SYSTICK_STCTRL_ENABLE; REG(SYSTICK_STCTRL) |= SYSTICK_STCTRL_ENABLE;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**
* \brief The clock Interrupt Service Routine. It polls the etimer process * \brief The clock Interrupt Service Routine
* if an etimer has expired. It also updates the software clock tick and *
* seconds counter since reset. * It polls the etimer process if an etimer has expired. It also updates the
* software clock tick and seconds counter.
*/ */
void void
clock_isr(void) clock_isr(void)
{ {
ENERGEST_ON(ENERGEST_TYPE_IRQ); ENERGEST_ON(ENERGEST_TYPE_IRQ);
count++;
if(etimer_pending()) {
etimer_request_poll();
}
if(--second_countdown == 0) { update_ticks();
secs++;
second_countdown = CLOCK_SECOND;
}
ENERGEST_OFF(ENERGEST_TYPE_IRQ); ENERGEST_OFF(ENERGEST_TYPE_IRQ);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

@ -51,7 +51,7 @@
#define write_byte(b) usb_serial_writeb(b) #define write_byte(b) usb_serial_writeb(b)
#define flush() usb_serial_flush() #define flush() usb_serial_flush()
#else #else
#define write_byte(b) uart_write_byte(b) #define write_byte(b) uart_write_byte(DBG_CONF_UART, b)
#define flush() #define flush()
#endif #endif
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

99
cpu/cc2538/dev/adc.c Normal file
View file

@ -0,0 +1,99 @@
/*
* Copyright (c) 2013, ADVANSEE - http://www.advansee.com/
* Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup cc2538-adc
* @{
*
* \file
* Implementation of the cc2538 ADC driver
*/
#include "contiki.h"
#include "dev/soc-adc.h"
#include "dev/cctest.h"
#include "dev/rfcore-xreg.h"
#include "dev/adc.h"
#include "reg.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
void
adc_init(void)
{
/* Start conversions only manually */
REG(SOC_ADC_ADCCON1) |= SOC_ADC_ADCCON1_STSEL;
}
/*---------------------------------------------------------------------------*/
int16_t
adc_get(uint8_t channel, uint8_t ref, uint8_t div)
{
uint32_t cctest_tr0, rfcore_xreg_atest;
int16_t res;
/* On-chip temperature sensor */
if(channel == SOC_ADC_ADCCON_CH_TEMP) {
/* Connect the temperature sensor to the ADC */
cctest_tr0 = REG(CCTEST_TR0);
REG(CCTEST_TR0) = cctest_tr0 | CCTEST_TR0_ADCTM;
/* Enable the temperature sensor */
rfcore_xreg_atest = REG(RFCORE_XREG_ATEST);
REG(RFCORE_XREG_ATEST) = (rfcore_xreg_atest & ~RFCORE_XREG_ATEST_ATEST_CTRL) |
RFCORE_XREG_ATEST_ATEST_CTRL_TEMP;
}
/* Start a single extra conversion with the given parameters */
REG(SOC_ADC_ADCCON3) = (REG(SOC_ADC_ADCCON3) &
~(SOC_ADC_ADCCON3_EREF | SOC_ADC_ADCCON3_EDIV | SOC_ADC_ADCCON3_ECH)) |
ref | div | channel;
/* Poll until end of conversion */
while(!(REG(SOC_ADC_ADCCON1) & SOC_ADC_ADCCON1_EOC));
/* Read conversion result, reading SOC_ADC_ADCH last to clear
* SOC_ADC_ADCCON1.EOC */
res = REG(SOC_ADC_ADCL) & 0xfc;
res |= REG(SOC_ADC_ADCH) << 8;
/* On-chip temperature sensor */
if(channel == SOC_ADC_ADCCON_CH_TEMP) {
/* Restore the initial temperature sensor state and connection (better for
* power consumption) */
REG(RFCORE_XREG_ATEST) = rfcore_xreg_atest;
REG(CCTEST_TR0) = cctest_tr0;
}
/* Return conversion result */
return res;
}
/** @} */

75
cpu/cc2538/dev/adc.h Normal file
View file

@ -0,0 +1,75 @@
/*
* Copyright (c) 2013, ADVANSEE - http://www.advansee.com/
* Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup cc2538
* @{
*
* \defgroup cc2538-adc cc2538 ADC
*
* Driver for the cc2538 ADC controller
* @{
*
* \file
* Header file for the cc2538 ADC driver
*/
#ifndef ADC_H_
#define ADC_H_
#include "contiki.h"
#include "dev/soc-adc.h"
#include <stdint.h>
/*---------------------------------------------------------------------------*/
/** \name ADC functions
* @{
*/
/** \brief Initializes the ADC controller */
void adc_init(void);
/** \brief Performs a single conversion on a given ADC channel
* \param channel The channel used for the conversion: \c SOC_ADC_ADCCON_CH_x
* \param ref The reference voltage used for the conversion: \c SOC_ADC_ADCCON_REF_x
* \param div The decimation rate used for the conversion: \c SOC_ADC_ADCCON_DIV_x
* \return Signed 16-bit conversion result: 2's complement, ENOBs in MSBs
* \note PD[5:4] are not usable when the temperature sensor is selected.
*/
int16_t adc_get(uint8_t channel, uint8_t ref, uint8_t div);
/** @} */
#endif /* ADC_H_ */
/**
* @}
* @}
*/

View file

@ -106,7 +106,7 @@ static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /** Snif */
#define flush() usb_serial_flush() #define flush() usb_serial_flush()
#else #else
#include "dev/uart.h" #include "dev/uart.h"
#define write_byte(b) uart_write_byte(b) #define write_byte(b) uart_write_byte(CC2538_RF_CONF_SNIFFER_UART, b)
#define flush() #define flush()
#endif #endif

92
cpu/cc2538/dev/cctest.h Normal file
View file

@ -0,0 +1,92 @@
/*
* Original file:
* Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
* All rights reserved.
*
* Port to Contiki:
* Copyright (c) 2013, ADVANSEE - http://www.advansee.com/
* Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup cc2538-rfcore
* @{
*
* \file
* Header with declarations of CCTEST module registers.
*/
#ifndef CCTEST_H
#define CCTEST_H
/*---------------------------------------------------------------------------*/
/**
* \name CCTEST register offsets
* @{
*/
#define CCTEST_IO 0x44010000 /**< Output strength control */
#define CCTEST_OBSSEL0 0x44010014 /**< Observation output 0 */
#define CCTEST_OBSSEL1 0x44010018 /**< Observation output 1 */
#define CCTEST_OBSSEL2 0x4401001C /**< Observation output 2 */
#define CCTEST_OBSSEL3 0x44010020 /**< Observation output 3 */
#define CCTEST_OBSSEL4 0x44010024 /**< Observation output 4 */
#define CCTEST_OBSSEL5 0x44010028 /**< Observation output 5 */
#define CCTEST_OBSSEL6 0x4401002C /**< Observation output 6 */
#define CCTEST_OBSSEL7 0x44010030 /**< Observation output 7 */
#define CCTEST_TR0 0x44010034 /**< Test register 0 */
#define CCTEST_USBCTRL 0x44010050 /**< USB PHY stand-by control */
/** @} */
/*---------------------------------------------------------------------------*/
/** \name CCTEST_IO register bit fields
* @{
*/
#define CCTEST_IO_SC 0x00000001 /**< I/O strength control */
/** @} */
/*---------------------------------------------------------------------------*/
/** \name CCTEST_OBSSELx registers bit fields
* @{
*/
#define CCTEST_OBSSEL_EN 0x00000080 /**< Observation output enable */
#define CCTEST_OBSSEL_SEL_M 0x0000007F /**< n - obs_sigs[n] output selection mask */
#define CCTEST_OBSSEL_SEL_S 0 /**< n - obs_sigs[n] output selection shift */
/** @} */
/*---------------------------------------------------------------------------*/
/** \name CCTEST_TR0 register bit fields
* @{
*/
#define CCTEST_TR0_ADCTM 0x00000002 /**< Connect temperature sensor to ADC */
/** @} */
/*---------------------------------------------------------------------------*/
/** \name CCTEST_USBCTRL register bit fields
* @{
*/
#define CCTEST_USBCTRL_USB_STB 0x00000001 /**< USB PHY stand-by override */
/** @} */
#endif /* CCTEST_H */
/** @} */

View file

@ -575,6 +575,8 @@
* @{ * @{
*/ */
#define RFCORE_XREG_ATEST_ATEST_CTRL 0x0000003F /**< Controls the analog test mode */ #define RFCORE_XREG_ATEST_ATEST_CTRL 0x0000003F /**< Controls the analog test mode */
#define RFCORE_XREG_ATEST_ATEST_CTRL_DIS 0x00000000 /**< Analog test mode: disabled */
#define RFCORE_XREG_ATEST_ATEST_CTRL_TEMP 0x00000001 /**< Analog test mode: enable temperature sensor */
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name RFCORE_XREG_PTEST0 register bit masks /** \name RFCORE_XREG_PTEST0 register bit masks

View file

@ -83,6 +83,34 @@
#define SOC_ADC_ADCCON3_ECH 0x0000000F /**< Single channel select */ #define SOC_ADC_ADCCON3_ECH 0x0000000F /**< Single channel select */
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name SOC_ADC_ADCCONx registers field values
* @{
*/
#define SOC_ADC_ADCCON_REF_INT (0 << 6) /**< Internal reference */
#define SOC_ADC_ADCCON_REF_EXT_SINGLE (1 << 6) /**< External reference on AIN7 pin */
#define SOC_ADC_ADCCON_REF_AVDD5 (2 << 6) /**< AVDD5 pin */
#define SOC_ADC_ADCCON_REF_EXT_DIFF (3 << 6) /**< External reference on AIN6-AIN7 differential input */
#define SOC_ADC_ADCCON_DIV_64 (0 << 4) /**< 64 decimation rate (7 bits ENOB) */
#define SOC_ADC_ADCCON_DIV_128 (1 << 4) /**< 128 decimation rate (9 bits ENOB) */
#define SOC_ADC_ADCCON_DIV_256 (2 << 4) /**< 256 decimation rate (10 bits ENOB) */
#define SOC_ADC_ADCCON_DIV_512 (3 << 4) /**< 512 decimation rate (12 bits ENOB) */
#define SOC_ADC_ADCCON_CH_AIN0 0x0 /**< AIN0 */
#define SOC_ADC_ADCCON_CH_AIN1 0x1 /**< AIN1 */
#define SOC_ADC_ADCCON_CH_AIN2 0x2 /**< AIN2 */
#define SOC_ADC_ADCCON_CH_AIN3 0x3 /**< AIN3 */
#define SOC_ADC_ADCCON_CH_AIN4 0x4 /**< AIN4 */
#define SOC_ADC_ADCCON_CH_AIN5 0x5 /**< AIN5 */
#define SOC_ADC_ADCCON_CH_AIN6 0x6 /**< AIN6 */
#define SOC_ADC_ADCCON_CH_AIN7 0x7 /**< AIN7 */
#define SOC_ADC_ADCCON_CH_AIN0_AIN1 0x8 /**< AIN0-AIN1 */
#define SOC_ADC_ADCCON_CH_AIN2_AIN3 0x9 /**< AIN2-AIN3 */
#define SOC_ADC_ADCCON_CH_AIN4_AIN5 0xA /**< AIN4-AIN5 */
#define SOC_ADC_ADCCON_CH_AIN6_AIN7 0xB /**< AIN6-AIN7 */
#define SOC_ADC_ADCCON_CH_GND 0xC /**< GND */
#define SOC_ADC_ADCCON_CH_TEMP 0xE /**< Temperature sensor */
#define SOC_ADC_ADCCON_CH_VDD_3 0xF /**< VDD/3 */
/** @} */
/*---------------------------------------------------------------------------*/
/** \name SOC_ADC_ADC[L:H] register bit masks /** \name SOC_ADC_ADC[L:H] register bit masks
* @{ * @{
*/ */

View file

@ -48,23 +48,6 @@
#define SPI_MOSI_PIN_MASK GPIO_PIN_MASK(SPI_MOSI_PIN) #define SPI_MOSI_PIN_MASK GPIO_PIN_MASK(SPI_MOSI_PIN)
#define SPI_MISO_PORT_BASE GPIO_PORT_TO_BASE(SPI_MISO_PORT) #define SPI_MISO_PORT_BASE GPIO_PORT_TO_BASE(SPI_MISO_PORT)
#define SPI_MISO_PIN_MASK GPIO_PIN_MASK(SPI_MISO_PIN) #define SPI_MISO_PIN_MASK GPIO_PIN_MASK(SPI_MISO_PIN)
#define SPI_SEL_PORT_BASE GPIO_PORT_TO_BASE(SPI_SEL_PORT)
#define SPI_SEL_PIN_MASK GPIO_PIN_MASK(SPI_SEL_PIN)
/* Default: Motorola mode 3 with 8-bit data words */
#ifndef SPI_CONF_PHASE
#define SPI_CONF_PHASE SSI_CR0_SPH
#endif
#ifndef SPI_CONF_POLARITY
#define SPI_CONF_POLARITY SSI_CR0_SPO
#endif
#ifndef SPI_CONF_DATA_SIZE
#define SPI_CONF_DATA_SIZE 8
#endif
#if SPI_CONF_DATA_SIZE < 4 || SPI_CONF_DATA_SIZE > 16
#error SPI_CONF_DATA_SIZE must be set between 4 and 16 inclusive.
#endif
/** /**
* \brief Initialize the SPI bus. * \brief Initialize the SPI bus.
@ -73,12 +56,11 @@
* 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
* SPI_SEL_PORT SPI_SEL_PIN
* *
* This sets the mode to Motorola SPI with the following format options: * This sets the mode to Motorola SPI with the following format options:
* SPI_CONF_PHASE: 0 or SSI_CR0_SPH * Clock phase: 1; data captured on second (rising) edge
* SPI_CONF_POLARITY: 0 or SSI_CR0_SPO * Clock polarity: 1; clock is high when idle
* SPI_CONF_DATA_SIZE: 4 to 16 bits * Data size: 8 bits
*/ */
void void
spi_init(void) spi_init(void)
@ -95,31 +77,42 @@ spi_init(void)
ioc_set_sel(SPI_CLK_PORT, SPI_CLK_PIN, IOC_PXX_SEL_SSI0_CLKOUT); ioc_set_sel(SPI_CLK_PORT, SPI_CLK_PIN, IOC_PXX_SEL_SSI0_CLKOUT);
ioc_set_sel(SPI_MOSI_PORT, SPI_MOSI_PIN, IOC_PXX_SEL_SSI0_TXD); ioc_set_sel(SPI_MOSI_PORT, SPI_MOSI_PIN, IOC_PXX_SEL_SSI0_TXD);
REG(IOC_SSIRXD_SSI0) = (SPI_MISO_PORT * 8) + SPI_MISO_PIN; REG(IOC_SSIRXD_SSI0) = (SPI_MISO_PORT * 8) + SPI_MISO_PIN;
ioc_set_sel(SPI_SEL_PORT, SPI_SEL_PIN, IOC_PXX_SEL_SSI0_FSSOUT);
/* Put all the SSI gpios into peripheral mode */ /* Put all the SSI gpios into peripheral mode */
GPIO_PERIPHERAL_CONTROL(SPI_CLK_PORT_BASE, SPI_CLK_PIN_MASK); GPIO_PERIPHERAL_CONTROL(SPI_CLK_PORT_BASE, SPI_CLK_PIN_MASK);
GPIO_PERIPHERAL_CONTROL(SPI_MOSI_PORT_BASE, SPI_MOSI_PIN_MASK); GPIO_PERIPHERAL_CONTROL(SPI_MOSI_PORT_BASE, SPI_MOSI_PIN_MASK);
GPIO_PERIPHERAL_CONTROL(SPI_MISO_PORT_BASE, SPI_MISO_PIN_MASK); GPIO_PERIPHERAL_CONTROL(SPI_MISO_PORT_BASE, SPI_MISO_PIN_MASK);
GPIO_PERIPHERAL_CONTROL(SPI_SEL_PORT_BASE, SPI_SEL_PIN_MASK);
/* Disable any pull ups or the like */ /* Disable any pull ups or the like */
ioc_set_over(SPI_CLK_PORT, SPI_CLK_PIN, IOC_OVERRIDE_DIS); ioc_set_over(SPI_CLK_PORT, SPI_CLK_PIN, IOC_OVERRIDE_DIS);
ioc_set_over(SPI_MOSI_PORT, SPI_MOSI_PIN, IOC_OVERRIDE_DIS); ioc_set_over(SPI_MOSI_PORT, SPI_MOSI_PIN, IOC_OVERRIDE_DIS);
ioc_set_over(SPI_MISO_PORT, SPI_MISO_PIN, IOC_OVERRIDE_DIS); ioc_set_over(SPI_MISO_PORT, SPI_MISO_PIN, IOC_OVERRIDE_DIS);
ioc_set_over(SPI_SEL_PORT, SPI_SEL_PIN, IOC_OVERRIDE_DIS);
/* Configure the clock */ /* Configure the clock */
REG(SSI0_BASE + SSI_CPSR) = 2; REG(SSI0_BASE + SSI_CPSR) = 2;
/* Put the ssi in Motorola SPI mode using the provided format options */ /* Configure the default SPI options.
REG(SSI0_BASE + SSI_CR0) = SPI_CONF_PHASE | SPI_CONF_POLARITY | (SPI_CONF_DATA_SIZE - 1); * mode: Motorola frame format
* clock: High when idle
* data: Valid on rising edges of the clock
* bits: 8 byte data
*/
REG(SSI0_BASE + SSI_CR0) = SSI_CR0_SPH | SSI_CR0_SPO | (0x07);
/* Enable the SSI */ /* Enable the SSI */
REG(SSI0_BASE + SSI_CR1) |= SSI_CR1_SSE; REG(SSI0_BASE + SSI_CR1) |= SSI_CR1_SSE;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
spi_cs_init(uint8_t port, uint8_t pin)
{
GPIO_SOFTWARE_CONTROL(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin));
ioc_set_over(port, pin, IOC_OVERRIDE_DIS);
GPIO_SET_OUTPUT(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin));
GPIO_SET_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin));
}
/*---------------------------------------------------------------------------*/
void
spi_enable(void) spi_enable(void)
{ {
/* Enable the clock for the SSI peripheral */ /* Enable the clock for the SSI peripheral */
@ -132,4 +125,16 @@ spi_disable(void)
/* Gate the clock for the SSI peripheral */ /* Gate the clock for the SSI peripheral */
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)
{
/* Disable the SSI peripheral to configure it */
REG(SSI0_BASE + SSI_CR1) = 0;
/* Configure the SSI options */
REG(SSI0_BASE + SSI_CR0) = clock_phase | clock_polarity | frame_format | (data_size - 1);
/* Re-enable the SSI */
REG(SSI0_BASE + SSI_CR1) |= SSI_CR1_SSE;
}
/** @} */ /** @} */

View file

@ -74,98 +74,106 @@
*/ */
#define SSI_CR0_SCR_M 0x0000FF00 /**< Serial clock rate mask */ #define SSI_CR0_SCR_M 0x0000FF00 /**< Serial clock rate mask */
#define SSI_CR0_SCR_S 8 /**< Serial clock rate shift */ #define SSI_CR0_SCR_S 8 /**< Serial clock rate shift */
#define SSI_CR0_SPH 0x00000080 /**< Serial clock phase (H) */
#define SSI_CR0_SPH_M 0x00000080 /**< Serial clock phase (H) mask */ #define SSI_CR0_SPH_M 0x00000080 /**< Serial clock phase (H) mask */
#define SSI_CR0_SPH_S 7 /**< Serial clock phase (H) shift */ #define SSI_CR0_SPH_S 7 /**< Serial clock phase (H) shift */
#define SSI_CR0_SPO 0x00000040 /**< Serial clock phase (O) */
#define SSI_CR0_SPO_M 0x00000040 /**< Serial clock phase (O) mask */ #define SSI_CR0_SPO_M 0x00000040 /**< Serial clock phase (O) mask */
#define SSI_CR0_SPO_S 6 /**< Serial clock phase (O) shift */ #define SSI_CR0_SPO_S 6 /**< Serial clock phase (O) shift */
#define SSI_CR0_FRF_M 0x00000030 /**< Frame format select mask */ #define SSI_CR0_FRF_M 0x00000030 /**< Frame format select mask */
#define SSI_CR0_FRF_S 4 /**< Frame format select shift */ #define SSI_CR0_FRF_S 4 /**< Frame format select shift */
#define SSI_CR0_DSS_M 0x0000000F /**< Data size select mask */ #define SSI_CR0_DSS_M 0x0000000F /**< Data size select mask */
#define SSI_CR0_DSS_S 0 /**< Data size select shift */ #define SSI_CR0_DSS_S 0 /**< Data size select shift */
#define SSI_CR1_SOD 0x00000008 /**< Slave mode output disable */
#define SSI_CR1_SOD_M 0x00000008 /**< Slave mode output disable mask */ #define SSI_CR1_SOD_M 0x00000008 /**< Slave mode output disable mask */
#define SSI_CR1_SOD_S 3 /**< Slave mode output disable shift */ #define SSI_CR1_SOD_S 3 /**< Slave mode output disable shift */
#define SSI_CR1_MS 0x00000004 /**< Master and slave select */
#define SSI_CR1_MS_M 0x00000004 /**< Master and slave select mask */ #define SSI_CR1_MS_M 0x00000004 /**< Master and slave select mask */
#define SSI_CR1_MS_S 2 /**< Master and slave select shift */ #define SSI_CR1_MS_S 2 /**< Master and slave select shift */
#define SSI_CR1_SSE 0x00000002 /**< Synchronous serial port enable */
#define SSI_CR1_SSE_M 0x00000002 /**< Synchronous serial port enable mask */ #define SSI_CR1_SSE_M 0x00000002 /**< Synchronous serial port enable mask */
#define SSI_CR1_SSE_S 1 /**< Synchronous serial port enable shift */ #define SSI_CR1_SSE_S 1 /**< Synchronous serial port enable shift */
#define SSI_CR1_LBM 0x00000001 /**< Loop-back mode */
#define SSI_CR1_LBM_M 0x00000001 /**< Loop-back mode mask */ #define SSI_CR1_LBM_M 0x00000001 /**< Loop-back mode mask */
#define SSI_CR1_LBM_S 0 /**< Loop-back mode shift */ #define SSI_CR1_LBM_S 0 /**< Loop-back mode shift */
#define SSI_DR_DATA_M 0x0000FFFF /**< FIFO data mask */ #define SSI_DR_DATA_M 0x0000FFFF /**< FIFO data mask */
#define SSI_DR_DATA_S 0 /**< FIFO data shift */ #define SSI_DR_DATA_S 0 /**< FIFO data shift */
#define SSI_SR_BSY 0x00000010 /**< Busy bit */
#define SSI_SR_BSY_M 0x00000010 /**< Busy bit mask */ #define SSI_SR_BSY_M 0x00000010 /**< Busy bit mask */
#define SSI_SR_BSY_S 4 /**< Busy bit shift */ #define SSI_SR_BSY_S 4 /**< Busy bit shift */
#define SSI_SR_RFF 0x00000008 /**< Receive FIFO full */
#define SSI_SR_RFF_M 0x00000008 /**< Receive FIFO full mask */ #define SSI_SR_RFF_M 0x00000008 /**< Receive FIFO full mask */
#define SSI_SR_RFF_S 3 /**< Receive FIFO full shift */ #define SSI_SR_RFF_S 3 /**< Receive FIFO full shift */
#define SSI_SR_RNE 0x00000004 /**< Receive FIFO not empty */
#define SSI_SR_RNE_M 0x00000004 /**< Receive FIFO not empty mask */ #define SSI_SR_RNE_M 0x00000004 /**< Receive FIFO not empty mask */
#define SSI_SR_RNE_S 2 /**< Receive FIFO not empty shift */ #define SSI_SR_RNE_S 2 /**< Receive FIFO not empty shift */
#define SSI_SR_TNF 0x00000002 /**< Transmit FIFO not full */
#define SSI_SR_TNF_M 0x00000002 /**< Transmit FIFO not full mask */ #define SSI_SR_TNF_M 0x00000002 /**< Transmit FIFO not full mask */
#define SSI_SR_TNF_S 1 /**< Transmit FIFO not full shift */ #define SSI_SR_TNF_S 1 /**< Transmit FIFO not full shift */
#define SSI_SR_TFE 0x00000001 /**< Transmit FIFO empty */
#define SSI_SR_TFE_M 0x00000001 /**< Transmit FIFO empty mask */ #define SSI_SR_TFE_M 0x00000001 /**< Transmit FIFO empty mask */
#define SSI_SR_TFE_S 0 /**< Transmit FIFO empty shift */ #define SSI_SR_TFE_S 0 /**< Transmit FIFO empty shift */
#define SSI_CPSR_CPSDVSR_M 0x000000FF /**< Clock prescale divisor mask */ #define SSI_CPSR_CPSDVSR_M 0x000000FF /**< Clock prescale divisor mask */
#define SSI_CPSR_CPSDVSR_S 0 /**< Clock prescale divisor shift */ #define SSI_CPSR_CPSDVSR_S 0 /**< Clock prescale divisor shift */
#define SSI_IM_TXIM 0x00000008 /**< Transmit FIFO interrupt mask */
#define SSI_IM_TXIM_M 0x00000008 /**< Transmit FIFO interrupt mask mask */ #define SSI_IM_TXIM_M 0x00000008 /**< Transmit FIFO interrupt mask mask */
#define SSI_IM_TXIM_S 3 /**< Transmit FIFO interrupt mask shift */ #define SSI_IM_TXIM_S 3 /**< Transmit FIFO interrupt mask shift */
#define SSI_IM_RXIM 0x00000004 /**< Receive FIFO interrupt mask */
#define SSI_IM_RXIM_M 0x00000004 /**< Receive FIFO interrupt mask mask */ #define SSI_IM_RXIM_M 0x00000004 /**< Receive FIFO interrupt mask mask */
#define SSI_IM_RXIM_S 2 /**< Receive FIFO interrupt mask shift */ #define SSI_IM_RXIM_S 2 /**< Receive FIFO interrupt mask shift */
#define SSI_IM_RTIM 0x00000002 /**< Receive time-out interrupt mask */
#define SSI_IM_RTIM_M 0x00000002 /**< Receive time-out interrupt mask mask */ #define SSI_IM_RTIM_M 0x00000002 /**< Receive time-out interrupt mask mask */
#define SSI_IM_RTIM_S 1 /**< Receive time-out interrupt mask shift */ #define SSI_IM_RTIM_S 1 /**< Receive time-out interrupt mask shift */
#define SSI_IM_RORIM 0x00000001 /**< Receive overrun interrupt mask */
#define SSI_IM_RORIM_M 0x00000001 /**< Receive overrun interrupt mask mask */ #define SSI_IM_RORIM_M 0x00000001 /**< Receive overrun interrupt mask mask */
#define SSI_IM_RORIM_S 0 /**< Receive overrun interrupt mask shift */ #define SSI_IM_RORIM_S 0 /**< Receive overrun interrupt mask shift */
#define SSI_RIS_TXRIS 0x00000008 /**< SSITXINTR raw state */
#define SSI_RIS_TXRIS_M 0x00000008 /**< SSITXINTR raw state mask */ #define SSI_RIS_TXRIS_M 0x00000008 /**< SSITXINTR raw state mask */
#define SSI_RIS_TXRIS_S 3 /**< SSITXINTR raw state shift */ #define SSI_RIS_TXRIS_S 3 /**< SSITXINTR raw state shift */
#define SSI_RIS_RXRIS 0x00000004 /**< SSIRXINTR raw state */
#define SSI_RIS_RXRIS_M 0x00000004 /**< SSIRXINTR raw state mask */ #define SSI_RIS_RXRIS_M 0x00000004 /**< SSIRXINTR raw state mask */
#define SSI_RIS_RXRIS_S 2 /**< SSIRXINTR raw state shift */ #define SSI_RIS_RXRIS_S 2 /**< SSIRXINTR raw state shift */
#define SSI_RIS_RTRIS 0x00000002 /**< SSIRTINTR raw state */
#define SSI_RIS_RTRIS_M 0x00000002 /**< SSIRTINTR raw state mask */ #define SSI_RIS_RTRIS_M 0x00000002 /**< SSIRTINTR raw state mask */
#define SSI_RIS_RTRIS_S 1 /**< SSIRTINTR raw state shift */ #define SSI_RIS_RTRIS_S 1 /**< SSIRTINTR raw state shift */
#define SSI_RIS_RORRIS 0x00000001 /**< SSIRORINTR raw state */
#define SSI_RIS_RORRIS_M 0x00000001 /**< SSIRORINTR raw state mask */ #define SSI_RIS_RORRIS_M 0x00000001 /**< SSIRORINTR raw state mask */
#define SSI_RIS_RORRIS_S 0 /**< SSIRORINTR raw state shift */ #define SSI_RIS_RORRIS_S 0 /**< SSIRORINTR raw state shift */
#define SSI_MIS_TXMIS 0x00000008 /**< SSITXINTR masked state */
#define SSI_MIS_TXMIS_M 0x00000008 /**< SSITXINTR masked state mask */ #define SSI_MIS_TXMIS_M 0x00000008 /**< SSITXINTR masked state mask */
#define SSI_MIS_TXMIS_S 3 /**< SSITXINTR masked state shift */ #define SSI_MIS_TXMIS_S 3 /**< SSITXINTR masked state shift */
#define SSI_MIS_RXMIS 0x00000004 /**< SSIRXINTR masked state */
#define SSI_MIS_RXMIS_M 0x00000004 /**< SSIRXINTR masked state mask */ #define SSI_MIS_RXMIS_M 0x00000004 /**< SSIRXINTR masked state mask */
#define SSI_MIS_RXMIS_S 2 /**< SSIRXINTR masked state shift */ #define SSI_MIS_RXMIS_S 2 /**< SSIRXINTR masked state shift */
#define SSI_MIS_RTMIS 0x00000002 /**< SSIRTINTR masked state */
#define SSI_MIS_RTMIS_M 0x00000002 /**< SSIRTINTR masked state mask */ #define SSI_MIS_RTMIS_M 0x00000002 /**< SSIRTINTR masked state mask */
#define SSI_MIS_RTMIS_S 1 /**< SSIRTINTR masked state shift */ #define SSI_MIS_RTMIS_S 1 /**< SSIRTINTR masked state shift */
#define SSI_MIS_RORMIS 0x00000001 /**< SSIRORINTR masked state */
#define SSI_MIS_RORMIS_M 0x00000001 /**< SSIRORINTR masked state mask */ #define SSI_MIS_RORMIS_M 0x00000001 /**< SSIRORINTR masked state mask */
#define SSI_MIS_RORMIS_S 0 /**< SSIRORINTR masked state shift */ #define SSI_MIS_RORMIS_S 0 /**< SSIRORINTR masked state shift */
#define SSI_ICR_RTIC 0x00000002 /**< Receive time-out interrupt clear */
#define SSI_ICR_RTIC_M 0x00000002 /**< Receive time-out interrupt clear mask */ #define SSI_ICR_RTIC_M 0x00000002 /**< Receive time-out interrupt clear mask */
#define SSI_ICR_RTIC_S 1 /**< Receive time-out interrupt clear shift */ #define SSI_ICR_RTIC_S 1 /**< Receive time-out interrupt clear shift */
#define SSI_ICR_RORIC 0x00000001 /**< Receive overrun interrupt clear */
#define SSI_ICR_RORIC_M 0x00000001 /**< Receive overrun interrupt clear mask */ #define SSI_ICR_RORIC_M 0x00000001 /**< Receive overrun interrupt clear mask */
#define SSI_ICR_RORIC_S 0 /**< Receive overrun interrupt clear shift */ #define SSI_ICR_RORIC_S 0 /**< Receive overrun interrupt clear shift */
#define SSI_DMACTL_TXDMAE 0x00000002 /**< Transmit DMA enable */
#define SSI_DMACTL_TXDMAE_M 0x00000002 /**< Transmit DMA enable mask */ #define SSI_DMACTL_TXDMAE_M 0x00000002 /**< Transmit DMA enable mask */
#define SSI_DMACTL_TXDMAE_S 1 /**< Transmit DMA enable shift */ #define SSI_DMACTL_TXDMAE_S 1 /**< Transmit DMA enable shift */
#define SSI_DMACTL_RXDMAE 0x00000001 /**< Receive DMA enable */
#define SSI_DMACTL_RXDMAE_M 0x00000001 /**< Receive DMA enable mask */ #define SSI_DMACTL_RXDMAE_M 0x00000001 /**< Receive DMA enable mask */
#define SSI_DMACTL_RXDMAE_S 0 /**< Receive DMA enable shift */ #define SSI_DMACTL_RXDMAE_S 0 /**< Receive DMA enable shift */
#define SSI_CC_CS_M 0x00000007 /**< Baud and system clock source mask */ #define SSI_CC_CS_M 0x00000007 /**< Baud and system clock source mask */
#define SSI_CC_CS_S 0 /**< Baud and system clock source shift */ #define SSI_CC_CS_S 0 /**< Baud and system clock source shift */
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/
/** \name SSI Register Values
* @{
*/
#define SSI_CR0_SPH 0x00000080 /**< Serial clock phase (H) */
#define SSI_CR0_SPO 0x00000040 /**< Serial clock phase (O) */
#define SSI_CR0_FRF_MOTOROLA 0x00000000 /**< Motorola frame format */
#define SSI_CR0_FRF_TI 0x00000010 /**< Texas Instruments frame format */
#define SSI_CR0_FRF_MICROWIRE 0x00000020 /**< National Microwire frame format */
#define SSI_CR1_SOD 0x00000008 /**< Slave mode output disable */
#define SSI_CR1_MS 0x00000004 /**< Master and slave select */
#define SSI_CR1_SSE 0x00000002 /**< Synchronous serial port enable */
#define SSI_CR1_LBM 0x00000001 /**< Loop-back mode */
#define SSI_SR_BSY 0x00000010 /**< Busy bit */
#define SSI_SR_RFF 0x00000008 /**< Receive FIFO full */
#define SSI_SR_RNE 0x00000004 /**< Receive FIFO not empty */
#define SSI_SR_TNF 0x00000002 /**< Transmit FIFO not full */
#define SSI_SR_TFE 0x00000001 /**< Transmit FIFO empty */
#define SSI_IM_TXIM 0x00000008 /**< Transmit FIFO interrupt mask */
#define SSI_IM_RXIM 0x00000004 /**< Receive FIFO interrupt mask */
#define SSI_IM_RTIM 0x00000002 /**< Receive time-out interrupt mask */
#define SSI_IM_RORIM 0x00000001 /**< Receive overrun interrupt mask */
#define SSI_RIS_TXRIS 0x00000008 /**< SSITXINTR raw state */
#define SSI_RIS_RXRIS 0x00000004 /**< SSIRXINTR raw state */
#define SSI_RIS_RTRIS 0x00000002 /**< SSIRTINTR raw state */
#define SSI_RIS_RORRIS 0x00000001 /**< SSIRORINTR raw state */
#define SSI_MIS_TXMIS 0x00000008 /**< SSITXINTR masked state */
#define SSI_MIS_RXMIS 0x00000004 /**< SSIRXINTR masked state */
#define SSI_MIS_RTMIS 0x00000002 /**< SSIRTINTR masked state */
#define SSI_MIS_RORMIS 0x00000001 /**< SSIRORINTR masked state */
#define SSI_ICR_RTIC 0x00000002 /**< Receive time-out interrupt clear */
#define SSI_ICR_RORIC 0x00000001 /**< Receive overrun interrupt clear */
#define SSI_DMACTL_TXDMAE 0x00000002 /**< Transmit DMA enable */
#define SSI_DMACTL_RXDMAE 0x00000001 /**< Receive DMA enable */
/** @} */
#endif #endif
/** /**

View file

@ -48,88 +48,220 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
static int (* input_handler)(unsigned char c); #ifndef UART0_RX_PORT
/*---------------------------------------------------------------------------*/ #define UART0_RX_PORT (-1)
#define UART_RX_PORT_BASE GPIO_PORT_TO_BASE(UART_RX_PORT) #endif
#define UART_RX_PIN_MASK GPIO_PIN_MASK(UART_RX_PIN) #ifndef UART0_RX_PIN
#define UART0_RX_PIN (-1)
#endif
#if UART0_RX_PORT >= 0 && UART0_RX_PIN < 0 || \
UART0_RX_PORT < 0 && UART0_RX_PIN >= 0
#error Both UART0_RX_PORT and UART0_RX_PIN must be valid or invalid
#endif
#define UART_TX_PORT_BASE GPIO_PORT_TO_BASE(UART_TX_PORT) #ifndef UART0_TX_PORT
#define UART_TX_PIN_MASK GPIO_PIN_MASK(UART_TX_PIN) #define UART0_TX_PORT (-1)
#endif
#ifndef UART0_TX_PIN
#define UART0_TX_PIN (-1)
#endif
#if UART0_TX_PORT >= 0 && UART0_TX_PIN < 0 || \
UART0_TX_PORT < 0 && UART0_TX_PIN >= 0
#error Both UART0_TX_PORT and UART0_TX_PIN must be valid or invalid
#endif
#define UART_CTS_PORT_BASE GPIO_PORT_TO_BASE(UART_CTS_PORT) #if UART0_RX_PORT >= 0 && UART0_TX_PORT < 0 || \
#define UART_CTS_PIN_MASK GPIO_PIN_MASK(UART_CTS_PIN) UART0_RX_PORT < 0 && UART0_TX_PORT >= 0
#error Both UART0_RX and UART0_TX pads must be valid or invalid
#endif
#define UART_RTS_PORT_BASE GPIO_PORT_TO_BASE(UART_RTS_PORT) #if UART_IN_USE(0) && UART0_RX_PORT < 0
#define UART_RTS_PIN_MASK GPIO_PIN_MASK(UART_RTS_PIN) #error Contiki is configured to use UART0, but its pads are not valid
/*---------------------------------------------------------------------------*/ #endif
/*
* Once we know what UART we're on, configure correct values to be written to
* the correct registers
*/
#if UART_BASE==UART_1_BASE
/* Running, in sleep, in deep sleep, enable the clock for the correct UART */
#define SYS_CTRL_RCGCUART_UART SYS_CTRL_RCGCUART_UART1
#define SYS_CTRL_SCGCUART_UART SYS_CTRL_SCGCUART_UART1
#define SYS_CTRL_DCGCUART_UART SYS_CTRL_DCGCUART_UART1
#define NVIC_INT_UART NVIC_INT_UART1 #ifndef UART1_RX_PORT
#define IOC_PXX_SEL_UART_TXD IOC_PXX_SEL_UART1_TXD #define UART1_RX_PORT (-1)
#define IOC_UARTRXD_UART IOC_UARTRXD_UART1 #endif
#else /* Defaults for UART0 */ #ifndef UART1_RX_PIN
#define SYS_CTRL_RCGCUART_UART SYS_CTRL_RCGCUART_UART0 #define UART1_RX_PIN (-1)
#define SYS_CTRL_SCGCUART_UART SYS_CTRL_SCGCUART_UART0 #endif
#define SYS_CTRL_DCGCUART_UART SYS_CTRL_DCGCUART_UART0 #if UART1_RX_PORT >= 0 && UART1_RX_PIN < 0 || \
UART1_RX_PORT < 0 && UART1_RX_PIN >= 0
#error Both UART1_RX_PORT and UART1_RX_PIN must be valid or invalid
#endif
#define NVIC_INT_UART NVIC_INT_UART0 #ifndef UART1_TX_PORT
#define UART1_TX_PORT (-1)
#endif
#ifndef UART1_TX_PIN
#define UART1_TX_PIN (-1)
#endif
#if UART1_TX_PORT >= 0 && UART1_TX_PIN < 0 || \
UART1_TX_PORT < 0 && UART1_TX_PIN >= 0
#error Both UART1_TX_PORT and UART1_TX_PIN must be valid or invalid
#endif
#define IOC_PXX_SEL_UART_TXD IOC_PXX_SEL_UART0_TXD #if UART1_RX_PORT >= 0 && UART1_TX_PORT < 0 || \
#define IOC_UARTRXD_UART IOC_UARTRXD_UART0 UART1_RX_PORT < 0 && UART1_TX_PORT >= 0
#error Both UART1_RX and UART1_TX pads must be valid or invalid
#endif
#if UART_IN_USE(1) && UART1_RX_PORT < 0
#error Contiki is configured to use UART1, but its pads are not valid
#endif
#ifndef UART1_CTS_PORT
#define UART1_CTS_PORT (-1)
#endif
#ifndef UART1_CTS_PIN
#define UART1_CTS_PIN (-1)
#endif
#if UART1_CTS_PORT >= 0 && UART1_CTS_PIN < 0 || \
UART1_CTS_PORT < 0 && UART1_CTS_PIN >= 0
#error Both UART1_CTS_PORT and UART1_CTS_PIN must be valid or invalid
#endif
#ifndef UART1_RTS_PORT
#define UART1_RTS_PORT (-1)
#endif
#ifndef UART1_RTS_PIN
#define UART1_RTS_PIN (-1)
#endif
#if UART1_RTS_PORT >= 0 && UART1_RTS_PIN < 0 || \
UART1_RTS_PORT < 0 && UART1_RTS_PIN >= 0
#error Both UART1_RTS_PORT and UART1_RTS_PIN must be valid or invalid
#endif #endif
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/*
* Baud rate defines used in uart_init() to set the values of UART_IBRD and
* UART_FBRD in order to achieve the configured baud rates.
*/
#define UART_CLOCK_RATE 16000000 /* 16 MHz */
#define UART_CTL_HSE_VALUE 0
#define UART_CTL_VALUE (UART_CTL_RXE | UART_CTL_TXE | (UART_CTL_HSE_VALUE << 5))
/* DIV_ROUND() divides integers while avoiding a rounding error: */
#define DIV_ROUND(num, denom) (((num) + (denom) / 2) / (denom))
#define BAUD2BRD(baud) DIV_ROUND(UART_CLOCK_RATE << (UART_CTL_HSE_VALUE + 2), (baud))
#define BAUD2IBRD(baud) (BAUD2BRD(baud) >> 6)
#define BAUD2FBRD(baud) (BAUD2BRD(baud) & 0x3f)
/*---------------------------------------------------------------------------*/
typedef struct {
int8_t port;
int8_t pin;
} uart_pad_t;
typedef struct {
uint32_t sys_ctrl_rcgcuart_uart;
uint32_t sys_ctrl_scgcuart_uart;
uint32_t sys_ctrl_dcgcuart_uart;
uint32_t base;
uint32_t ioc_uartrxd_uart;
uint32_t ioc_pxx_sel_uart_txd;
uint32_t ibrd;
uint32_t fbrd;
uart_pad_t rx;
uart_pad_t tx;
uart_pad_t cts;
uart_pad_t rts;
uint8_t nvic_int;
} uart_regs_t;
/*---------------------------------------------------------------------------*/
static const uart_regs_t uart_regs[UART_INSTANCE_COUNT] = {
{
.sys_ctrl_rcgcuart_uart = SYS_CTRL_RCGCUART_UART0,
.sys_ctrl_scgcuart_uart = SYS_CTRL_SCGCUART_UART0,
.sys_ctrl_dcgcuart_uart = SYS_CTRL_DCGCUART_UART0,
.base = UART_0_BASE,
.ioc_uartrxd_uart = IOC_UARTRXD_UART0,
.ioc_pxx_sel_uart_txd = IOC_PXX_SEL_UART0_TXD,
.ibrd = BAUD2IBRD(UART0_CONF_BAUD_RATE),
.fbrd = BAUD2FBRD(UART0_CONF_BAUD_RATE),
.rx = {UART0_RX_PORT, UART0_RX_PIN},
.tx = {UART0_TX_PORT, UART0_TX_PIN},
.cts = {-1, -1},
.rts = {-1, -1},
.nvic_int = NVIC_INT_UART0
}, {
.sys_ctrl_rcgcuart_uart = SYS_CTRL_RCGCUART_UART1,
.sys_ctrl_scgcuart_uart = SYS_CTRL_SCGCUART_UART1,
.sys_ctrl_dcgcuart_uart = SYS_CTRL_DCGCUART_UART1,
.base = UART_1_BASE,
.ioc_uartrxd_uart = IOC_UARTRXD_UART1,
.ioc_pxx_sel_uart_txd = IOC_PXX_SEL_UART1_TXD,
.ibrd = BAUD2IBRD(UART1_CONF_BAUD_RATE),
.fbrd = BAUD2FBRD(UART1_CONF_BAUD_RATE),
.rx = {UART1_RX_PORT, UART1_RX_PIN},
.tx = {UART1_TX_PORT, UART1_TX_PIN},
.cts = {UART1_CTS_PORT, UART1_CTS_PIN},
.rts = {UART1_RTS_PORT, UART1_RTS_PIN},
.nvic_int = NVIC_INT_UART1
}
};
static int (* input_handler[UART_INSTANCE_COUNT])(unsigned char c);
/*---------------------------------------------------------------------------*/
static void static void
reset(void) reset(uint32_t uart_base)
{ {
uint32_t lchr; uint32_t lchr;
/* Make sure the UART is disabled before trying to configure it */ /* Make sure the UART is disabled before trying to configure it */
REG(UART_BASE | UART_CTL) = UART_CTL_TXE | UART_CTL_RXE; REG(uart_base | UART_CTL) = UART_CTL_VALUE;
/* Clear error status */ /* Clear error status */
REG(UART_BASE | UART_ECR) = 0xFF; REG(uart_base | UART_ECR) = 0xFF;
/* Store LCHR configuration */ /* Store LCHR configuration */
lchr = REG(UART_BASE | UART_LCRH); lchr = REG(uart_base | UART_LCRH);
/* Flush FIFOs by clearing LCHR.FEN */ /* Flush FIFOs by clearing LCHR.FEN */
REG(UART_BASE | UART_LCRH) = 0; REG(uart_base | UART_LCRH) = 0;
/* Restore LCHR configuration */ /* Restore LCHR configuration */
REG(UART_BASE | UART_LCRH) = lchr; REG(uart_base | UART_LCRH) = lchr;
/* UART Enable */ /* UART Enable */
REG(UART_BASE | UART_CTL) |= UART_CTL_UARTEN; REG(uart_base | UART_CTL) |= UART_CTL_UARTEN;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
static bool static bool
permit_pm1(void) permit_pm1(void)
{ {
/* Note: UART_FR.TXFE reads 0 if the UART clock is gated. */ const uart_regs_t *regs;
return (REG(SYS_CTRL_RCGCUART) & SYS_CTRL_RCGCUART_UART) == 0 ||
(REG(UART_BASE | UART_FR) & UART_FR_TXFE) != 0; for(regs = &uart_regs[0]; regs < &uart_regs[UART_INSTANCE_COUNT]; regs++) {
/* Note: UART_FR.TXFE reads 0 if the UART clock is gated. */
if((REG(SYS_CTRL_RCGCUART) & regs->sys_ctrl_rcgcuart_uart) != 0 &&
(REG(regs->base | UART_FR) & UART_FR_TXFE) == 0) {
return false;
}
}
return true;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uart_init(void) uart_init(uint8_t uart)
{ {
const uart_regs_t *regs;
if(uart >= UART_INSTANCE_COUNT) {
return;
}
regs = &uart_regs[uart];
if(regs->rx.port < 0 || regs->tx.port < 0) {
return;
}
lpm_register_peripheral(permit_pm1); lpm_register_peripheral(permit_pm1);
/* Enable clock for the UART while Running, in Sleep and Deep Sleep */ /* Enable clock for the UART while Running, in Sleep and Deep Sleep */
REG(SYS_CTRL_RCGCUART) |= SYS_CTRL_RCGCUART_UART; REG(SYS_CTRL_RCGCUART) |= regs->sys_ctrl_rcgcuart_uart;
REG(SYS_CTRL_SCGCUART) |= SYS_CTRL_SCGCUART_UART; REG(SYS_CTRL_SCGCUART) |= regs->sys_ctrl_scgcuart_uart;
REG(SYS_CTRL_DCGCUART) |= SYS_CTRL_DCGCUART_UART; REG(SYS_CTRL_DCGCUART) |= regs->sys_ctrl_dcgcuart_uart;
/* Run on SYS_DIV */ /* Run on SYS_DIV */
REG(UART_BASE | UART_CC) = 0; REG(regs->base | UART_CC) = 0;
/* /*
* Select the UARTx RX pin by writing to the IOC_UARTRXD_UARTn register * Select the UARTx RX pin by writing to the IOC_UARTRXD_UARTn register
@ -139,92 +271,116 @@ uart_init(void)
* *
* (port << 3) + pin * (port << 3) + pin
*/ */
REG(IOC_UARTRXD_UART) = (UART_RX_PORT << 3) + UART_RX_PIN; REG(regs->ioc_uartrxd_uart) = (regs->rx.port << 3) + regs->rx.pin;
/* /*
* Pad Control for the TX pin: * Pad Control for the TX pin:
* - Set function to UART0 TX * - Set function to UARTn TX
* - Output Enable * - Output Enable
*/ */
ioc_set_sel(UART_TX_PORT, UART_TX_PIN, IOC_PXX_SEL_UART_TXD); ioc_set_sel(regs->tx.port, regs->tx.pin, regs->ioc_pxx_sel_uart_txd);
ioc_set_over(UART_TX_PORT, UART_TX_PIN, IOC_OVERRIDE_OE); ioc_set_over(regs->tx.port, regs->tx.pin, IOC_OVERRIDE_OE);
/* Set RX and TX pins to peripheral mode */ /* Set RX and TX pins to peripheral mode */
GPIO_PERIPHERAL_CONTROL(UART_TX_PORT_BASE, UART_TX_PIN_MASK); GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->tx.port),
GPIO_PERIPHERAL_CONTROL(UART_RX_PORT_BASE, UART_RX_PIN_MASK); GPIO_PIN_MASK(regs->tx.pin));
GPIO_PERIPHERAL_CONTROL(GPIO_PORT_TO_BASE(regs->rx.port),
GPIO_PIN_MASK(regs->rx.pin));
if(regs->cts.port >= 0 || regs->rts.port >= 0) {
/* TODO Hardware flow control */
}
/* /*
* UART Interrupt Masks: * UART Interrupt Masks:
* Acknowledge RX and RX Timeout * Acknowledge RX and RX Timeout
* Acknowledge Framing, Overrun and Break Errors * Acknowledge Framing, Overrun and Break Errors
*/ */
REG(UART_BASE | UART_IM) = UART_IM_RXIM | UART_IM_RTIM; REG(regs->base | UART_IM) = UART_IM_RXIM | UART_IM_RTIM;
REG(UART_BASE | UART_IM) |= UART_IM_OEIM | UART_IM_BEIM | UART_IM_FEIM; REG(regs->base | UART_IM) |= UART_IM_OEIM | UART_IM_BEIM | UART_IM_FEIM;
REG(UART_BASE | UART_IFLS) = REG(regs->base | UART_IFLS) =
UART_IFLS_RXIFLSEL_1_8 | UART_IFLS_TXIFLSEL_1_2; UART_IFLS_RXIFLSEL_1_8 | UART_IFLS_TXIFLSEL_1_2;
/* Make sure the UART is disabled before trying to configure it */ /* Make sure the UART is disabled before trying to configure it */
REG(UART_BASE | UART_CTL) = UART_CTL_TXE | UART_CTL_RXE; REG(regs->base | UART_CTL) = UART_CTL_VALUE;
/* Baud Rate Generation */ /* Baud Rate Generation */
REG(UART_BASE | UART_IBRD) = UART_CONF_IBRD; REG(regs->base | UART_IBRD) = regs->ibrd;
REG(UART_BASE | UART_FBRD) = UART_CONF_FBRD; REG(regs->base | UART_FBRD) = regs->fbrd;
/* UART Control: 8N1 with FIFOs */ /* UART Control: 8N1 with FIFOs */
REG(UART_BASE | UART_LCRH) = UART_LCRH_WLEN_8 | UART_LCRH_FEN; REG(regs->base | UART_LCRH) = UART_LCRH_WLEN_8 | UART_LCRH_FEN;
/* UART Enable */ /* UART Enable */
REG(UART_BASE | UART_CTL) |= UART_CTL_UARTEN; REG(regs->base | UART_CTL) |= UART_CTL_UARTEN;
/* Enable UART0 Interrupts */ /* Enable UART0 Interrupts */
nvic_interrupt_enable(NVIC_INT_UART); nvic_interrupt_enable(regs->nvic_int);
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uart_set_input(int (* input)(unsigned char c)) uart_set_input(uint8_t uart, int (* input)(unsigned char c))
{ {
input_handler = input; if(uart >= UART_INSTANCE_COUNT) {
} return;
/*---------------------------------------------------------------------------*/ }
void
uart_write_byte(uint8_t b)
{
/* Block if the TX FIFO is full */
while(REG(UART_BASE | UART_FR) & UART_FR_TXFF);
REG(UART_BASE | UART_DR) = b; input_handler[uart] = input;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
void void
uart_isr(void) uart_write_byte(uint8_t uart, uint8_t b)
{ {
uint32_t uart_base;
if(uart >= UART_INSTANCE_COUNT) {
return;
}
uart_base = uart_regs[uart].base;
/* Block if the TX FIFO is full */
while(REG(uart_base | UART_FR) & UART_FR_TXFF);
REG(uart_base | UART_DR) = b;
}
/*---------------------------------------------------------------------------*/
void
uart_isr(uint8_t uart)
{
uint32_t uart_base;
uint16_t mis; uint16_t mis;
ENERGEST_ON(ENERGEST_TYPE_IRQ); ENERGEST_ON(ENERGEST_TYPE_IRQ);
uart_base = uart_regs[uart].base;
/* Store the current MIS and clear all flags early, except the RTM flag. /* Store the current MIS and clear all flags early, except the RTM flag.
* This will clear itself when we read out the entire FIFO contents */ * This will clear itself when we read out the entire FIFO contents */
mis = REG(UART_BASE | UART_MIS) & 0x0000FFFF; mis = REG(uart_base | UART_MIS) & 0x0000FFFF;
REG(UART_BASE | UART_ICR) = 0x0000FFBF; REG(uart_base | UART_ICR) = 0x0000FFBF;
if(mis & (UART_MIS_RXMIS | UART_MIS_RTMIS)) { if(mis & (UART_MIS_RXMIS | UART_MIS_RTMIS)) {
while(!(REG(UART_BASE | UART_FR) & UART_FR_RXFE)) { while(!(REG(uart_base | UART_FR) & UART_FR_RXFE)) {
if(input_handler != NULL) { if(input_handler[uart] != NULL) {
input_handler((unsigned char)(REG(UART_BASE | UART_DR) & 0xFF)); input_handler[uart]((unsigned char)(REG(uart_base | UART_DR) & 0xFF));
} else { } else {
/* To prevent an Overrun Error, we need to flush the FIFO even if we /* To prevent an Overrun Error, we need to flush the FIFO even if we
* don't have an input_handler. Use mis as a data trash can */ * don't have an input_handler. Use mis as a data trash can */
mis = REG(UART_BASE | UART_DR); mis = REG(uart_base | UART_DR);
} }
} }
} else if(mis & (UART_MIS_OEMIS | UART_MIS_BEMIS | UART_MIS_FEMIS)) { } else if(mis & (UART_MIS_OEMIS | UART_MIS_BEMIS | UART_MIS_FEMIS)) {
/* ISR triggered due to some error condition */ /* ISR triggered due to some error condition */
reset(); reset(uart_base);
} }
ENERGEST_OFF(ENERGEST_TYPE_IRQ); ENERGEST_OFF(ENERGEST_TYPE_IRQ);
} }
/*---------------------------------------------------------------------------*/
#define UART_ISR(u) void uart##u##_isr(void) { uart_isr(u); }
UART_ISR(0)
UART_ISR(1)
/** @} */ /** @} */

View file

@ -47,52 +47,17 @@
#include <stdint.h> #include <stdint.h>
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name UART instance count
* @{
*/
#define UART_INSTANCE_COUNT 2
/** @} */
/*---------------------------------------------------------------------------*/
/** \name UART base addresses /** \name UART base addresses
* @{ * @{
*/ */
#define UART_0_BASE 0x4000C000 #define UART_0_BASE 0x4000C000
#define UART_1_BASE 0x4000D000 #define UART_1_BASE 0x4000D000
/* Default to UART 0 unless the configuration tells us otherwise */
#ifdef UART_CONF_BASE
#define UART_BASE UART_CONF_BASE
#else
#define UART_BASE UART_0_BASE
#endif
/** @} */
/*---------------------------------------------------------------------------*/
/**
* \name Baud rate defines
*
* Used in uart_init() to set the values of UART_IBRD and UART_FBRD in order to
* achieve some standard baud rates. These defines assume that the UART is
* clocked at 16MHz and that Clock Div is 16 (UART_CTL:HSE clear)
* @{
*/
#define UART_IBRD_115200 8 /**< IBRD value for baud rate 115200 */
#define UART_FBRD_115200 44 /**< FBRD value for baud rate 115200 */
#define UART_IBRD_230400 4 /**< IBRD value for baud rate 230400 */
#define UART_FBRD_230400 22 /**< FBRD value for baud rate 230400 */
#define UART_IBRD_460800 2 /**< IBRD value for baud rate 460800 */
#define UART_FBRD_460800 11 /**< FBRD value for baud rate 460800 */
#if UART_CONF_BAUD_RATE==115200
#define UART_CONF_IBRD UART_IBRD_115200
#define UART_CONF_FBRD UART_FBRD_115200
#elif UART_CONF_BAUD_RATE==230400
#define UART_CONF_IBRD UART_IBRD_230400
#define UART_CONF_FBRD UART_FBRD_230400
#elif UART_CONF_BAUD_RATE==460800
#define UART_CONF_IBRD UART_IBRD_460800
#define UART_CONF_FBRD UART_FBRD_460800
#else /* Bail out with an error unless the user provided custom values */
#if !(defined UART_CONF_IBRD && defined UART_CONF_FBRD)
#error "UART baud rate misconfigured and custom IBRD/FBRD values not provided"
#error "Check the value of UART_CONF_BAUD_RATE in contiki-conf.h or project-conf.h"
#error "Supported values are 115200, 230400 and 460800. Alternatively, you can"
#error "provide custom values for UART_CONF_IBRD and UART_CONF_FBRD"
#endif
#endif
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name UART Register Offsets /** \name UART Register Offsets
@ -366,18 +331,22 @@
*/ */
/** \brief Initialises the UART controller, configures I/O control /** \brief Initialises the UART controller, configures I/O control
* and interrupts */ * and interrupts
void uart_init(void); * \param uart The UART instance to use (0 to \c UART_INSTANCE_COUNT - 1)
*/
void uart_init(uint8_t uart);
/** \brief Sends a single character down the UART /** \brief Sends a single character down the UART
* \param uart The UART instance to use (0 to \c UART_INSTANCE_COUNT - 1)
* \param b The character to transmit * \param b The character to transmit
*/ */
void uart_write_byte(uint8_t b); void uart_write_byte(uint8_t uart, uint8_t b);
/** \brief Assigns a callback to be called when the UART receives a byte /** \brief Assigns a callback to be called when the UART receives a byte
* \param uart The UART instance to use (0 to \c UART_INSTANCE_COUNT - 1)
* \param input A pointer to the function * \param input A pointer to the function
*/ */
void uart_set_input(int (* input)(unsigned char c)); void uart_set_input(uint8_t uart, int (* input)(unsigned char c));
/** @} */ /** @} */

View file

@ -44,7 +44,7 @@
#include "dev/uart.h" #include "dev/uart.h"
#define BAUD2UBR(x) x #define BAUD2UBR(x) x
#define uart1_set_input(f) uart_set_input(f) #define uart1_set_input(f) uart_set_input(UART1_CONF_UART, f)
#endif /* UART1_H_ */ #endif /* UART1_H_ */

View file

@ -52,7 +52,7 @@ ieee_addr_cpy_to(uint8_t *dst, uint8_t len)
/* Reading from Info Page, we need to invert byte order */ /* Reading from Info Page, we need to invert byte order */
int i; int i;
for(i = 0; i < len; i++) { for(i = 0; i < len; i++) {
dst[i] = ((uint8_t *)IEEE_ADDR_LOCATION_PRIMARY)[len - 1 - i]; dst[i] = ((uint8_t *)IEEE_ADDR_LOCATION)[len - 1 - i];
} }
} }

View file

@ -53,6 +53,18 @@
* @{ * @{
*/ */
#define IEEE_ADDR_LOCATION_PRIMARY 0x00280028 /**< IEEE address location */ #define IEEE_ADDR_LOCATION_PRIMARY 0x00280028 /**< IEEE address location */
#define IEEE_ADDR_LOCATION_SECONDARY 0x0027FFCC /**< IEEE address location */
/** @} */
/*---------------------------------------------------------------------------*/
/**
* \brief Select which address location to use
* @{
*/
#if IEEE_ADDR_CONF_USE_SECONDARY_LOCATION
#define IEEE_ADDR_LOCATION IEEE_ADDR_LOCATION_SECONDARY
#else
#define IEEE_ADDR_LOCATION IEEE_ADDR_LOCATION_PRIMARY
#endif
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*

View file

@ -88,14 +88,11 @@ rtimer_clock_t lpm_stats[3];
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* /*
* Remembers what time it was when went to deep sleep * Remembers what time it was when went to deep sleep
* This is used when coming out of PM1/2 to adjust the system clock, which * This is used when coming out of PM0/1/2 to keep stats
* stops ticking while in those PMs
*/ */
static rtimer_clock_t sleep_enter_time; static rtimer_clock_t sleep_enter_time;
#define RTIMER_CLOCK_TICK_RATIO (RTIMER_SECOND / CLOCK_SECOND) void clock_adjust(void);
void clock_adjust(clock_time_t ticks);
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* Stores the currently specified MAX allowed PM */ /* Stores the currently specified MAX allowed PM */
static uint8_t max_pm; static uint8_t max_pm;
@ -137,10 +134,7 @@ enter_pm0(void)
/* We are only interested in IRQ energest while idle or in LPM */ /* We are only interested in IRQ energest while idle or in LPM */
ENERGEST_IRQ_RESTORE(irq_energest); ENERGEST_IRQ_RESTORE(irq_energest);
/* /* Remember the current time so we can keep stats when we wake up */
* After PM0 we don't need to adjust the system clock. Thus, saving the time
* we enter Deep Sleep is only required if we are keeping stats.
*/
if(LPM_CONF_STATS) { if(LPM_CONF_STATS) {
sleep_enter_time = RTIMER_NOW(); sleep_enter_time = RTIMER_NOW();
} }
@ -215,10 +209,8 @@ lpm_exit()
RTIMER_NOW() - sleep_enter_time); RTIMER_NOW() - sleep_enter_time);
/* Adjust the system clock, since it was not counting while we were sleeping /* Adjust the system clock, since it was not counting while we were sleeping
* We need to convert sleep duration from rtimer ticks to clock ticks and * We need to convert sleep duration from rtimer ticks to clock ticks */
* this will cost us some accuracy */ clock_adjust();
clock_adjust((clock_time_t)
((RTIMER_NOW() - sleep_enter_time) / RTIMER_CLOCK_TICK_RATIO));
/* Restore system clock to the 32 MHz XOSC */ /* Restore system clock to the 32 MHz XOSC */
select_32_mhz_xosc(); select_32_mhz_xosc();
@ -306,8 +298,10 @@ lpm_enter()
ENERGEST_OFF(ENERGEST_TYPE_CPU); ENERGEST_OFF(ENERGEST_TYPE_CPU);
ENERGEST_ON(ENERGEST_TYPE_LPM); ENERGEST_ON(ENERGEST_TYPE_LPM);
/* Remember the current time so we can adjust the clock when we wake up */ /* Remember the current time so we can keep stats when we wake up */
sleep_enter_time = RTIMER_NOW(); if(LPM_CONF_STATS) {
sleep_enter_time = RTIMER_NOW();
}
/* /*
* Last chance to abort entering Deep Sleep. * Last chance to abort entering Deep Sleep.

View file

@ -52,8 +52,8 @@
#define set_input(f) usb_serial_set_input(f) #define set_input(f) usb_serial_set_input(f)
#define flush() usb_serial_flush() #define flush() usb_serial_flush()
#else #else
#define write_byte(b) uart_write_byte(b) #define write_byte(b) uart_write_byte(SLIP_ARCH_CONF_UART, b)
#define set_input(f) uart_set_input(f) #define set_input(f) uart_set_input(SLIP_ARCH_CONF_UART, f)
#define flush() #define flush()
#endif #endif

View file

@ -41,27 +41,51 @@
#ifndef SPI_ARCH_H_ #ifndef SPI_ARCH_H_
#define SPI_ARCH_H_ #define SPI_ARCH_H_
#include "contiki.h"
#include "dev/ssi.h" #include "dev/ssi.h"
#define SPI_WAITFORTxREADY() do { \ #define SPI_WAITFORTxREADY() do { \
while(!(REG(SSI0_BASE + SSI_SR) & SSI_SR_TNF)); \ while(!(REG(SSI0_BASE + SSI_SR) & SSI_SR_TNF)); \
} while (0) } while(0)
#define SPI_TXBUF REG(SSI0_BASE + SSI_DR) #define SPI_TXBUF REG(SSI0_BASE + SSI_DR)
#define SPI_RXBUF REG(SSI0_BASE + SSI_DR) #define SPI_RXBUF REG(SSI0_BASE + SSI_DR)
#define SPI_WAITFOREOTx() do { \ #define SPI_WAITFOREOTx() do { \
while(REG(SSI0_BASE + SSI_SR) & SSI_SR_BSY); \ while(REG(SSI0_BASE + SSI_SR) & SSI_SR_BSY); \
} while (0) } while(0)
#define SPI_WAITFOREORx() do { \ #define SPI_WAITFOREORx() do { \
while(!(REG(SSI0_BASE + SSI_SR) & SSI_SR_RNE)); \ while(!(REG(SSI0_BASE + SSI_SR) & SSI_SR_RNE)); \
} while (0) } while(0)
#ifdef SPI_FLUSH
#error "You must include spi-arch.h before spi.h for the CC2538."
#endif
#define SPI_FLUSH() do { \
SPI_WAITFOREORx(); \
while (REG(SSI0_BASE + SSI_SR) & SSI_SR_RNE) { \
SPI_RXBUF; \
} \
} while(0)
#define SPI_CS_CLR(port, pin) do { \
GPIO_CLR_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); \
} while(0)
#define SPI_CS_SET(port, pin) do { \
GPIO_SET_PIN(GPIO_PORT_TO_BASE(port), GPIO_PIN_MASK(pin)); \
} while(0)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name Arch-specific SPI functions /** \name Arch-specific SPI functions
* @{ * @{
*/ */
/**
* \brief Configure a GPIO to be the chip select pin
*/
void spi_cs_init(uint8_t port, uint8_t pin);
/** \brief Enables the SPI peripheral /** \brief Enables the SPI peripheral
*/ */
void spi_enable(void); void spi_enable(void);
@ -71,6 +95,27 @@ void spi_enable(void);
*/ */
void spi_disable(void); void spi_disable(void);
/**
* \brief Configure the SPI data and clock polarity and the data size.
*
* This function configures the SSI peripheral to use a particular SPI
* configuration that a slave device requires. It should always be called
* before using the SPI bus as another driver could have changed the settings.
*
* See section 19.4.4 in the CC2538 user guide for more information.
*
* \param frame_format Set the SSI frame format. Use SSI_CR0_FRF_MOTOROLA,
* SSI_CR0_FRF_TI, or SSI_CR0_FRF_MICROWIRE.
* \param clock_polarity In Motorola mode, set whether the clock is high or low
* when idle. Use SSI_CR0_SPO or 0.
* \param clock_phase In Motorola mode, select whether data is valid on the
* first or second edge of the clock. Use SSI_CR0_SPH or 0.
* \param data_size The number of bits in each "byte" of data. Must be
* between 4 and 16, inclusive.
*/
void spi_set_mode(uint32_t frame_format, uint32_t clock_polarity,
uint32_t clock_phase, uint32_t data_size);
/** @} */ /** @} */
#endif /* SPI_ARCH_H_ */ #endif /* SPI_ARCH_H_ */

View file

@ -88,7 +88,8 @@ LDFLAGSNO += -D_STACK_SIZE=$(IAR_STACK_SIZE) -D_DATA16_HEAP_SIZE=$(IAR_DATA16_HE
CUSTOM_RULE_C_TO_O = 1 CUSTOM_RULE_C_TO_O = 1
%.o: %.c %.o: %.c
$(CC) $(CFLAGS) $< -o $@ $(TRACE_CC)
$(Q)$(CC) $(CFLAGS) $< -o $@
define FINALIZE_CYGWIN_DEPENDENCY define FINALIZE_CYGWIN_DEPENDENCY
sed -e 's/ \([A-Z]\):\\/ \/cygdrive\/\L\1\//' -e 's/\\/\//g' \ sed -e 's/ \([A-Z]\):\\/ \/cygdrive\/\L\1\//' -e 's/\\/\//g' \
@ -98,14 +99,16 @@ endef
CUSTOM_RULE_C_TO_OBJECTDIR_O = 1 CUSTOM_RULE_C_TO_OBJECTDIR_O = 1
$(OBJECTDIR)/%.o: %.c | $(OBJECTDIR) $(OBJECTDIR)/%.o: %.c | $(OBJECTDIR)
$(CC) $(CFLAGS) $< --dependencies=m $(@:.o=.P) -o $@ $(TRACE_CC)
$(Q)$(CC) $(CFLAGS) $< --dependencies=m $(@:.o=.P) -o $@
ifeq ($(HOST_OS),Windows) ifeq ($(HOST_OS),Windows)
@$(FINALIZE_CYGWIN_DEPENDENCY) @$(FINALIZE_CYGWIN_DEPENDENCY)
endif endif
CUSTOM_RULE_C_TO_CO = 1 CUSTOM_RULE_C_TO_CO = 1
%.co: %.c %.co: %.c
$(CC) $(CFLAGS) -DAUTOSTART_ENABLE $< -o $@ $(TRACE_CC)
$(Q)$(CC) $(CFLAGS) -DAUTOSTART_ENABLE $< -o $@
AROPTS = -o AROPTS = -o
@ -175,7 +178,8 @@ PROJECT_OBJECTFILES += ${addprefix $(OBJECTDIR)/,$(CONTIKI_TARGET_MAIN:.c=.o)}
$(STRIP) --strip-unneeded -g -x -o $@ $< $(STRIP) --strip-unneeded -g -x -o $@ $<
%.o: ${CONTIKI_TARGET}/loader/%.S %.o: ${CONTIKI_TARGET}/loader/%.S
$(AS) -o $(notdir $(<:.S=.o)) $< $(TRACE_AS)
$(Q)$(AS) -o $(notdir $(<:.S=.o)) $<
%.firmware: %.${TARGET} %.firmware: %.${TARGET}
mv $< $@ mv $< $@
@ -188,7 +192,15 @@ else
$(OBJCOPY) $^ -O ihex $@ $(OBJCOPY) $^ -O ihex $@
endif endif
%.mspsim: %.${TARGET} $(CONTIKI)/tools/mspsim/build.xml:
@echo '----------------'
@echo 'Could not find the MSPSim build file. Did you run "git submodule update --init"?'
@echo '----------------'
$(CONTIKI)/tools/mspsim/mspsim.jar: $(CONTIKI)/tools/mspsim/build.xml
(cd $(CONTIKI)/tools/mspsim && ant jar)
%.mspsim: %.${TARGET} ${CONTIKI}/tools/mspsim/mspsim.jar
java -jar ${CONTIKI}/tools/mspsim/mspsim.jar -platform=${TARGET} $< java -jar ${CONTIKI}/tools/mspsim/mspsim.jar -platform=${TARGET} $<
mspsim-maptable: contiki-${TARGET}.map mspsim-maptable: contiki-${TARGET}.map

View file

@ -83,68 +83,6 @@ msp430_init_dco(void)
/* DCO Internal Resistor */ /* DCO Internal Resistor */
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Start CPU with full speed (? good or bad?) and go downwards */
/*---------------------------------------------------------------------------*/
void
msp430_quick_synch_dco(void) {
uint16_t last;
uint16_t diff;
uint16_t dco_reg = 0x0fff;
uint8_t current_bit = 12;
uint16_t i;
/* DELTA_2 assumes an ACLK of 32768 Hz */
#define DELTA_2 ((MSP430_CPU_SPEED) / 32768)
/* Select SMCLK clock, and capture on ACLK for TBCCR6 */
TBCTL = TBSSEL1 | TBCLR;
TBCCTL6 = CCIS0 + CM0 + CAP;
/* start the timer */
TBCTL |= MC1;
BCSCTL1 = 0x8D | 7;
DCOCTL = 0xff; /* MAX SPEED ?? */
/* IDEA: do binary search - check MSB first, etc... */
/* 1 set current bit to zero - if to slow, put back to 1 */
while(current_bit--) {
/* first set the current bit to zero and check - we know that it is
set from start so ^ works (first bit = bit 11) */
dco_reg = dco_reg ^ (1 << current_bit); /* clear bit 11..10..9.. */
/* set dco registers */
DCOCTL = dco_reg & 0xff;
BCSCTL1 = (BCSCTL1 & 0xf8) | (dco_reg >> 8);
/* some delay to make clock stable - could possibly be made using
captures too ... */
for(i=0; i < 1000; i++) {
i = i | 1;
}
/* do capture... */
while(!(TBCCTL6 & CCIFG));
last = TBCCR6;
TBCCTL6 &= ~CCIFG;
/* wait for next Capture - and calculate difference */
while(!(TBCCTL6 & CCIFG));
diff = TBCCR6 - last;
/* /\* store what was run during the specific test *\/ */
/* dcos[current_bit] = dco_reg; */
/* vals[current_bit] = diff; */
/* should we keep the bit cleared or not ? */
if(diff < DELTA_2) { /* DCO is too slow - fewer ticks than desired */
/* toggle bit again to get it back to one */
dco_reg = dco_reg ^ (1 << current_bit);
}
}
}
/*---------------------------------------------------------------------------*/
static void static void
init_ports(void) init_ports(void)
{ {
@ -224,7 +162,10 @@ msp430_cpu_init(void)
dint(); dint();
watchdog_init(); watchdog_init();
init_ports(); init_ports();
msp430_quick_synch_dco(); /* set DCO to a reasonable default value (8MHz) */
msp430_init_dco();
/* calibrate the DCO step-by-step */
msp430_sync_dco();
eint(); eint();
#if defined(__MSP430__) && defined(__GNUC__) #if defined(__MSP430__) && defined(__GNUC__)
if((uintptr_t)cur_break & 1) { /* Workaround for msp430-ld bug! */ if((uintptr_t)cur_break & 1) { /* Workaround for msp430-ld bug! */
@ -282,13 +223,10 @@ int __low_level_init(void)
} }
#endif #endif
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
#if DCOSYNCH_CONF_ENABLED
/* this code will always start the TimerB if not already started */
void void
msp430_sync_dco(void) { msp430_sync_dco(void) {
uint16_t last; uint16_t oldcapture;
uint16_t diff; int16_t diff;
/* uint32_t speed; */
/* DELTA_2 assumes an ACLK of 32768 Hz */ /* DELTA_2 assumes an ACLK of 32768 Hz */
#define DELTA_2 ((MSP430_CPU_SPEED) / 32768) #define DELTA_2 ((MSP430_CPU_SPEED) / 32768)
@ -298,36 +236,35 @@ msp430_sync_dco(void) {
/* start the timer */ /* start the timer */
TBCTL |= MC1; TBCTL |= MC1;
/* wait for next Capture */ while(1) {
TBCCTL6 &= ~CCIFG; /* wait for the next capture */
while(!(TBCCTL6 & CCIFG)); TBCCTL6 &= ~CCIFG;
last = TBCCR6; while(!(TBCCTL6 & CCIFG));
oldcapture = TBCCR6;
TBCCTL6 &= ~CCIFG; /* wait for the next capture - and calculate difference */
/* wait for next Capture - and calculate difference */ TBCCTL6 &= ~CCIFG;
while(!(TBCCTL6 & CCIFG)); while(!(TBCCTL6 & CCIFG));
diff = TBCCR6 - last; diff = TBCCR6 - oldcapture;
/* Stop timer - conserves energy according to user guide */ /* resynchronize the DCO speed if not at target */
TBCTL = 0; if(DELTA_2 == diff) {
break; /* if equal, leave "while(1)" */
/* speed = diff; */ } else if(DELTA_2 < diff) { /* DCO is too fast, slow it down */
/* speed = speed * 32768; */ DCOCTL--;
/* printf("Last TAR diff:%d target: %ld ", diff, DELTA_2); */ if(DCOCTL == 0xFF) { /* Did DCO roll under? */
/* printf("CPU Speed: %lu DCOCTL: %d\n", speed, DCOCTL); */ BCSCTL1--;
}
/* resynchronize the DCO speed if not at target */ } else { /* -> Select next lower RSEL */
if(DELTA_2 < diff) { /* DCO is too fast, slow it down */ DCOCTL++;
DCOCTL--; if(DCOCTL == 0x00) { /* Did DCO roll over? */
if(DCOCTL == 0xFF) { /* Did DCO role under? */ BCSCTL1++;
BCSCTL1--; }
} /* -> Select next higher RSEL */
} else if(DELTA_2 > diff) {
DCOCTL++;
if(DCOCTL == 0x00) { /* Did DCO role over? */
BCSCTL1++;
} }
} }
/* Stop the timer - conserves energy according to user guide */
TBCTL = 0;
} }
#endif /* DCOSYNCH_CONF_ENABLED */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View file

@ -50,6 +50,8 @@
* - BTN_DOWN turns on LEDS_REBOOT and causes a watchdog reboot * - BTN_DOWN turns on LEDS_REBOOT and causes a watchdog reboot
* - BTN_UP to soft reset (SYS_CTRL_PWRDBG::FORCE_WARM_RESET) * - BTN_UP to soft reset (SYS_CTRL_PWRDBG::FORCE_WARM_RESET)
* - BTN_LEFT and BTN_RIGHT flash the LED defined as LEDS_BUTTON * - BTN_LEFT and BTN_RIGHT flash the LED defined as LEDS_BUTTON
* - ADC sensors : On-chip VDD / 3 and temperature, and ambient light sensor
* values are printed over UART periodically.
* - UART : Every LOOP_INTERVAL the EM will print something over the * - UART : Every LOOP_INTERVAL the EM will print something over the
* UART. Receiving an entire line of text over UART (ending * UART. Receiving an entire line of text over UART (ending
* in \\r) will cause LEDS_SERIAL_IN to toggle * in \\r) will cause LEDS_SERIAL_IN to toggle
@ -68,6 +70,7 @@
#include "dev/leds.h" #include "dev/leds.h"
#include "dev/uart.h" #include "dev/uart.h"
#include "dev/button-sensor.h" #include "dev/button-sensor.h"
#include "dev/adc-sensor.h"
#include "dev/watchdog.h" #include "dev/watchdog.h"
#include "dev/serial-line.h" #include "dev/serial-line.h"
#include "dev/sys-ctrl.h" #include "dev/sys-ctrl.h"
@ -111,6 +114,7 @@ rt_callback(struct rtimer *t, void *ptr)
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
PROCESS_THREAD(cc2538_demo_process, ev, data) PROCESS_THREAD(cc2538_demo_process, ev, data)
{ {
int16_t value;
PROCESS_EXITHANDLER(broadcast_close(&bc)) PROCESS_EXITHANDLER(broadcast_close(&bc))
@ -127,7 +131,18 @@ PROCESS_THREAD(cc2538_demo_process, ev, data)
if(ev == PROCESS_EVENT_TIMER) { if(ev == PROCESS_EVENT_TIMER) {
leds_on(LEDS_PERIODIC); leds_on(LEDS_PERIODIC);
printf("Counter = 0x%08x\n", counter); printf("-----------------------------------------\n"
"Counter = 0x%08x\n", counter);
value = adc_sensor.value(ADC_SENSOR_VDD_3);
printf("VDD = %d mV\n", value * (3 * 1190) / (2047 << 4));
value = adc_sensor.value(ADC_SENSOR_TEMP);
printf("Temperature = %d mC\n",
25000 + ((value >> 4) - 1422) * 10000 / 42);
value = adc_sensor.value(ADC_SENSOR_ALS);
printf("Ambient light sensor = %d raw\n", value);
etimer_set(&et, CLOCK_SECOND); etimer_set(&et, CLOCK_SECOND);
rtimer_set(&rt, RTIMER_NOW() + LEDS_OFF_HYSTERISIS, 1, rtimer_set(&rt, RTIMER_NOW() + LEDS_OFF_HYSTERISIS, 1,

View file

@ -42,7 +42,7 @@
#define CC2538_RF_CONF_AUTOACK 0 #define CC2538_RF_CONF_AUTOACK 0
#define NETSTACK_CONF_RDC stub_rdc_driver #define NETSTACK_CONF_RDC stub_rdc_driver
#define UART_CONF_BAUD_RATE 460800 #define UART0_CONF_BAUD_RATE 460800
#endif /* PROJECT_CONF_H_ */ #endif /* PROJECT_CONF_H_ */

View file

@ -528,7 +528,7 @@ event_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred
/* A post_handler that handles subscriptions/observing will be called for periodic resources by the framework. */ /* A post_handler that handles subscriptions/observing will be called for periodic resources by the framework. */
} }
/* Additionally, a handler function named [resource name]_event_handler must be implemented for each PERIODIC_RESOURCE defined. /* Additionally, a handler function named [resource name]_event_handler must be implemented for each EVENT_RESOURCE defined.
* It will be called by the REST manager process with the defined period. */ * It will be called by the REST manager process with the defined period. */
void void
event_event_handler(resource_t *r) event_event_handler(resource_t *r)

View file

@ -0,0 +1,11 @@
DEFINES+=PROJECT_CONF_H=\"project-conf.h\"
UIP_CONF_IPV6=1
CONTIKI_PROJECT = root intermediate sink
all: $(CONTIKI_PROJECT)
CONTIKI = ../../..
MODULES += core/net/ipv6/multicast
include $(CONTIKI)/Makefile.include

View file

@ -0,0 +1,64 @@
/*
* Copyright (c) 2010, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* This node is part of the RPL multicast example. It basically
* represents a node that does not join the multicast group
* but still knows how to forward multicast packets
* The example will work with or without any number of these nodes
*
* Also, performs some sanity checks for the contiki configuration
* and generates an error if the conf is bad
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#include "contiki.h"
#include "contiki-net.h"
#include "net/ipv6/multicast/uip-mcast6.h"
#if !UIP_CONF_IPV6 || !UIP_CONF_ROUTER || !UIP_CONF_IPV6_MULTICAST || !UIP_CONF_IPV6_RPL
#error "This example can not work with the current contiki configuration"
#error "Check the values of: UIP_CONF_IPV6, UIP_CONF_ROUTER, UIP_CONF_IPV6_RPL"
#endif
/*---------------------------------------------------------------------------*/
PROCESS(mcast_intermediate_process, "Intermediate Process");
AUTOSTART_PROCESSES(&mcast_intermediate_process);
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(mcast_intermediate_process, ev, data)
{
PROCESS_BEGIN();
PROCESS_END();
}
/*---------------------------------------------------------------------------*/

View file

@ -0,0 +1,257 @@
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<project EXPORT="discard">[APPS_DIR]/mrm</project>
<project EXPORT="discard">[APPS_DIR]/mspsim</project>
<project EXPORT="discard">[APPS_DIR]/avrora</project>
<project EXPORT="discard">[APPS_DIR]/serial_socket</project>
<project EXPORT="discard">[APPS_DIR]/collect-view</project>
<project EXPORT="discard">[APPS_DIR]/powertracker</project>
<simulation>
<title>Example of a uIPv6 network with multicast support</title>
<randomseed>123456</randomseed>
<motedelay_us>1000000</motedelay_us>
<radiomedium>
org.contikios.cooja.radiomediums.UDGM
<transmitting_range>50.0</transmitting_range>
<interference_range>50.0</interference_range>
<success_ratio_tx>1.0</success_ratio_tx>
<success_ratio_rx>1.0</success_ratio_rx>
</radiomedium>
<events>
<logoutput>40000</logoutput>
</events>
<motetype>
org.contikios.cooja.mspmote.SkyMoteType
<identifier>sky1</identifier>
<description>root</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/ipv6/multicast/root.c</source>
<commands EXPORT="discard">make root.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/ipv6/multicast/root.sky</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface>
</motetype>
<motetype>
org.contikios.cooja.mspmote.SkyMoteType
<identifier>sky2</identifier>
<description>intermediate</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/ipv6/multicast/intermediate.c</source>
<commands EXPORT="discard">make intermediate.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/ipv6/multicast/intermediate.sky</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface>
</motetype>
<motetype>
org.contikios.cooja.mspmote.SkyMoteType
<identifier>sky3</identifier>
<description>sink</description>
<source EXPORT="discard">[CONTIKI_DIR]/examples/ipv6/multicast/sink.c</source>
<commands EXPORT="discard">make sink.sky TARGET=sky</commands>
<firmware EXPORT="copy">[CONTIKI_DIR]/examples/ipv6/multicast/sink.sky</firmware>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyButton</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyFlash</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyCoffeeFilesystem</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspSerial</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyLED</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
<moteinterface>org.contikios.cooja.mspmote.interfaces.SkyTemperature</moteinterface>
</motetype>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>5.995813174969022</x>
<y>34.43129455447824</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>1</id>
</interface_config>
<motetype_identifier>sky1</motetype_identifier>
</mote>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>40.70237155931961</x>
<y>16.396742420332068</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>2</id>
</interface_config>
<motetype_identifier>sky2</motetype_identifier>
</mote>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>100.3720728044051</x>
<y>70.93197095432518</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>3</id>
</interface_config>
<motetype_identifier>sky3</motetype_identifier>
</mote>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>81.7376718406712</x>
<y>28.854291358797</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>4</id>
</interface_config>
<motetype_identifier>sky3</motetype_identifier>
</mote>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>-26.161520836433183</x>
<y>8.116006415286686</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>5</id>
</interface_config>
<motetype_identifier>sky3</motetype_identifier>
</mote>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>-34.57705675553882</x>
<y>92.87247531485058</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>6</id>
</interface_config>
<motetype_identifier>sky3</motetype_identifier>
</mote>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>39.86312587077661</x>
<y>59.603125741056246</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>7</id>
</interface_config>
<motetype_identifier>sky2</motetype_identifier>
</mote>
<mote>
<breakpoints />
<interface_config>
org.contikios.cooja.interfaces.Position
<x>1.4345607604759194</x>
<y>75.2481773153879</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.mspmote.interfaces.MspMoteID
<id>8</id>
</interface_config>
<motetype_identifier>sky2</motetype_identifier>
</mote>
</simulation>
<plugin>
org.contikios.cooja.plugins.SimControl
<width>318</width>
<z>0</z>
<height>192</height>
<location_x>0</location_x>
<location_y>0</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Visualizer
<plugin_config>
<skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.AddressVisualizerSkin</skin>
<viewport>3.914959956760176 0.0 0.0 3.914959956760176 300.2075734071477 -15.682931033747009</viewport>
</plugin_config>
<width>869</width>
<z>3</z>
<height>441</height>
<location_x>320</location_x>
<location_y>3</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.LogListener
<plugin_config>
<filter />
<formatted_time />
<coloring />
</plugin_config>
<width>1281</width>
<z>2</z>
<height>213</height>
<location_x>-1</location_x>
<location_y>714</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.RadioLogger
<plugin_config>
<split>117</split>
<formatted_time />
<showdups>false</showdups>
<hidenodests>false</hidenodests>
<analyzers name="6lowpan-pcap" />
</plugin_config>
<width>1280</width>
<z>1</z>
<height>268</height>
<location_x>0</location_x>
<location_y>445</location_y>
</plugin>
</simconf>

View file

@ -0,0 +1,69 @@
/*
* Copyright (c) 2010, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* Project specific configuration defines for the RPl multicast
* example.
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#ifndef PROJECT_CONF_H_
#define PROJECT_CONF_H_
#include "net/ipv6/multicast/uip-mcast6-engines.h"
/* Change this to switch engines. Engine codes in uip-mcast6-engines.h */
#define UIP_MCAST6_CONF_ENGINE UIP_MCAST6_ENGINE_ROLL_TM
/* For Imin: Use 16 over NullRDC, 64 over Contiki MAC */
#define ROLL_TM_CONF_IMIN_1 64
#undef UIP_CONF_IPV6_RPL
#undef UIP_CONF_ND6_SEND_RA
#undef UIP_CONF_ROUTER
#define UIP_CONF_IPV6_RPL 1
#define UIP_CONF_ND6_SEND_RA 0
#define UIP_CONF_ROUTER 1
#define UIP_MCAST6_ROUTE_CONF_ROUTES 1
#undef UIP_CONF_TCP
#define UIP_CONF_TCP 0
/* Code/RAM footprint savings so that things will fit on our device */
#undef UIP_CONF_DS6_NBR_NBU
#undef UIP_CONF_DS6_ROUTE_NBU
#define UIP_CONF_DS6_NBR_NBU 10
#define UIP_CONF_DS6_ROUTE_NBU 10
#endif /* PROJECT_CONF_H_ */

View file

@ -0,0 +1,171 @@
/*
* Copyright (c) 2010, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* This node is part of the RPL multicast example. It is an RPL root
* and sends a multicast message periodically. For the example to work,
* we need one of those nodes.
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#include "contiki.h"
#include "contiki-lib.h"
#include "contiki-net.h"
#include "net/ipv6/multicast/uip-mcast6.h"
#include <string.h>
#define DEBUG DEBUG_PRINT
#include "net/ip/uip-debug.h"
#include "net/rpl/rpl.h"
#define MAX_PAYLOAD_LEN 120
#define MCAST_SINK_UDP_PORT 3001 /* Host byte order */
#define SEND_INTERVAL CLOCK_SECOND /* clock ticks */
#define ITERATIONS 100 /* messages */
/* Start sending messages START_DELAY secs after we start so that routing can
* converge */
#define START_DELAY 60
static struct uip_udp_conn * mcast_conn;
static char buf[MAX_PAYLOAD_LEN];
static uint32_t seq_id;
#if !UIP_CONF_IPV6 || !UIP_CONF_ROUTER || !UIP_CONF_IPV6_MULTICAST || !UIP_CONF_IPV6_RPL
#error "This example can not work with the current contiki configuration"
#error "Check the values of: UIP_CONF_IPV6, UIP_CONF_ROUTER, UIP_CONF_IPV6_RPL"
#endif
/*---------------------------------------------------------------------------*/
PROCESS(rpl_root_process, "RPL ROOT, Multicast Sender");
AUTOSTART_PROCESSES(&rpl_root_process);
/*---------------------------------------------------------------------------*/
static void
multicast_send(void)
{
uint32_t id;
id = uip_htonl(seq_id);
memset(buf, 0, MAX_PAYLOAD_LEN);
memcpy(buf, &id, sizeof(seq_id));
PRINTF("Send to: ");
PRINT6ADDR(&mcast_conn->ripaddr);
PRINTF(" Remote Port %u,", uip_ntohs(mcast_conn->rport));
PRINTF(" (msg=0x%08lx)", (unsigned long)uip_ntohl(*((uint32_t *)buf)));
PRINTF(" %lu bytes\n", (unsigned long)sizeof(id));
seq_id++;
uip_udp_packet_send(mcast_conn, buf, sizeof(id));
}
/*---------------------------------------------------------------------------*/
static void
prepare_mcast(void)
{
uip_ipaddr_t ipaddr;
/*
* IPHC will use stateless multicast compression for this destination
* (M=1, DAC=0), with 32 inline bits (1E 89 AB CD)
*/
uip_ip6addr(&ipaddr, 0xFF1E,0,0,0,0,0,0x89,0xABCD);
mcast_conn = udp_new(&ipaddr, UIP_HTONS(MCAST_SINK_UDP_PORT), NULL);
}
/*---------------------------------------------------------------------------*/
static void
set_own_addresses(void)
{
int i;
uint8_t state;
rpl_dag_t *dag;
uip_ipaddr_t ipaddr;
uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
PRINTF("Our IPv6 addresses:\n");
for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
state = uip_ds6_if.addr_list[i].state;
if(uip_ds6_if.addr_list[i].isused && (state == ADDR_TENTATIVE || state
== ADDR_PREFERRED)) {
PRINTF(" ");
PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr);
PRINTF("\n");
if(state == ADDR_TENTATIVE) {
uip_ds6_if.addr_list[i].state = ADDR_PREFERRED;
}
}
}
/* Become root of a new DODAG with ID our global v6 address */
dag = rpl_set_root(RPL_DEFAULT_INSTANCE, &ipaddr);
if(dag != NULL) {
rpl_set_prefix(dag, &ipaddr, 64);
PRINTF("Created a new RPL dag with ID: ");
PRINT6ADDR(&dag->dag_id);
PRINTF("\n");
}
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(rpl_root_process, ev, data)
{
static struct etimer et;
PROCESS_BEGIN();
PRINTF("Multicast Engine: '%s'\n", UIP_MCAST6.name);
NETSTACK_MAC.off(1);
set_own_addresses();
prepare_mcast();
etimer_set(&et, START_DELAY * CLOCK_SECOND);
while(1) {
PROCESS_YIELD();
if(etimer_expired(&et)) {
if(seq_id == ITERATIONS) {
etimer_stop(&et);
} else {
multicast_send();
etimer_set(&et, SEND_INTERVAL);
}
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/

View file

@ -0,0 +1,136 @@
/*
* Copyright (c) 2010, Loughborough University - Computer Science
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This file is part of the Contiki operating system.
*/
/**
* \file
* This node is part of the RPL multicast example. It is a node that
* joins a multicast group and listens for messages. It also knows how
* to forward messages down the tree.
* For the example to work, we need one or more of those nodes.
*
* \author
* George Oikonomou - <oikonomou@users.sourceforge.net>
*/
#include "contiki.h"
#include "contiki-lib.h"
#include "contiki-net.h"
#include "net/ipv6/multicast/uip-mcast6.h"
#include <string.h>
#define DEBUG DEBUG_PRINT
#include "net/ip/uip-debug.h"
#define MCAST_SINK_UDP_PORT 3001 /* Host byte order */
static struct uip_udp_conn *sink_conn;
static uint16_t count;
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
#if !UIP_CONF_IPV6 || !UIP_CONF_ROUTER || !UIP_CONF_IPV6_MULTICAST || !UIP_CONF_IPV6_RPL
#error "This example can not work with the current contiki configuration"
#error "Check the values of: UIP_CONF_IPV6, UIP_CONF_ROUTER, UIP_CONF_IPV6_RPL"
#endif
/*---------------------------------------------------------------------------*/
PROCESS(mcast_sink_process, "Multicast Sink");
AUTOSTART_PROCESSES(&mcast_sink_process);
/*---------------------------------------------------------------------------*/
static void
tcpip_handler(void)
{
if(uip_newdata()) {
count++;
PRINTF("In: [0x%08lx], TTL %u, total %u\n",
uip_ntohl((unsigned long) *((uint32_t *)(uip_appdata))),
UIP_IP_BUF->ttl, count);
}
return;
}
/*---------------------------------------------------------------------------*/
static uip_ds6_maddr_t *
join_mcast_group(void)
{
uip_ipaddr_t addr;
uip_ds6_maddr_t *rv;
/* First, set our v6 global */
uip_ip6addr(&addr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
uip_ds6_set_addr_iid(&addr, &uip_lladdr);
uip_ds6_addr_add(&addr, 0, ADDR_AUTOCONF);
/*
* IPHC will use stateless multicast compression for this destination
* (M=1, DAC=0), with 32 inline bits (1E 89 AB CD)
*/
uip_ip6addr(&addr, 0xFF1E,0,0,0,0,0,0x89,0xABCD);
rv = uip_ds6_maddr_add(&addr);
if(rv) {
PRINTF("Joined multicast group ");
PRINT6ADDR(&uip_ds6_maddr_lookup(&addr)->ipaddr);
PRINTF("\n");
}
return rv;
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(mcast_sink_process, ev, data)
{
PROCESS_BEGIN();
PRINTF("Multicast Engine: '%s'\n", UIP_MCAST6.name);
if(join_mcast_group() == NULL) {
PRINTF("Failed to join multicast group\n");
PROCESS_EXIT();
}
count = 0;
sink_conn = udp_new(NULL, UIP_HTONS(0), NULL);
udp_bind(sink_conn, UIP_HTONS(MCAST_SINK_UDP_PORT));
PRINTF("Listening: ");
PRINT6ADDR(&sink_conn->ripaddr);
PRINTF(" local/remote port %u/%u\n",
UIP_HTONS(sink_conn->lport), UIP_HTONS(sink_conn->rport));
while(1) {
PROCESS_YIELD();
if(ev == tcpip_event) {
tcpip_handler();
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/

View file

@ -0,0 +1,5 @@
all: tcp-server
CONTIKI=../..
include $(CONTIKI)/Makefile.include

View file

@ -0,0 +1,119 @@
/*
* Copyright (c) 2012, Thingsquare, http://www.thingsquare.com/.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "contiki-net.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SERVER_PORT 80
static struct tcp_socket socket;
#define INPUTBUFSIZE 400
static uint8_t inputbuf[INPUTBUFSIZE];
#define OUTPUTBUFSIZE 400
static uint8_t outputbuf[OUTPUTBUFSIZE];
PROCESS(tcp_server_process, "TCP echo process");
AUTOSTART_PROCESSES(&tcp_server_process);
static uint8_t get_received;
static int bytes_to_send;
/*---------------------------------------------------------------------------*/
static int
input(struct tcp_socket *s, void *ptr,
const uint8_t *inputptr, int inputdatalen)
{
printf("input %d bytes '%s'\n", inputdatalen, inputptr);
if(!get_received) {
/* See if we have a full GET request in the buffer. */
if(strncmp((char *)inputptr, "GET /", 5) == 0 &&
atoi((char *)&inputptr[5]) != 0) {
bytes_to_send = atoi((char *)&inputptr[5]);
printf("bytes_to_send %d\n", bytes_to_send);
return 0;
}
printf("inputptr '%.*s'\n", inputdatalen, inputptr);
/* Return the number of data bytes we received, to keep them all
in the buffer. */
return inputdatalen;
} else {
/* Discard everything */
return 0; /* all data consumed */
}
}
/*---------------------------------------------------------------------------*/
static void
event(struct tcp_socket *s, void *ptr,
tcp_socket_event_t ev)
{
printf("event %d\n", ev);
}
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(tcp_server_process, ev, data)
{
PROCESS_BEGIN();
tcp_socket_register(&socket, NULL,
inputbuf, sizeof(inputbuf),
outputbuf, sizeof(outputbuf),
input, event);
tcp_socket_listen(&socket, SERVER_PORT);
printf("Listening on %d\n", SERVER_PORT);
while(1) {
PROCESS_PAUSE();
if(bytes_to_send > 0) {
/* Send header */
printf("sending header\n");
tcp_socket_send_str(&socket, "HTTP/1.0 200 ok\r\nServer: Contiki tcp-socket example\r\n\r\n");
/* Send data */
printf("sending data\n");
while(bytes_to_send > 0) {
PROCESS_PAUSE();
int len, tosend;
#define MIN(a,b) ((a)<(b)?(a):(b))
tosend = MIN(bytes_to_send, sizeof(outputbuf));
len = tcp_socket_send(&socket, (uint8_t *)"", tosend);
bytes_to_send -= len;
}
tcp_socket_close(&socket);
}
}
PROCESS_END();
}
/*---------------------------------------------------------------------------*/

View file

@ -7,8 +7,9 @@ so please consult cpu/6502/README.md for further details.
The following Apple II Ethernet cards are supported: The following Apple II Ethernet cards are supported:
- Uthernet: Use driver cs8900a.eth with address $C0x0 (x = 8 + slot number). - Uthernet: Use driver cs8900a.eth with address $C0x0 (x = 8 + slot number).
- LANceGS: Use driver lan91c96.eth with address $C0x0 (x = 8 + slot number). - Uthernet II: Use driver w5100.eth with address $C0x4 (x = 8 + slot number).
- LANceGS: Use driver lan91c96.eth with address $C0x0 (x = 8 + slot number).
In most cases it is desirable to use an emulator for the development and testing In most cases it is desirable to use an emulator for the development and testing
of a Contiki application. AppleWin is especially well suited as it emulates the of a Contiki application. AppleWin is especially well suited as it emulates the

View file

@ -8,7 +8,8 @@ CONTIKI_TARGET_DIRS = . dev
CONTIKI_TARGET_SOURCEFILES += leds.c leds-arch.c CONTIKI_TARGET_SOURCEFILES += leds.c leds-arch.c
CONTIKI_TARGET_SOURCEFILES += contiki-main.c CONTIKI_TARGET_SOURCEFILES += contiki-main.c
CONTIKI_TARGET_SOURCEFILES += sensors.c smartrf-sensors.c button-sensor.c CONTIKI_TARGET_SOURCEFILES += sensors.c smartrf-sensors.c
CONTIKI_TARGET_SOURCEFILES += button-sensor.c adc-sensor.c
TARGET_START_SOURCEFILES += startup-gcc.c TARGET_START_SOURCEFILES += startup-gcc.c
TARGET_STARTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(TARGET_START_SOURCEFILES)}} TARGET_STARTFILES = ${addprefix $(OBJECTDIR)/,${call oname, $(TARGET_START_SOURCEFILES)}}
@ -28,3 +29,12 @@ include $(CONTIKI_CPU)/Makefile.cc2538
MODULES += core/net core/net/ipv6 core/net/mac core/net/ip \ MODULES += core/net core/net/ipv6 core/net/mac core/net/ip \
core/net/rpl core/net/rime core/net/mac/contikimac core/net/rpl core/net/rime core/net/mac/contikimac
BSL = $(CONTIKI)/tools/cc2538-bsl/cc2538-bsl.py
%.upload: %.bin
ifeq ($(wildcard $(BSL)), )
@echo "ERROR: Could not find the cc2538-bsl script. Did you run 'git submodule update --init' ?"
else
python $(BSL) -e -w -v $<
endif

View file

@ -28,9 +28,11 @@ In terms of hardware support, the following drivers have been implemented:
* Random number generator * Random number generator
* Low Power Modes * Low Power Modes
* General-Purpose Timers. NB: GPT0 is in use by the platform code, the remaining GPTs are available for application development. * General-Purpose Timers. NB: GPT0 is in use by the platform code, the remaining GPTs are available for application development.
* ADC
* SmartRF06 EB and BB peripherals * SmartRF06 EB and BB peripherals
* LEDs * LEDs
* Buttons * Buttons
* ADC sensors (on-chip VDD / 3 and temperature, ambient light sensor)
* UART connectivity over the XDS100v3 backchannel (EB only) * UART connectivity over the XDS100v3 backchannel (EB only)
Requirements Requirements
@ -44,8 +46,8 @@ To start using Contiki, you will need the following:
Different tasks can be performed under different operating systems. The table below summarises what task can be performed on which OS: Different tasks can be performed under different operating systems. The table below summarises what task can be performed on which OS:
Windows Linux OS-X Windows Linux OS-X
Building Contiki Y Y N Building Contiki Y Y Y
Node Programming Y Y N Node Programming Y Y Y
Console output Console output
(UART) Y Y Y (UART) Y Y Y
(USB CDC-ACM) Y Y Y (USB CDC-ACM) Y Y Y
@ -56,7 +58,7 @@ Different tasks can be performed under different operating systems. The table be
(UART) N Y Y (UART) N Y Y
(USB CDC-ACM) N Y Y (USB CDC-ACM) N Y Y
The platform has been developed and tested under Windows XP, Mac OS X 10.7 and Ubuntu 12.04 and 12.10. The matrix above has been populated based on information for those OSs. The platform has been developed and tested under Windows XP, Mac OS X 10.9.1 and Ubuntu 12.04 and 12.10. The matrix above has been populated based on information for those OSs.
Install a Toolchain Install a Toolchain
------------------- -------------------
@ -193,9 +195,18 @@ On Linux:
Software to Program the Nodes Software to Program the Nodes
----------------------------- -----------------------------
On Windows, nodes can be programmed with TI's ArmProgConsole or the [SmartRF Flash Programmer][smart-rf-flashprog]. The README should be self-explanatory. With ArmProgConsole, upload the file with a `.bin` extension. The CC2538 can be programmed via the jtag interface or via the serial boot loader on the chip.
On Linux, nodes can be programmed with TI's [UniFlash] tool. With UniFlash, use the file with `.elf` extension. * On Windows:
* Nodes can be programmed with TI's ArmProgConsole or the [SmartRF Flash Programmer 2][smart-rf-flashprog]. The README should be self-explanatory. With ArmProgConsole, upload the file with a `.bin` extension. (jtag + serial)
* Nodes can also be programmed via the serial boot loader in the cc2538. In `tools/cc2538-bsl/` you can find `cc2538-bsl.py` this is a python script that can download firmware to your node via a serial connection. If you use this option you just need to make sure you have a working version of python installed. You can read the README in the same directory for more info. (serial)
* On Linux:
* Nodes can be programmed with TI's [UniFlash] tool. With UniFlash, use the file with `.elf` extension. (jtag + serial)
* Nodes can also be programmed via the serial boot loader in the cc2538. No extra software needs to be installed. (serial)
* On OSX:
* The `cc2538-bsl.py` script in `tools/cc2538-bsl/` is the only option. No extra software needs to be installed. (serial)
The file with a `.cc2538dk` extension is a copy of the `.elf` file. The file with a `.cc2538dk` extension is a copy of the `.elf` file.
@ -231,8 +242,12 @@ It is recommended to start with the `cc2538-demo` and `timer-test` examples unde
Strictly speaking, to build them you need to run `make TARGET=cc2538dk`. However, the example directories contain a `Makefile.target` which is automatically included and specifies the correct `TARGET=` argument. Thus, for examples under the `cc2538dk` directory, you can simply run `make`. Strictly speaking, to build them you need to run `make TARGET=cc2538dk`. However, the example directories contain a `Makefile.target` which is automatically included and specifies the correct `TARGET=` argument. Thus, for examples under the `cc2538dk` directory, you can simply run `make`.
If you want to upload the compiled firmware to a node via the serial boot loader you need to manually enable the boot loader and then use `make cc2538-demo.upload`. On the SmartRF06 board you enable the boot loader by resetting the board (EM RESET button) while holding the `select` button. (The boot loader backdoor needs to be enabled on the chip for this to work, see README in the `tools/cc2538-bsl` directory for more info)
For the `cc2538-demo`, the comments at the top of `cc2538-demo.c` describe in detail what the example does. For the `cc2538-demo`, the comments at the top of `cc2538-demo.c` describe in detail what the example does.
To generate an assembly listing of the compiled firmware, run `make cc2538-demo.lst`. This may be useful for debugging or optimizing your application code. To intersperse the C source code within the assembly listing, you must instruct the compiler to include debugging information by adding `CFLAGS += -g` to the project Makefile and rebuild by running `make clean cc2538-demo.lst`.
Node IEEE/RIME/IPv6 Addresses Node IEEE/RIME/IPv6 Addresses
----------------------------- -----------------------------
@ -243,7 +258,7 @@ To configure the IEEE address source location (Info Page or hard-coded), use the
* 0: Info Page * 0: Info Page
* 1: Hard-coded * 1: Hard-coded
If `IEEE_ADDR_CONF_HARDCODED` is defined as 1, the IEEE address will take its value from the `IEEE_ADDR_CONF_ADDRESS` define. If `IEEE_ADDR_CONF_HARDCODED` is defined as 1, the IEEE address will take its value from the `IEEE_ADDR_CONF_ADDRESS` define. If `IEEE_ADDR_CONF_HARDCODED` is defined as 0, the IEEE address can come from either the primary or secondary location in the Info Page. To use the secondary address, define `IEEE_ADDR_CONF_USE_SECONDARY_LOCATION` as 1.
Additionally, you can override the IEEE's 2 LSBs, by using the `NODEID` make variable. The value of `NODEID` will become the value of the `IEEE_ADDR_NODE_ID` pre-processor define. If `NODEID` is not defined, `IEEE_ADDR_NODE_ID` will not get defined either. For example: Additionally, you can override the IEEE's 2 LSBs, by using the `NODEID` make variable. The value of `NODEID` will become the value of the `IEEE_ADDR_NODE_ID` pre-processor define. If `NODEID` is not defined, `IEEE_ADDR_NODE_ID` will not get defined either. For example:
@ -350,19 +365,33 @@ By default, everything is configured to use the UART (stdio, border router's SLI
You can multiplex things (for instance, SLIP as well as debugging over USB or SLIP over USB but debugging over UART and other combinations). You can multiplex things (for instance, SLIP as well as debugging over USB or SLIP over USB but debugging over UART and other combinations).
Selecting UART0 and/or UART1
----------------------------
By default, everything is configured to use the UART0 (stdio, border router's SLIP, sniffer's output stream). If you want to change this, these are the relevant lines in contiki-conf.h (0: UART0, 1: UART1):
#define SERIAL_LINE_CONF_UART 0
#define SLIP_ARCH_CONF_UART 0
#define CC2538_RF_CONF_SNIFFER_UART 0
#define DBG_CONF_UART 0
#define UART1_CONF_UART 0
A single UART is available on CC2538DK, so all the configuration values above should be the same (i.e. either all 0 or all 1), but 0 and 1 could be mixed for other CC2538-based platforms supporting 2 UARTs.
The chosen UARTs must have their ports and pins defined in board.h:
#define UART0_RX_PORT GPIO_A_NUM
#define UART0_RX_PIN 0
#define UART0_TX_PORT GPIO_A_NUM
#define UART0_TX_PIN 1
Only the UART ports and pins implemented on the board can be defined.
UART Baud Rate UART Baud Rate
-------------- --------------
By default, the CC2538 UART is configured with a baud rate of 115200. It is easy to increase this to 230400 by changing the value of `UART_CONF_BAUD_RATE` in `contiki-conf.h` or `project-conf.h`. By default, the CC2538 UART is configured with a baud rate of 115200. It is easy to increase this to 230400 by changing the value of `UART0_CONF_BAUD_RATE` or `UART1_CONF_BAUD_RATE` in `contiki-conf.h` or `project-conf.h`, according to the UART instance used.
#define UART_CONF_BAUD_RATE 230400 #define UART0_CONF_BAUD_RATE 230400
#define UART1_CONF_BAUD_RATE 230400
Currently, this configuration directive only supports values 115200, 230400 and 460800. Custom baud rates can also be achieved by following the steps below:
* Configure `UART_CONF_BAUD_RATE` with an unsupported value to prevent it from auto-choosing values for IBRD and FBRD. For instance, in your project-conf.h you can do:
#define UART_CONF_BAUD_RATE 0
* Provide custom values for `UART_CONF_IBRD` and `UART_CONF_FBRD` according to the guidelines in the CC2538 User Guide.
RF and USB DMA RF and USB DMA
-------------- --------------

View file

@ -40,6 +40,16 @@ typedef uint32_t rtimer_clock_t;
#define RTIMER_CLOCK_LT(a,b) ((int32_t)((a)-(b)) < 0) #define RTIMER_CLOCK_LT(a,b) ((int32_t)((a)-(b)) < 0)
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/**
* \name Serial Boot Loader Backdoor configuration
*
* @{
*/
#ifndef FLASH_CCA_CONF_BOOTLDR_BACKDOOR
#define FLASH_CCA_CONF_BOOTLDR_BACKDOOR 1 /**<Enable the boot loader backdoor */
#endif
/** @} */
/*---------------------------------------------------------------------------*/
/** /**
* \name USB 'core' configuration * \name USB 'core' configuration
* *
@ -94,20 +104,53 @@ typedef uint32_t rtimer_clock_t;
#define UART_CONF_ENABLE 1 /**< Enable/Disable UART I/O */ #define UART_CONF_ENABLE 1 /**< Enable/Disable UART I/O */
#endif #endif
#ifndef UART_CONF_BAUD_RATE #ifndef UART0_CONF_BAUD_RATE
#define UART_CONF_BAUD_RATE 115200 /**< Default baud rate */ #define UART0_CONF_BAUD_RATE 115200 /**< Default UART0 baud rate */
#endif
#ifndef UART1_CONF_BAUD_RATE
#define UART1_CONF_BAUD_RATE 115200 /**< Default UART1 baud rate */
#endif #endif
#ifndef SLIP_ARCH_CONF_USB #ifndef SLIP_ARCH_CONF_USB
#define SLIP_ARCH_CONF_USB 0 /**< SLIP over UART by default */ #define SLIP_ARCH_CONF_USB 0 /**< SLIP over UART by default */
#endif #endif
#ifndef CC2538_RF_CONF_SNIFFER_USB #ifndef CC2538_RF_CONF_SNIFFER_USB
#define CC2538_RF_CONF_SNIFFER_USB 0 /**< Sniffer out over UART by default */ #define CC2538_RF_CONF_SNIFFER_USB 0 /**< Sniffer out over UART by default */
#endif #endif
#ifndef DBG_CONF_USB #ifndef DBG_CONF_USB
#define DBG_CONF_USB 0 /**< All debugging over UART by default */ #define DBG_CONF_USB 0 /**< All debugging over UART by default */
#endif #endif
#ifndef SERIAL_LINE_CONF_UART
#define SERIAL_LINE_CONF_UART 0 /**< UART to use with serial line */
#endif
#if !SLIP_ARCH_CONF_USB
#ifndef SLIP_ARCH_CONF_UART
#define SLIP_ARCH_CONF_UART 0 /**< UART to use with SLIP */
#endif
#endif
#if !CC2538_RF_CONF_SNIFFER_USB
#ifndef CC2538_RF_CONF_SNIFFER_UART
#define CC2538_RF_CONF_SNIFFER_UART 0 /**< UART to use with sniffer */
#endif
#endif
#if !DBG_CONF_USB
#ifndef DBG_CONF_UART
#define DBG_CONF_UART 0 /**< UART to use for debugging */
#endif
#endif
#ifndef UART1_CONF_UART
#define UART1_CONF_UART 0 /**< UART to use for examples relying on
the uart1_* API */
#endif
/* Turn off example-provided putchars */ /* Turn off example-provided putchars */
#define SLIP_BRIDGE_CONF_NO_PUTCHAR 1 #define SLIP_BRIDGE_CONF_NO_PUTCHAR 1
#define SLIP_RADIO_CONF_NO_PUTCHAR 1 #define SLIP_RADIO_CONF_NO_PUTCHAR 1
@ -175,8 +218,32 @@ typedef uint32_t rtimer_clock_t;
* this * this
*/ */
#if SLIP_ARCH_CONF_ENABLED #if SLIP_ARCH_CONF_ENABLED
#define DBG_CONF_SLIP_MUX (SLIP_ARCH_CONF_USB==DBG_CONF_USB) #define DBG_CONF_SLIP_MUX (SLIP_ARCH_CONF_USB == DBG_CONF_USB && \
(SLIP_ARCH_CONF_USB || \
SLIP_ARCH_CONF_UART == DBG_CONF_UART))
#endif #endif
/*
* Automatic detection of whether a specific UART is in use
*/
#define UART_IN_USE_BY_SERIAL_LINE(u) (SERIAL_LINE_CONF_UART == (u))
#define UART_IN_USE_BY_SLIP(u) (SLIP_ARCH_CONF_ENABLED && \
!SLIP_ARCH_CONF_USB && \
SLIP_ARCH_CONF_UART == (u))
#define UART_IN_USE_BY_RF_SNIFFER(u) (CC2538_RF_CONF_SNIFFER && \
!CC2538_RF_CONF_SNIFFER_USB && \
CC2538_RF_CONF_SNIFFER_UART == (u))
#define UART_IN_USE_BY_DBG(u) (!DBG_CONF_USB && DBG_CONF_UART == (u))
#define UART_IN_USE_BY_UART1(u) (UART1_CONF_UART == (u))
#define UART_IN_USE(u) ( \
UART_CONF_ENABLE && \
(UART_IN_USE_BY_SERIAL_LINE(u) || \
UART_IN_USE_BY_SLIP(u) || \
UART_IN_USE_BY_RF_SNIFFER(u) || \
UART_IN_USE_BY_DBG(u) || \
UART_IN_USE_BY_UART1(u)) \
)
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/* board.h assumes that basic configuration is done */ /* board.h assumes that basic configuration is done */
@ -268,6 +335,16 @@ typedef uint32_t rtimer_clock_t;
#ifndef IEEE_ADDR_CONF_ADDRESS #ifndef IEEE_ADDR_CONF_ADDRESS
#define IEEE_ADDR_CONF_ADDRESS { 0x00, 0x12, 0x4B, 0x00, 0x89, 0xAB, 0xCD, 0xEF } #define IEEE_ADDR_CONF_ADDRESS { 0x00, 0x12, 0x4B, 0x00, 0x89, 0xAB, 0xCD, 0xEF }
#endif #endif
/**
* \brief Location of the IEEE address in the InfoPage when
* IEEE_ADDR_CONF_HARDCODED is defined as 0
* 0 => Use the primary address location
* 1 => Use the secondary address location
*/
#ifndef IEEE_ADDR_CONF_USE_SECONDARY_LOCATION
#define IEEE_ADDR_CONF_USE_SECONDARY_LOCATION 0
#endif
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**

View file

@ -153,8 +153,9 @@ main(void)
* slip_input_byte instead * slip_input_byte instead
*/ */
#if UART_CONF_ENABLE #if UART_CONF_ENABLE
uart_init(); uart_init(0);
uart_set_input(serial_line_input_byte); uart_init(1);
uart_set_input(SERIAL_LINE_CONF_UART, serial_line_input_byte);
#endif #endif
#if USB_SERIAL_CONF_ENABLE #if USB_SERIAL_CONF_ENABLE

View file

@ -0,0 +1,111 @@
/*
* Copyright (c) 2013, ADVANSEE - http://www.advansee.com/
* Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup cc2538dk-adc-sensor
* @{
*
* \file
* Driver for the SmartRF06EB ADC
*/
#include "contiki.h"
#include "sys/clock.h"
#include "dev/ioc.h"
#include "dev/gpio.h"
#include "dev/adc.h"
#include "dev/adc-sensor.h"
#include <stdint.h>
#define ADC_ALS_PWR_PORT_BASE GPIO_PORT_TO_BASE(ADC_ALS_PWR_PORT)
#define ADC_ALS_PWR_PIN_MASK GPIO_PIN_MASK(ADC_ALS_PWR_PIN)
#define ADC_ALS_OUT_PIN_MASK GPIO_PIN_MASK(ADC_ALS_OUT_PIN)
/*---------------------------------------------------------------------------*/
static int
value(int type)
{
uint8_t channel;
int16_t res;
switch(type) {
case ADC_SENSOR_VDD_3:
channel = SOC_ADC_ADCCON_CH_VDD_3;
break;
case ADC_SENSOR_TEMP:
channel = SOC_ADC_ADCCON_CH_TEMP;
break;
case ADC_SENSOR_ALS:
channel = SOC_ADC_ADCCON_CH_AIN0 + ADC_ALS_OUT_PIN;
GPIO_SET_PIN(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK);
clock_delay_usec(2000);
break;
default:
return 0;
}
res = adc_get(channel, SOC_ADC_ADCCON_REF_INT, SOC_ADC_ADCCON_DIV_512);
if(type == ADC_SENSOR_ALS) {
GPIO_CLR_PIN(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK);
}
return res;
}
/*---------------------------------------------------------------------------*/
static int
configure(int type, int value)
{
switch(type) {
case SENSORS_HW_INIT:
GPIO_SOFTWARE_CONTROL(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK);
GPIO_SET_OUTPUT(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK);
GPIO_CLR_PIN(ADC_ALS_PWR_PORT_BASE, ADC_ALS_PWR_PIN_MASK);
ioc_set_over(ADC_ALS_PWR_PORT, ADC_ALS_PWR_PIN, IOC_OVERRIDE_DIS);
GPIO_SOFTWARE_CONTROL(GPIO_A_BASE, ADC_ALS_OUT_PIN_MASK);
GPIO_SET_INPUT(GPIO_A_BASE, ADC_ALS_OUT_PIN_MASK);
ioc_set_over(GPIO_A_NUM, ADC_ALS_OUT_PIN, IOC_OVERRIDE_ANA);
adc_init();
break;
}
return 0;
}
/*---------------------------------------------------------------------------*/
static int
status(int type)
{
return 1;
}
/*---------------------------------------------------------------------------*/
SENSORS_SENSOR(adc_sensor, ADC_SENSOR, value, configure, status);
/** @} */

View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 2013, ADVANSEE - http://www.advansee.com/
* Benoît Thébaudeau <benoit.thebaudeau@advansee.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \addtogroup cc2538-smartrf-sensors
* @{
*
* \defgroup cc2538dk-adc-sensor cc2538dk ADC Driver
*
* Driver for the SmartRF06EB ADC sensors
* @{
*
* \file
* Header file for the cc2538dk ADC Driver
*/
#ifndef ADC_SENSOR_H_
#define ADC_SENSOR_H_
#include "lib/sensors.h"
/*---------------------------------------------------------------------------*/
/** \name ADC sensors
* @{
*/
#define ADC_SENSOR "ADC"
#define ADC_SENSOR_VDD_3 0 /**< On-chip VDD / 3 */
#define ADC_SENSOR_TEMP 1 /**< On-chip temperature */
#define ADC_SENSOR_ALS 2 /**< Ambient light sensor */
/** @} */
extern const struct sensors_sensor adc_sensor;
#endif /* ADC_SENSOR_H_ */
/**
* @}
* @}
*/

View file

@ -110,22 +110,21 @@
* - CTS: PB0 (Can only be used with UART1) * - CTS: PB0 (Can only be used with UART1)
* - RTS: PD3 (Can only be used with UART1) * - RTS: PD3 (Can only be used with UART1)
* *
* We configure the port to use UART0. To use UART1, change UART_CONF_BASE * We configure the port to use UART0. To use UART1, replace UART0_* with
* UART1_* below.
* @{ * @{
*/ */
#define UART_CONF_BASE UART_0_BASE #define UART0_RX_PORT GPIO_A_NUM
#define UART0_RX_PIN 0
#define UART_RX_PORT GPIO_A_NUM #define UART0_TX_PORT GPIO_A_NUM
#define UART_RX_PIN 0 #define UART0_TX_PIN 1
#define UART_TX_PORT GPIO_A_NUM #define UART1_CTS_PORT GPIO_B_NUM
#define UART_TX_PIN 1 #define UART1_CTS_PIN 0
#define UART_CTS_PORT GPIO_B_NUM #define UART1_RTS_PORT GPIO_D_NUM
#define UART_CTS_PIN 0 #define UART1_RTS_PIN 3
#define UART_RTS_PORT GPIO_D_NUM
#define UART_RTS_PIN 3
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** \name SmartRF Button configuration /** \name SmartRF Button configuration
@ -167,6 +166,20 @@
#define PLATFORM_HAS_BUTTON 1 #define PLATFORM_HAS_BUTTON 1
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/**
* \name ADC configuration
*
* These values configure which CC2538 pins and ADC channels to use for the ADC
* inputs.
*
* ADC inputs can only be on port A.
* @{
*/
#define ADC_ALS_PWR_PORT GPIO_A_NUM /**< ALS power GPIO control port */
#define ADC_ALS_PWR_PIN 7 /**< ALS power GPIO control pin */
#define ADC_ALS_OUT_PIN 6 /**< ALS output ADC input pin on port A */
/** @} */
/*---------------------------------------------------------------------------*/
/** /**
* \name SPI configuration * \name SPI configuration
* *
@ -179,8 +192,6 @@
#define SPI_MOSI_PIN 4 #define SPI_MOSI_PIN 4
#define SPI_MISO_PORT GPIO_A_NUM #define SPI_MISO_PORT GPIO_A_NUM
#define SPI_MISO_PIN 5 #define SPI_MISO_PIN 5
#define SPI_SEL_PORT GPIO_B_NUM
#define SPI_SEL_PIN 5
/** @} */ /** @} */
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
/** /**

View file

@ -42,12 +42,13 @@
*/ */
#include "contiki.h" #include "contiki.h"
#include "dev/button-sensor.h" #include "dev/button-sensor.h"
#include "dev/adc-sensor.h"
#include <string.h> #include <string.h>
/** \brief Exports a global symbol to be used by the sensor API */ /** \brief Exports a global symbol to be used by the sensor API */
SENSORS(&button_select_sensor, &button_left_sensor, &button_right_sensor, SENSORS(&button_select_sensor, &button_left_sensor, &button_right_sensor,
&button_up_sensor, &button_down_sensor); &button_up_sensor, &button_down_sensor, &adc_sensor);
/** /**
* @} * @}

View file

@ -63,6 +63,15 @@ void cc2538_rf_err_isr(void);
void udma_isr(void); void udma_isr(void);
void udma_err_isr(void); void udma_err_isr(void);
/* Boot Loader Backdoor selection */
#if FLASH_CCA_CONF_BOOTLDR_BACKDOOR
/* Backdoor enabled, on PA_3 (Select button) */
#define FLASH_CCA_BOOTLDR_CFG (FLASH_CCA_BOOTLDR_CFG_ENABLE \
| ((3 << FLASH_CCA_BOOTLDR_CFG_PORT_A_PIN_S) & FLASH_CCA_BOOTLDR_CFG_PORT_A_PIN_M))
#else
#define FLASH_CCA_BOOTLDR_CFG FLASH_CCA_BOOTLDR_CFG_DISABLE
#endif
/* Link in the USB ISR only if USB is enabled */ /* Link in the USB ISR only if USB is enabled */
#if USB_SERIAL_CONF_ENABLE #if USB_SERIAL_CONF_ENABLE
void usb_isr(void); void usb_isr(void);
@ -72,16 +81,8 @@ void usb_isr(void);
/* Likewise for the UART[01] ISRs */ /* Likewise for the UART[01] ISRs */
#if UART_CONF_ENABLE #if UART_CONF_ENABLE
void uart_isr(void); void uart0_isr(void);
void uart1_isr(void);
#if UART_BASE==UART_1_BASE
#define uart0_isr default_handler
#define uart1_isr uart_isr
#else
#define uart0_isr uart_isr
#define uart1_isr default_handler
#endif
#else /* UART_CONF_ENABLE */ #else /* UART_CONF_ENABLE */
#define uart0_isr default_handler #define uart0_isr default_handler
#define uart1_isr default_handler #define uart1_isr default_handler
@ -95,7 +96,7 @@ extern uint8_t _text[0];
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
__attribute__ ((section(".flashcca"), used)) __attribute__ ((section(".flashcca"), used))
const flash_cca_lock_page_t __cca = { const flash_cca_lock_page_t __cca = {
FLASH_CCA_BOOTLDR_CFG_DISABLE, /* Bootloader backdoor disabled */ FLASH_CCA_BOOTLDR_CFG, /* Boot loader backdoor configuration */
FLASH_CCA_IMAGE_VALID, /* Image valid */ FLASH_CCA_IMAGE_VALID, /* Image valid */
&_text, /* Vector table located at the start of .text */ &_text, /* Vector table located at the start of .text */
/* Unlock all pages and debug */ /* Unlock all pages and debug */

View file

@ -46,4 +46,5 @@ CURSES_LIBS ?= -lncurses
TARGET_LIBFILES += $(CURSES_LIBS) TARGET_LIBFILES += $(CURSES_LIBS)
MODULES+=core/net/ip core/net/ipv4 core/net core/net/ipv6 core/net/rime core/net/mac MODULES+=core/net/ip core/net/ipv4 core/net core/net/ipv6 core/net/rime \
core/net/mac core/net/rpl core/ctk

View file

@ -27,6 +27,7 @@ sky-ip/sky \
sky-shell/sky \ sky-shell/sky \
sky-shell-exec/sky \ sky-shell-exec/sky \
sky-shell-webserver/sky \ sky-shell-webserver/sky \
tcp-socket/minimal-net \
telnet-server/minimal-net \ telnet-server/minimal-net \
webserver/minimal-net \ webserver/minimal-net \
webserver-ipv6/exp5438 \ webserver-ipv6/exp5438 \
@ -34,6 +35,7 @@ webserver-ipv6/eval-adf7xxxmb4z \
wget/minimal-net \ wget/minimal-net \
z1/z1 \ z1/z1 \
settings-example/avr-raven \ settings-example/avr-raven \
ipv6/multicast/sky \
TOOLS= TOOLS=

View file

@ -0,0 +1,367 @@
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<project EXPORT="discard">[APPS_DIR]/mrm</project>
<project EXPORT="discard">[APPS_DIR]/mspsim</project>
<project EXPORT="discard">[APPS_DIR]/avrora</project>
<project EXPORT="discard">[APPS_DIR]/serial_socket</project>
<project EXPORT="discard">[APPS_DIR]/collect-view</project>
<project EXPORT="discard">[APPS_DIR]/powertracker</project>
<simulation>
<title>Multicast regression test</title>
<randomseed>123456</randomseed>
<motedelay_us>1000000</motedelay_us>
<radiomedium>
org.contikios.cooja.radiomediums.UDGM
<transmitting_range>15.0</transmitting_range>
<interference_range>0.0</interference_range>
<success_ratio_tx>1.0</success_ratio_tx>
<success_ratio_rx>1.0</success_ratio_rx>
</radiomedium>
<events>
<logoutput>40000</logoutput>
</events>
<motetype>
org.contikios.cooja.contikimote.ContikiMoteType
<identifier>mtype612</identifier>
<description>Root/sender</description>
<source>[CONTIKI_DIR]/examples/ipv6/multicast/root.c</source>
<commands>make root.cooja TARGET=cooja</commands>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<symbols>false</symbols>
</motetype>
<motetype>
org.contikios.cooja.contikimote.ContikiMoteType
<identifier>mtype890</identifier>
<description>Intermediate</description>
<source>[CONTIKI_DIR]/examples/ipv6/multicast/intermediate.c</source>
<commands>make intermediate.cooja TARGET=cooja</commands>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<symbols>false</symbols>
</motetype>
<motetype>
org.contikios.cooja.contikimote.ContikiMoteType
<identifier>mtype956</identifier>
<description>Receiver</description>
<source>[CONTIKI_DIR]/examples/ipv6/multicast/sink.c</source>
<commands>make sink.cooja TARGET=cooja</commands>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<symbols>false</symbols>
</motetype>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>-7.983976888750106</x>
<y>0.37523218201044733</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>1</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype612</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>0.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>2</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype890</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>10.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>3</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype890</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>20.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>4</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype890</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>30.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>5</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype890</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>40.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>6</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype890</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>50.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>7</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype890</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>60.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>8</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype890</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>70.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>9</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype890</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>79.93950307524713</x>
<y>-0.043451055913349</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>10</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype890</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>90.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>11</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype890</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>99.61761525766555</x>
<y>0.37523218201044733</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>12</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype956</motetype_identifier>
</mote>
</simulation>
<plugin>
org.contikios.cooja.plugins.SimControl
<width>280</width>
<z>1</z>
<height>160</height>
<location_x>400</location_x>
<location_y>0</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Visualizer
<plugin_config>
<moterelations>true</moterelations>
<skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.GridVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.TrafficVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin>
<viewport>2.388440494916608 0.0 0.0 2.388440494916608 109.06925371156906 149.10378026149033</viewport>
</plugin_config>
<width>400</width>
<z>3</z>
<height>400</height>
<location_x>1</location_x>
<location_y>1</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.LogListener
<plugin_config>
<filter />
<formatted_time />
<coloring />
</plugin_config>
<width>1200</width>
<z>2</z>
<height>240</height>
<location_x>400</location_x>
<location_y>160</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Notes
<plugin_config>
<notes>Enter notes here</notes>
<decorations>true</decorations>
</plugin_config>
<width>920</width>
<z>4</z>
<height>160</height>
<location_x>680</location_x>
<location_y>0</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.ScriptRunner
<plugin_config>
<script>TIMEOUT(300000);&#xD;
&#xD;
WAIT_UNTIL(msg.startsWith("In: "));&#xD;
&#xD;
log.testOK(); /* Report test success and quit */</script>
<active>true</active>
</plugin_config>
<width>600</width>
<z>0</z>
<height>700</height>
<location_x>843</location_x>
<location_y>77</location_y>
</plugin>
</simconf>

View file

@ -0,0 +1,707 @@
<?xml version="1.0" encoding="UTF-8"?>
<simconf>
<project EXPORT="discard">[APPS_DIR]/mrm</project>
<project EXPORT="discard">[APPS_DIR]/mspsim</project>
<project EXPORT="discard">[APPS_DIR]/avrora</project>
<project EXPORT="discard">[APPS_DIR]/serial_socket</project>
<project EXPORT="discard">[APPS_DIR]/collect-view</project>
<project EXPORT="discard">[APPS_DIR]/powertracker</project>
<simulation>
<title>Multicast regression test</title>
<randomseed>123456</randomseed>
<motedelay_us>1000000</motedelay_us>
<radiomedium>
org.contikios.cooja.radiomediums.UDGM
<transmitting_range>15.0</transmitting_range>
<interference_range>0.0</interference_range>
<success_ratio_tx>1.0</success_ratio_tx>
<success_ratio_rx>1.0</success_ratio_rx>
</radiomedium>
<events>
<logoutput>40000</logoutput>
</events>
<motetype>
org.contikios.cooja.contikimote.ContikiMoteType
<identifier>mtype816</identifier>
<description>Root/sender</description>
<source>[CONTIKI_DIR]/examples/ipv6/multicast/root.c</source>
<commands>make root.cooja TARGET=cooja</commands>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<symbols>false</symbols>
</motetype>
<motetype>
org.contikios.cooja.contikimote.ContikiMoteType
<identifier>mtype53</identifier>
<description>Intermediate</description>
<source>[CONTIKI_DIR]/examples/ipv6/multicast/intermediate.c</source>
<commands>make intermediate.cooja TARGET=cooja</commands>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<symbols>false</symbols>
</motetype>
<motetype>
org.contikios.cooja.contikimote.ContikiMoteType
<identifier>mtype191</identifier>
<description>Receiver</description>
<source>[CONTIKI_DIR]/examples/ipv6/multicast/sink.c</source>
<commands>make sink.cooja TARGET=cooja</commands>
<moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
<moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
<moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
<symbols>false</symbols>
</motetype>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>-7.983976888750106</x>
<y>0.37523218201044733</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>1</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype816</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>0.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>2</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>10.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>3</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>20.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>4</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>30.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>5</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>40.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>6</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>50.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>7</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>60.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>8</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>70.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>9</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>79.93950307524713</x>
<y>-0.043451055913349</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>10</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>90.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>11</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>299.830399237567</x>
<y>0.21169609213234786</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>12</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype191</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>100.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>13</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>110.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>14</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>120.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>15</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>130.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>16</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>140.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>17</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>150.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>18</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>160.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>19</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>170.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>20</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>180.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>21</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>190.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>22</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>200.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>23</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>210.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>24</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>220.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>25</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>230.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>26</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>240.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>27</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>250.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>28</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>260.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>29</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>270.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>30</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>280.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>31</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
<mote>
<interface_config>
org.contikios.cooja.interfaces.Position
<x>290.0</x>
<y>0.0</y>
<z>0.0</z>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiMoteID
<id>32</id>
</interface_config>
<interface_config>
org.contikios.cooja.contikimote.interfaces.ContikiRadio
<bitrate>250.0</bitrate>
</interface_config>
<motetype_identifier>mtype53</motetype_identifier>
</mote>
</simulation>
<plugin>
org.contikios.cooja.plugins.SimControl
<width>280</width>
<z>1</z>
<height>160</height>
<location_x>400</location_x>
<location_y>0</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Visualizer
<plugin_config>
<moterelations>true</moterelations>
<skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.GridVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.TrafficVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin>
<skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin>
<viewport>1.1837122130192945 0.0 0.0 1.1837122130192945 27.087094588040927 150.74941275029448</viewport>
</plugin_config>
<width>400</width>
<z>2</z>
<height>400</height>
<location_x>1</location_x>
<location_y>1</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.LogListener
<plugin_config>
<filter />
<formatted_time />
<coloring />
</plugin_config>
<width>1200</width>
<z>3</z>
<height>240</height>
<location_x>400</location_x>
<location_y>160</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.Notes
<plugin_config>
<notes>Enter notes here</notes>
<decorations>true</decorations>
</plugin_config>
<width>920</width>
<z>4</z>
<height>160</height>
<location_x>680</location_x>
<location_y>0</location_y>
</plugin>
<plugin>
org.contikios.cooja.plugins.ScriptRunner
<plugin_config>
<script>TIMEOUT(300000);&#xD;
&#xD;
WAIT_UNTIL(msg.startsWith("In: "));&#xD;
&#xD;
log.testOK(); /* Report test success and quit */</script>
<active>true</active>
</plugin_config>
<width>600</width>
<z>0</z>
<height>700</height>
<location_x>843</location_x>
<location_y>77</location_y>
</plugin>
</simconf>

View file

@ -7,6 +7,7 @@ cc2530dk/cc2530dk \
cc2530dk/border-router/cc2530dk \ cc2530dk/border-router/cc2530dk \
cc2530dk/udp-ipv6/cc2530dk \ cc2530dk/udp-ipv6/cc2530dk \
cc2530dk/sniffer/cc2530dk \ cc2530dk/sniffer/cc2530dk \
ipv6/multicast/cc2530dk \
TOOLS= TOOLS=

View file

@ -14,6 +14,8 @@ webserver-ipv6/cc2538dk \
cc2538dk/cc2538dk \ cc2538dk/cc2538dk \
cc2538dk/udp-ipv6-echo-server/cc2538dk \ cc2538dk/udp-ipv6-echo-server/cc2538dk \
cc2538dk/sniffer/cc2538dk \ cc2538dk/sniffer/cc2538dk \
ipv6/multicast/econotag \
ipv6/multicast/cc2538dk \
TOOLS= TOOLS=

1
tools/cc2538-bsl Submodule

@ -0,0 +1 @@
Subproject commit 1223bfe03cdb31c439f1a51593808cdabc1939d2

View file

@ -1,9 +0,0 @@
#!/bin/sh
f=`basename $1`
mkdir /tmp/$$
cp $1 /tmp/$$/
cp $1 /tmp/$$/$f.orig
export INDENT_PROFILE=`dirname $0`/indent.pro
indent /tmp/$$/$f
diff /tmp/$$/$f.orig /tmp/$$/$f
rm -rf /tmp/$$

View file

@ -1,3 +0,0 @@
#!/bin/sh
export INDENT_PROFILE=`dirname $0`/indent.pro
indent $*

View file

@ -1,22 +0,0 @@
-bad
-br
-brs
-cdw
-ce
-hnl
-i2
-lp
-nbap
-nbbb
-ncdb
-ncs
-nfca
-nlps
-npcs
-nprs
-nsaf
-nsai
-nsaw
-nsc
-nut
-psl

View file

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
# #
# This file checks your git index and runs indent on every changed *.c and *.h # This file checks your git index and runs uncrustify on every changed *.c and *.h
# file. # file.
# #
# Author: Valentin Sawadski <valentin@sawadski.eu> # Author: Valentin Sawadski <valentin@sawadski.eu>

View file

@ -26,13 +26,13 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
package org.contikios.mrm; package org.contikios.mrm;
import java.awt.Color; import java.awt.Color;
import java.awt.FontMetrics; import java.awt.FontMetrics;
import java.awt.Graphics; import java.awt.Graphics;
import java.awt.Point; import java.awt.Point;
import java.util.Set;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
@ -50,11 +50,13 @@ import org.contikios.mrm.ChannelModel.TxPair;
@ClassDescription("Radio environment (MRM)") @ClassDescription("Radio environment (MRM)")
@SupportedArguments(radioMediums = {MRM.class}) @SupportedArguments(radioMediums = {MRM.class})
public class MRMVisualizerSkin implements VisualizerSkin { public class MRMVisualizerSkin implements VisualizerSkin {
private static Logger logger = Logger.getLogger(MRMVisualizerSkin.class);
private static final Logger logger = Logger.getLogger(MRMVisualizerSkin.class);
private Simulation simulation = null; private Simulation simulation = null;
private Visualizer visualizer = null; private Visualizer visualizer = null;
@Override
public void setActive(Simulation simulation, Visualizer vis) { public void setActive(Simulation simulation, Visualizer vis) {
if (!(simulation.getRadioMedium() instanceof MRM)) { if (!(simulation.getRadioMedium() instanceof MRM)) {
logger.fatal("Cannot activate MRM skin for unknown radio medium: " + simulation.getRadioMedium()); logger.fatal("Cannot activate MRM skin for unknown radio medium: " + simulation.getRadioMedium());
@ -64,6 +66,7 @@ public class MRMVisualizerSkin implements VisualizerSkin {
this.visualizer = vis; this.visualizer = vis;
} }
@Override
public void setInactive() { public void setInactive() {
if (simulation == null) { if (simulation == null) {
/* Skin was never activated */ /* Skin was never activated */
@ -71,88 +74,98 @@ public class MRMVisualizerSkin implements VisualizerSkin {
} }
} }
@Override
public Color[] getColorOf(Mote mote) { public Color[] getColorOf(Mote mote) {
Mote selectedMote = visualizer.getSelectedMote(); if (visualizer.getSelectedMotes().contains(mote)) {
if (mote == selectedMote) { return new Color[]{Color.CYAN};
return new Color[] { Color.CYAN };
} }
return null; return null;
} }
@Override
public void paintBeforeMotes(Graphics g) { public void paintBeforeMotes(Graphics g) {
final Mote selectedMote = visualizer.getSelectedMote(); Set<Mote> selectedMotes = visualizer.getSelectedMotes();
if (simulation == null if (simulation == null || selectedMotes == null) {
|| selectedMote == null
|| selectedMote.getInterfaces().getRadio() == null) {
return; return;
} }
final Position sPos = selectedMote.getInterfaces().getPosition();
/* Paint transmission and interference range for selected mote */ for (final Mote selectedMote : selectedMotes) {
Position motePos = selectedMote.getInterfaces().getPosition(); if (selectedMote.getInterfaces().getRadio() == null) {
Point pixelCoord = visualizer.transformPositionToPixel(motePos);
int x = pixelCoord.x;
int y = pixelCoord.y;
FontMetrics fm = g.getFontMetrics();
g.setColor(Color.BLACK);
MRM radioMedium = (MRM) simulation.getRadioMedium();
/* Print transmission success probabilities */
Mote[] dests = simulation.getMotes();
if (dests == null || dests.length == 0) {
String msg = "No edges";
int msgWidth = fm.stringWidth(msg);
g.setColor(Color.BLACK);
g.drawString(msg, x - msgWidth/2, y + 2*Visualizer.MOTE_RADIUS + 3);
return;
}
g.setColor(Color.BLACK);
int edges = 0;
for (Mote d: dests) {
if (d == selectedMote) {
continue; continue;
} }
final Radio dRadio = d.getInterfaces().getRadio(); final Position sPos = selectedMote.getInterfaces().getPosition();
TxPair txPair = new RadioPair() {
public Radio getFromRadio() {
return selectedMote.getInterfaces().getRadio();
}
public Radio getToRadio() {
return dRadio;
}
};
double probArr[] = radioMedium.getChannelModel().getProbability(
txPair,
Double.NEGATIVE_INFINITY
);
double prob = probArr[0];
double ss = probArr[1];
if (prob == 0.0d) { /* Paint transmission and interference range for selected mote */
continue; Position motePos = selectedMote.getInterfaces().getPosition();
}
edges++; Point pixelCoord = visualizer.transformPositionToPixel(motePos);
String msg = String.format("%1.1f%%, %1.2fdB", 100.0*prob, ss); int x = pixelCoord.x;
Point pixel = visualizer.transformPositionToPixel(d.getInterfaces().getPosition()); int y = pixelCoord.y;
int msgWidth = fm.stringWidth(msg);
g.setColor(new Color(1-(float)prob, (float)prob, 0.0f)); FontMetrics fm = g.getFontMetrics();
g.drawLine(x, y, pixel.x, pixel.y);
g.setColor(Color.BLACK); g.setColor(Color.BLACK);
g.drawString(msg, pixel.x - msgWidth/2, pixel.y + 2*Visualizer.MOTE_RADIUS + 3);
}
String msg = dests.length + " edges"; MRM radioMedium = (MRM) simulation.getRadioMedium();
int msgWidth = fm.stringWidth(msg);
g.setColor(Color.BLACK); /* Print transmission success probabilities */
g.drawString(msg, x - msgWidth/2, y + 2*Visualizer.MOTE_RADIUS + 3); Mote[] dests = simulation.getMotes();
if (dests == null || dests.length == 0) {
String msg = "No edges";
int msgWidth = fm.stringWidth(msg);
g.setColor(Color.BLACK);
g.drawString(msg, x - msgWidth / 2, y + 2 * Visualizer.MOTE_RADIUS + 3);
return;
}
g.setColor(Color.BLACK);
int edges = 0;
for (Mote d : dests) {
if (d == selectedMote) {
continue;
}
final Radio dRadio = d.getInterfaces().getRadio();
TxPair txPair = new RadioPair() {
@Override
public Radio getFromRadio() {
return selectedMote.getInterfaces().getRadio();
}
@Override
public Radio getToRadio() {
return dRadio;
}
};
double probArr[] = radioMedium.getChannelModel().getProbability(
txPair,
Double.NEGATIVE_INFINITY
);
double prob = probArr[0];
double ss = probArr[1];
if (prob == 0.0d) {
continue;
}
edges++;
String msg = String.format("%1.1f%%, %1.2fdB", 100.0 * prob, ss);
Point pixel = visualizer.transformPositionToPixel(d.getInterfaces().getPosition());
int msgWidth = fm.stringWidth(msg);
g.setColor(new Color(1 - (float) prob, (float) prob, 0.0f));
g.drawLine(x, y, pixel.x, pixel.y);
g.setColor(Color.BLACK);
g.drawString(msg, pixel.x - msgWidth / 2, pixel.y + 2 * Visualizer.MOTE_RADIUS + 3);
}
String msg = dests.length + " edges";
int msgWidth = fm.stringWidth(msg);
g.setColor(Color.BLACK);
g.drawString(msg, x - msgWidth / 2, y + 2 * Visualizer.MOTE_RADIUS + 3);
}
} }
@Override
public void paintAfterMotes(Graphics g) { public void paintAfterMotes(Graphics g) {
} }
@Override
public Visualizer getVisualizer() { public Visualizer getVisualizer() {
return visualizer; return visualizer;
} }

View file

@ -1,3 +1,3 @@
org.contikios.cooja.Cooja.MOTETYPES = + org.contikios.cooja.mspmote.ESBMoteType org.contikios.cooja.mspmote.SkyMoteType org.contikios.cooja.mspmote.Z1MoteType org.contikios.cooja.mspmote.WismoteMoteType org.contikios.cooja.mspmote.Exp5438MoteType org.contikios.cooja.mspmote.SkyMoteType org.contikios.cooja.mspmote.CC430MoteType org.contikios.cooja.mspmote.Exp1120MoteType org.contikios.cooja.mspmote.Exp1101MoteType org.contikios.cooja.mspmote.Exp2420MoteType org.contikios.cooja.mspmote.Trxeb2520MoteType org.contikios.cooja.mspmote.Trxeb1120MoteType org.contikios.cooja.mspmote.Eth1120MoteType org.contikios.cooja.Cooja.MOTETYPES = + org.contikios.cooja.mspmote.ESBMoteType org.contikios.cooja.mspmote.SkyMoteType org.contikios.cooja.mspmote.Z1MoteType org.contikios.cooja.mspmote.WismoteMoteType org.contikios.cooja.mspmote.Exp5438MoteType org.contikios.cooja.mspmote.CC430MoteType org.contikios.cooja.mspmote.Exp1120MoteType org.contikios.cooja.mspmote.Exp1101MoteType org.contikios.cooja.mspmote.Exp2420MoteType org.contikios.cooja.mspmote.Trxeb2520MoteType org.contikios.cooja.mspmote.Trxeb1120MoteType org.contikios.cooja.mspmote.Eth1120MoteType
org.contikios.cooja.Cooja.JARFILES = + cooja_mspsim.jar mspsim.jar coffee.jar jipv6.jar org.contikios.cooja.Cooja.JARFILES = + cooja_mspsim.jar mspsim.jar coffee.jar jipv6.jar
org.contikios.cooja.Cooja.PLUGINS = + org.contikios.cooja.mspmote.plugins.MspCLI org.contikios.cooja.mspmote.plugins.MspCodeWatcher org.contikios.cooja.mspmote.plugins.MspStackWatcher org.contikios.cooja.mspmote.plugins.MspCycleWatcher org.contikios.cooja.Cooja.PLUGINS = + org.contikios.cooja.mspmote.plugins.MspCLI org.contikios.cooja.mspmote.plugins.MspCodeWatcher org.contikios.cooja.mspmote.plugins.MspStackWatcher org.contikios.cooja.mspmote.plugins.MspCycleWatcher

View file

@ -1659,7 +1659,6 @@ public class Cooja extends Observable {
return false; return false;
} }
int nrFrames = myDesktopPane.getAllFrames().length;
myDesktopPane.add(pluginFrame); myDesktopPane.add(pluginFrame);
/* Set size if not already specified by plugin */ /* Set size if not already specified by plugin */
@ -1667,11 +1666,9 @@ public class Cooja extends Observable {
pluginFrame.setSize(FRAME_STANDARD_WIDTH, FRAME_STANDARD_HEIGHT); pluginFrame.setSize(FRAME_STANDARD_WIDTH, FRAME_STANDARD_HEIGHT);
} }
/* Set location if not already visible */ /* Set location if not already set */
if (pluginFrame.getLocation().x <= 0 && pluginFrame.getLocation().y <= 0) { if (pluginFrame.getLocation().x <= 0 && pluginFrame.getLocation().y <= 0) {
pluginFrame.setLocation( pluginFrame.setLocation(determineNewPluginLocation());
nrFrames * FRAME_NEW_OFFSET,
nrFrames * FRAME_NEW_OFFSET);
} }
pluginFrame.setVisible(true); pluginFrame.setVisible(true);
@ -1690,6 +1687,29 @@ public class Cooja extends Observable {
}.invokeAndWait(); }.invokeAndWait();
} }
/**
* Determines suitable location for placing new plugin.
* <p>
* If possible, this is below right of the second last activated
* internfal frame (offset is determined by FRAME_NEW_OFFSET).
*
* @return Resulting placement position
*/
private Point determineNewPluginLocation() {
Point topFrameLoc;
JInternalFrame[] iframes = myDesktopPane.getAllFrames();
if (iframes.length > 1) {
topFrameLoc = iframes[1].getLocation();
} else {
topFrameLoc = new Point(
myDesktopPane.getSize().width / 2,
myDesktopPane.getSize().height / 2);
}
return new Point(
topFrameLoc.x + FRAME_NEW_OFFSET,
topFrameLoc.y + FRAME_NEW_OFFSET);
}
/** /**
* Close all mote plugins for given mote. * Close all mote plugins for given mote.
* *

View file

@ -757,6 +757,7 @@ public class Simulation extends Observable implements Runnable {
Runnable removeMote = new Runnable() { Runnable removeMote = new Runnable() {
public void run() { public void run() {
motes.remove(mote); motes.remove(mote);
motesUninit.remove(mote);
currentRadioMedium.unregisterMote(mote, Simulation.this); currentRadioMedium.unregisterMote(mote, Simulation.this);
/* Dispose mote interface resources */ /* Dispose mote interface resources */

View file

@ -252,7 +252,7 @@ public class ContikiRadio extends Radio implements ContikiMoteInterface, PolledA
/** Set LQI to a value between 0 and 255. /** Set LQI to a value between 0 and 255.
* *
* @see se.sics.cooja.interfaces.Radio#setLQI(int) * @see org.contikios.cooja.interfaces.Radio#setLQI(int)
*/ */
public void setLQI(int lqi){ public void setLQI(int lqi){
if(lqi<0) { if(lqi<0) {

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