Newer
Older

Robert Hartung
committed
/*
* Copyright (C) 2008, 2009, 2010 Kaspar Schleiser <kaspar@schleiser.de>
* Copyright (C) 2013 INRIA
* Copyright (C) 2013 Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup examples
* @{
*
* @file
* @brief Default application that shows a lot of functionality of RIOT
*
* @author Kaspar Schleiser <kaspar@schleiser.de>
* @author Oliver Hahm <oliver.hahm@inria.fr>
* @author Ludwig Knüpfer <ludwig.knuepfer@fu-berlin.de>
*
* @}
*/
#include <stdio.h>
#include <string.h>
#include "msg.h"
#include "thread.h"
#include "shell.h"
#include "shell_commands.h"
#include "xtimer.h"
#include "net/gnrc.h"
#include "net/gnrc/netreg.h"
#include "net/gnrc/netif/ieee802154.h"

Robert Hartung
committed
#define SEND_INTERVAL (1)
#define RCV_QUEUE_SIZE (8)
#define MAX_PAYLOAD_LENGTH (32)
#define MAGIC_STRING "IBREVAL\0"

Robert Hartung
committed
#define SHELL_BUFFER_SIZE (256)

Robert Hartung
committed
#ifndef NODE_ID
#error NODE_ID undefined
#endif
/// 512 required for samr21-xpro, 256 sufficient for INGA and telosb
#ifdef BOARD_SAMR21_XPRO
char dump_thread_stack[1024+256];
char send_thread_stack[1024+256];
#else
char dump_thread_stack[512+256];
char send_thread_stack[512+256];
#endif
//static msg_t dump_thread_msg_queue[RCV_QUEUE_SIZE];
//static msg_t send_thread_msg_queue[RCV_QUEUE_SIZE];
char line_buf[SHELL_BUFFER_SIZE];

Robert Hartung
committed
char magic_string[8];

Robert Hartung
committed
uint8_t node_id;

Robert Hartung
committed
uint8_t temp;

Robert Hartung
committed
uint8_t payload[MAX_PAYLOAD_LENGTH];
} eval_message_t;
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
static eval_message_t eval_message = { .node_id = NODE_ID, .payload_length = 5, .payload = "Hello\0", .magic_string = MAGIC_STRING, .seq_nr = 0 };
kernel_pid_t send_thread_pid = 0;
/**
* Sends a packet via the network interface
*
* tx [count [delay]]
* - count: Number of packets to send
* - delay: Delay in µS between the packets
*/
int shell_tx(int argc, char** argv) {
(void)argc;
(void)argv;
uint8_t count = 1;
uint32_t delay = 100000; // 100000us = 100ms
if(argc > 1) {
count = atoi(argv[1]);
}
if(argc > 2) {
delay = (uint32_t)atol(argv[2]);
}
msg_t msg;
msg.type = 1337;
msg.content.value = 0;
//printf("Sending %u packets every %luus\n", count, delay);
while(count-- > 0) {
msg_send(&msg, send_thread_pid);
xtimer_usleep( delay );
}
return 0;
}
int shell_payload(int argc, char** argv) {
/// argv[0] is the function name
if(argc == 1) {
printf("Payload is: '%s'\n", eval_message.payload);
} else {
strcpy((char*)eval_message.payload, argv[1]);
eval_message.payload_length = strlen(argv[1]);
//eval_message.payload_length = strncpy( (char*)eval_message.payload, argv[1], MAX_PAYLOAD_LENGTH);
int shell_memdump(int argc, char** argv) {
(void) argc;
(void) argv;
//irq_disable();
/// TODO(rh): dump memory
const uint8_t *addr = (const uint8_t*)0x1800;
while(addr < (const uint8_t*)0x2600) {
uint8_t i = 0;
printf("%04X: ",(unsigned int)addr);
printf("%02X ", (unsigned int)(*(addr+i)));
i++;
}
i = 0;
while(i<0xF) {
char c = *(addr+i);
printf("%c", (c >= ' ' && c <= '~') ? c : '.');
i++;
}
addr += 0xF;
puts("");
}
//irq_enable();
return 0;
}
#ifdef BOARD_INGA_BLUE
int shell_temp(int argc, char** argv) {
(void) argc;
(void) argv;
// uint8_t result;
uint8_t result[2];
i2c_acquire(0);
//i2c_read_reg(0, 0x48, 0x00, &result);
i2c_read_regs(0, 0x48, 0x00, result, 2);
i2c_release(0);
//uint16_t temp = (result[0] << 8) | (result[1] >> 4);
//printf("temperature is %d %d\n", result[0], result[1]);
//printf("temperature=%u\n", temp);
printf("temperature=%u.%d\n", result[0], (result[1]>>4) );
return 0;
}
#endif
shell_command_t eval_shell_commands[] = {
{"tx", "Sends packets", shell_tx},
{"payload", "Sets or prints the payload", shell_payload},
{"memdump", "Prints the memory", shell_memdump},
#ifdef BOARD_INGA_BLUE
{"temp", "Read temperatur", shell_temp},
#endif

Robert Hartung
committed

Robert Hartung
committed
static void _dump(gnrc_pktsnip_t *pkt) {
gnrc_pktsnip_t *snip = pkt;
gnrc_pktsnip_t *payload = NULL;
uint8_t *data;
eval_message_t *packet;
gnrc_netif_hdr_t *hdr;
uint8_t len;
char serialbuffer[256];
printf("serialbuffer: from %p to %p\n", serialbuffer, serialbuffer+256);

Robert Hartung
committed
// printf("_dump: %d %d\n", gnrc_netreg_num(GNRC_NETTYPE_UNDEF, 0), gnrc_netreg_num(GNRC_NETTYPE_NETIF, 0));
while(snip != NULL) {
switch(snip->type) {
case GNRC_NETTYPE_UNDEF :
payload = snip;
break;
case GNRC_NETTYPE_NETIF :
hdr = snip->data;
//printf("HDR: %d %d %d\n", hdr->rssi, hdr->lqi, hdr->crc_valid);
//puts("OK");

Robert Hartung
committed
packet = (eval_message_t*)payload->data;
if(hdr->crc_valid) {
if(strcmp(packet->magic_string, MAGIC_STRING) == 0) {
int length = sprintf(serialbuffer, "%u|%u|%d|%u", packet->node_id, packet->seq_nr, hdr->rssi, hdr->lqi);
if(length > 0) {
printf("<magic:ok=%u/%u\n", length, strlen( serialbuffer ));
uint8_t sum = 0;
for(uint8_t i=0; i<length; i++) {
sum += serialbuffer[i];
}
printf("<%s=%02X\n", serialbuffer, sum);
}
else {
printf("<magic:length_error:%d\n", length);

Robert Hartung
committed
} else {
/// Make sure a corrupt packet does not exceed payload size

Robert Hartung
committed
len = payload->size;
if(len > sizeof(eval_message_t)) {
len = sizeof(eval_message_t);

Robert Hartung
committed
}

Robert Hartung
committed
data = (uint8_t*)payload->data;
int tmp;
tmp = snprintf(&serialbuffer[length], sizeof(serialbuffer) - length, "%d|%u|%u|", hdr->rssi, hdr->lqi, len);
if(tmp > 0) {
length += tmp;
/// Print each single byte
for(i=0; i<len; i++) {
/// Even though " %02X" is only three characters long, we need to pass 4 because of the null terminator for the string!
tmp = snprintf(&serialbuffer[length], sizeof(serialbuffer) - length, " %02X", data[i]);
if(tmp > 0) {
length += tmp;
} else {
puts("!length error 2");
break;
}
}
for(i=0; i<length; i++) {
sum += serialbuffer[i];

Robert Hartung
committed
}
printf("<%s=%02X\n", serialbuffer, sum);
} else {
puts("!length error 1");

Robert Hartung
committed
}
}
break;
default :
printf("snip of type %d\n", snip->type);
break;
}
snip = snip->next;
}
gnrc_pktbuf_release(pkt);
}
*/
static char serialbuffer[256];

Robert Hartung
committed
void *dump_thread(void *arg)
{
(void) arg;
msg_t dump_thread_msg_queue[RCV_QUEUE_SIZE];

Robert Hartung
committed
msg_init_queue(dump_thread_msg_queue, RCV_QUEUE_SIZE);
gnrc_netreg_entry_t me_reg = GNRC_NETREG_ENTRY_INIT_PID(GNRC_NETREG_DEMUX_CTX_ALL, sched_active_pid);
gnrc_netreg_register(GNRC_NETTYPE_UNDEF, &me_reg);
msg_t msg;
gnrc_pktsnip_t *snip = NULL;
gnrc_pktsnip_t *payload = NULL;
uint8_t *data;
eval_message_t *packet;
gnrc_netif_hdr_t *hdr;
uint8_t len;
memset(serialbuffer, sizeof(serialbuffer), 0x00);

Robert Hartung
committed
while(1) {
if(msg_receive(&msg) != 1) {
puts("Unable to receive message");
continue;
}
//printf("[dump_thread] message received: %d\n", msg.type);
switch(msg.type) {
case GNRC_NETAPI_MSG_TYPE_RCV :
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
//irq_disable();
//_dump( msg.content.ptr );
snip = msg.content.ptr;
payload = NULL;
// printf("_dump: %d %d\n", gnrc_netreg_num(GNRC_NETTYPE_UNDEF, 0), gnrc_netreg_num(GNRC_NETTYPE_NETIF, 0));
while(snip != NULL) {
switch(snip->type) {
case GNRC_NETTYPE_UNDEF :
payload = snip;
break;
case GNRC_NETTYPE_NETIF :
hdr = snip->data;
//printf("HDR: %d %d %d\n", hdr->rssi, hdr->lqi, hdr->crc_valid);
//puts("OK");
if(payload == NULL) {
puts("!whoops? NULL pointer");
}
packet = (eval_message_t*)payload->data;
if(hdr->crc_valid) {
if(strcmp(packet->magic_string, MAGIC_STRING) == 0) {
puts("<magic:found");
int length = sprintf(serialbuffer, "%u|%u|%d|%u", packet->node_id, packet->seq_nr, hdr->rssi, hdr->lqi);
if(length > 0) {
printf("<magic:ok=%u/%u\n", length, strlen( serialbuffer ));
uint8_t sum = 0;
for(uint8_t i=0; i<length; i++) {
sum += serialbuffer[i];
}
printf("<%s=%02X\n", serialbuffer, sum);
}
else {
printf("<magic:length_error:%d\n", length);
}
} else {
printf("<valid\n");
/// This is another packet, ignore it!
}
} else {
/* Make sure a corrupt packet does not exceed payload size */
len = payload->size;
if(len > sizeof(eval_message_t)) {
len = sizeof(eval_message_t);
}
/* Pointer to data */
data = (uint8_t*)payload->data;
uint8_t i,
sum = 0,
length = 0;
int tmp;
tmp = snprintf(&serialbuffer[length], sizeof(serialbuffer) - length, "%d|%u|%u|", hdr->rssi, hdr->lqi, len);
if(tmp > 0) {
length += tmp;
/* Print each single byte */
for(i=0; i<len; i++) {
/// Even though " %02X" is only three characters long, we need to pass 4 because of the null terminator for the string!
tmp = snprintf(&serialbuffer[length], sizeof(serialbuffer) - length, " %02X", data[i]);
if(tmp > 0) {
length += tmp;
} else {
puts("!length error 2");
break;
}
}
for(i=0; i<length; i++) {
sum += serialbuffer[i];
}
printf("<%s=%02X\n", serialbuffer, sum);
} else {
puts("!length error 1");
}
}
break;
default :
printf("snip of type %d\n", snip->type);
break;
}
snip = snip->next;
}
gnrc_pktbuf_release(msg.content.ptr);
//irq_enable();

Robert Hartung
committed
break;
default :
puts("ERROR: Unknown message type???");
//gnrc_pktbuf_release( msg.content.ptr );

Robert Hartung
committed
break;
}
}
puts("END OF dump_thread");
return NULL;
}
static char serialbuffer2[32];

Robert Hartung
committed
void *send_thread(void *arg)
{
gnrc_netif_t *ieee802154_netif = arg;

Robert Hartung
committed
/*
struct iovec vector[2];
uint8_t hdr[IEEE802154_MAX_HDR_LEN];
uint8_t src[2] = {1,1};
uint8_t dst[2] = {0xFF, 0xFF};
//uint8_t pan[2] = {0x12, 0x34};
le_uint16_t pan = {.u16 = 0x1234};
uint8_t seq = 0;
int res = ieee802154_set_frame_hdr(hdr, src, 2, dst, 2, pan, pan, NETDEV_IEEE802154_RAW | IEEE802154_FCF_TYPE_DATA, seq);
vector[0].iov_base = hdr;
vector[0].iov_len = (size_t)res;
vector[1].iov_base = data;
vector[1].iov_len = size;
*/
size_t addr_len = 0;
uint8_t addr[GNRC_NETIF_L2ADDR_MAXLEN];
gnrc_pktsnip_t *pkt, *hdr;
gnrc_netif_hdr_t *nethdr;
netopt_enable_t enable = true;
netopt_enable_t disable = false;

Robert Hartung
committed
int ret;
ret = gnrc_netapi_set(ieee802154_netif->pid, NETOPT_PROMISCUOUSMODE, 0, &enable, sizeof(netopt_enable_t));
if(ret < 0) {
puts("Unable to set promiscous mode");
}

Robert Hartung
committed
ret = gnrc_netapi_set(ieee802154_netif->pid, NETOPT_AUTOACK, 0, &disable, sizeof(netopt_enable_t));
if(ret < 0) {
puts("Unable to disable auto ack");
}

Robert Hartung
committed
ret = gnrc_netapi_set(ieee802154_netif->pid, NETOPT_CSMA, 0, &disable, sizeof(netopt_enable_t));
if(ret < 0) {
puts("Unable to disable CSMA");
}

Robert Hartung
committed
uint8_t retrans = 0;
ret = gnrc_netapi_set(ieee802154_netif->pid, NETOPT_RETRANS, 0, &retrans, sizeof(retrans));
if(ret < 0) {
puts("Unable to set retrans = 0");
}

Robert Hartung
committed
int8_t retries = 7;
ret = gnrc_netapi_set(ieee802154_netif->pid, NETOPT_CSMA_RETRIES, 0, &retries, sizeof(retries));
if(ret < 0) {
puts("Unable to set CSMA retries = 0");
}

Robert Hartung
committed
uint8_t flags = 0 | GNRC_NETIF_HDR_FLAGS_BROADCAST;
eval_message.payload_length = snprintf((char*)eval_message.payload, MAX_PAYLOAD_LENGTH, "Hello from %2d", NODE_ID);
msg_t send_thread_msg_queue[RCV_QUEUE_SIZE];
msg_init_queue(send_thread_msg_queue, RCV_QUEUE_SIZE);
msg_t msg;
memset(serialbuffer, sizeof(serialbuffer2), 0x00);

Robert Hartung
committed
while(1) {
msg_receive(&msg);
(void)msg;
/*
//printf("[dump_thread] message received: %d\n", msg.type);
switch(msg.type) {
case GNRC_NETAPI_MSG_TYPE_RCV :
_dump( msg.content.ptr );
break;
default :
puts("ERROR: Unknown message type???");
/// gnrc_pktbuf_release( msg.content.ptr );
break;
}

Robert Hartung
committed
xtimer_sleep(SEND_INTERVAL);

Robert Hartung
committed
//printf("send... %d", sizeof(eval_message) - MAX_PAYLOAD_LENGTH + payload_length);
//printf("send...");
/* Prepare packet */
eval_message.seq_nr += 1;
pkt = gnrc_pktbuf_add(NULL, &eval_message, sizeof(eval_message) - MAX_PAYLOAD_LENGTH + eval_message.payload_length, GNRC_NETTYPE_UNDEF);

Robert Hartung
committed
if (pkt == NULL) {
puts("ERROR: packet buffer full");
return NULL;
}
hdr = gnrc_netif_hdr_build(NULL, 0, addr, addr_len);
if (hdr == NULL) {
puts("ERROR: packet buffer full");
gnrc_pktbuf_release(pkt);
return NULL;
}
LL_PREPEND(pkt, hdr);
nethdr = (gnrc_netif_hdr_t *)hdr->data;
nethdr->flags = flags;
ret = gnrc_netapi_send(ieee802154_netif->pid, pkt);
if (ret < 1) {
printf("ERROR: unable to send: %d\n", ret);

Robert Hartung
committed
gnrc_pktbuf_release(pkt);
} else {
uint8_t length = snprintf(serialbuffer2, sizeof(serialbuffer2), "%u", eval_message.seq_nr);
printf(">%s=%02X\n", serialbuffer2, sum);
//irq_enable();

Robert Hartung
committed
}
}
return NULL;
}
int main(void)
{
/// +1 -> INGA working, but TelosB/Sky not
thread_create(dump_thread_stack, sizeof(dump_thread_stack), THREAD_PRIORITY_MAIN + 1, THREAD_CREATE_STACKTEST, dump_thread, NULL, "dump_thread");
int res = i2c_init_master(I2C_DEV(0), 2);
printf("i2c init: %s\n", res == 0 ? "OK\n" : "FAILED\n");

Robert Hartung
committed
gnrc_netif_t *netif = NULL;
if((netif = gnrc_netif_iter(netif))) {
gnrc_netif_t *ieee802154_netif = netif;
printf("Found gnrc netif: %d %d\n", netif->pid, ieee802154_netif->pid);

Robert Hartung
committed
/// +2 -> INGA working, but TelosB/Sky not
send_thread_pid = thread_create(send_thread_stack, sizeof(send_thread_stack), THREAD_PRIORITY_MAIN + 2, THREAD_CREATE_STACKTEST, send_thread, ieee802154_netif, "send_thread");

Robert Hartung
committed
puts("Unable to find netif");
}

Robert Hartung
committed
(void) puts("Welcome to RIOT!");
printf("This is node %d.\n", NODE_ID);
printf("line_buf from %p to %p\n", line_buf, line_buf + sizeof(line_buf));
printf("serialbuffer: from %p to %p\n", serialbuffer, serialbuffer+sizeof(serialbuffer));
printf("serialbuffer2: from %p to %p\n", serialbuffer2, serialbuffer2+sizeof(serialbuffer2));
shell_run(eval_shell_commands, line_buf, SHELL_BUFFER_SIZE);

Robert Hartung
committed
return 0;