Contiki-Inga 3.x
contiki-inga-main.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013, TU Braunschweig
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * This file is part of the Contiki operating system.
29  */
30 
31 /**
32  * \file
33  * Contiki system setup
34  * \author Robert Hartung
35  * \author Enrico Joerns <joerns@ibr.cs.tu-bs.de>
36  */
37 
38 #define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
39 
40 #define PRINTA(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
41 
42 /* If defined 1, prints debug infos. */
43 #ifndef DEBUG
44 #define DEBUG 1
45 #endif
46 
47 #if DEBUG
48 #define PRINTD(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
49 #else
50 #define PRINTD(...)
51 #endif
52 
53 /* Track interrupt flow through mac, rdc and radio driver */
54 #if DEBUGFLOWSIZE
55 uint8_t debugflowsize, debugflow[DEBUGFLOWSIZE];
56 #define DEBUGFLOW(c) if (debugflowsize<(DEBUGFLOWSIZE-1)) debugflow[debugflowsize++]=c
57 #else
58 #define DEBUGFLOW(c)
59 #endif
60 
61 #include <avr/io.h>
62 #include <util/delay.h>
63 #include <stdio.h>
64 #include <stdbool.h>
65 #include <string.h>
66 
67 #include "dev/watchdog.h"
68 
69 // settings manager
70 #include "lib/settings.h"
71 
72 // sensors
73 #include "lib/sensors.h"
74 #include "dev/button-sensor.h"
75 #include "dev/acc-sensor.h"
76 #include "dev/gyro-sensor.h"
77 #include "dev/pressure-sensor.h"
78 #include "dev/battery-sensor.h"
79 #include "dev/at45db.h"
80 
81 #include "ip/uip.h"
82 
83 #if RF230BB //radio driver using contiki core mac
84 #include "radio/rf230bb/rf230bb.h"
85 #include "net/mac/frame802154.h"
86 #include "net/mac/framer-802154.h"
87 #include "net/ipv6/sicslowpan.h"
88 
89 #else //radio driver using Atmel/Cisco 802.15.4'ish MAC
90 #include "mac.h"
91 #include "sicslowmac.h"
92 #include "sicslowpan.h"
93 #include "ieee-15-4-manager.h"
94 #endif /*RF230BB*/
95 
96 #include "contiki.h"
97 #include "contiki-net.h"
98 #include "contiki-lib.h"
99 #include "sys/node-id.h"
100 
101 #include "dev/rs232.h"
102 #include "dev/serial-line.h"
103 #include "dev/slip.h"
104 
105 #if AVR_WEBSERVER
106 #include "httpd-fs.h"
107 #include "httpd-cgi.h"
108 #endif
109 
110 #ifdef COFFEE_FILES
111 #include "cfs/cfs-coffee.h"
112 #endif
113 
114 #if WITH_UIP6
115 #include "net/ipv6/uip-ds6.h"
116 // function declaration for net/uip-debug.c
117 void uip_debug_ipaddr_print(const uip_ipaddr_t *addr);
118 void uip_debug_lladdr_print(const uip_lladdr_t *addr);
119 #endif /* WITH_UIP6 */
120 
121 #include "net/rime/rime.h"
122 
123 // Apps
124 #if (APP_SETTINGS_DELETE == 1)
125 #include "settings_delete.h"
126 #endif
127 #if (APP_SETTINGS_SET == 1)
128 #include "settings_set.h"
129 #endif
130 
131 /* Get periodic prints from idle loop, from clock seconds or rtimer interrupts */
132 /* Use of rtimer will conflict with other rtimer interrupts such as contikimac radio cycling */
133 /* STAMPS will print ENERGEST outputs if that is enabled. */
134 #ifndef INGA_CONF_PERIODIC
135 #define INGA_PERIODIC 1
136 #else
137 #define INGA_PERIODIC INGA_CONF_PERIODIC
138 #endif
139 
140 /** Enables route prints with given interval [seconds] */
141 #ifndef INGA_CONF_PERIODIC_ROUTES
142 #define INGA_PERIODIC_ROUTES 0
143 #else
144 #define INGA_PERIODIC_ROUTES INGA_CONF_PERIODIC_ROUTES
145 #if INGA_PERIODIC_ROUTES > 0 && !UIP_CONF_IPV6
146 #error Periodic routes only supported for IPv6
147 #endif
148 #endif
149 /** Enables time stamps with given interval [seconds] */
150 #ifndef INGA_CONF_PERIODIC_STAMPS
151 #define PER_STAMPS 60
152 #else
153 #define PER_STAMPS INGA_CONF_PERIODIC_STAMPS
154 #endif
155 /** Activates stack monitor with given interval [seconds] */
156 #ifndef INGA_CONF_PERIODIC_STACK
157 #define INGA_PERIODIC_STACK 60
158 #else
159 #define INGA_PERIODIC_STACK INGA_CONF_PERIODIC_STACK
160 #endif
161 
162 
163 #ifndef USART_BAUD_INGA
164 #define USART_BAUD_INGA USART_BAUD_19200
165 #endif
166 
167 /*-------------------------------------------------------------------------*/
168 /*----------------------Configuration of the .elf file---------------------*/
169 #if (__AVR_LIBC_VERSION__ >= 10700UL)
170 /* The proper way to set the signature is */
171 #include <avr/signature.h>
172 #else
173 
174 /* signature API not available before avr-lib-1.7.0. Do it manually.*/
175 typedef struct {
176  const unsigned char B2;
177  const unsigned char B1;
178  const unsigned char B0;
179 } __signature_t;
180 #define SIGNATURE __signature_t __signature __attribute__((section (".signature")))
181 SIGNATURE = {
182  .B2 = 0x05, //SIGNATURE_2, //ATMEGA1284p
183  .B1 = 0x97, //SIGNATURE_1, //128KB flash
184  .B0 = 0x1E, //SIGNATURE_0, //Atmel
185 };
186 #endif /* (__AVR_LIBC_VERSION__ >= 10700UL) */
187 
188 #define INGA_CONF_RANDOM_BSN_SEQNO 1
189 #if INGA_CONF_RANDOM_BSN_SEQNO || INGA_CONF_RANDOM_MAC
190 #include "dev/adc.h"
191 /** Get a pseudo random number using the ADC. */
192 static uint8_t
193 rng_get_uint8(void)
194 {
195  uint8_t i, j = 0;
197  adc_set_mux(0x1E);
198  for( i = 0; i < 4; i++) {
199  j += adc_get_value() & 0xFF;
200  }
201  adc_deinit();
202  printf("rng issues %d\n", j);
203  return j;
204 }
205 #endif /* INGA_CONF_RANDOM_BSN_SEQNO || INGA_CONF_RANDOM_MAC */
206 /*----------------------------------------------------------------------------*/
207 // NOTE: fixed parts are for 802.15.4 -> Ethernet MAC address matching
208 // according to [RFC 2373, Appendix A].
209 static void
210 generate_new_eui64(uint8_t eui64[8])
211 {
212  eui64[0] = 0x02;
213  eui64[1] = rng_get_uint8();
214  eui64[2] = rng_get_uint8();
215  eui64[3] = 0xFF;
216  eui64[4] = 0xFE;
217  eui64[5] = rng_get_uint8();
218  eui64[6] = rng_get_uint8();
219  eui64[7] = rng_get_uint8();
220 }
221 /*----------------------------------------------------------------------------*/
222 // implements log function from uipopt.h
223 void
224 uip_log(char *msg)
225 {
226  printf("%s\n", msg);
227 }
228 /*----------------------------------------------------------------------------*/
229 struct inga_config_s {
230  uint8_t eui64_addr[8];
231  uint8_t radio_channel;
232  uint8_t radio_tx_power;
233  uint16_t pan_id;
234  uint16_t pan_addr; // short address
235 };
236 struct inga_config_s inga_cfg; // Keep global!
237 /*----------------------------------------------------------------------------*/
238 // implement sys/node-id.h interface
239 unsigned short node_id = NODE_ID;
240 /*----------------------------------------------------------------------------*/
241 void node_id_restore(void) {
242  node_id = settings_get_uint16(SETTINGS_KEY_PAN_ADDR, 0);
243 }
244 /*----------------------------------------------------------------------------*/
245 void node_id_burn(unsigned short node_id) {
246  if (settings_set_uint16(SETTINGS_KEY_PAN_ADDR, (uint16_t) node_id) == SETTINGS_STATUS_OK) {
247  uint16_t settings_nodeid = settings_get_uint16(SETTINGS_KEY_PAN_ADDR, 0);
248  PRINTF("New Node ID: %04X\n", settings_nodeid);
249  } else {
250  PRINTF("Error: Error while writing NodeID to EEPROM\n");
251  }
252 }
253 /*----------------------------------------------------------------------------*/
254 #define CONVERTTXPOWER 1
255 #if CONVERTTXPOWER //adds ~120 bytes to program flash size
256 // NOTE: values for AT86RF231
257 const char txonesdigit[16] PROGMEM = {'3','2','2','1','1','0','0','1','2','3','4','5','7','9','2','7'};
258 const char txtenthsdigit[16] PROGMEM = {'0','8','3','8','3','7','0','0','0','0','0','0','0','0','0','0'};
259 static void printtxpower(void) {
260  uint8_t power = rf230_get_txpower() & 0xf;
261  char sign = (power < 0x7 ? '+' : '-');
262  char tens = (power > 0xD ? '1' : '0');
263  char ones = pgm_read_byte(&txonesdigit[power]);
264  char tenths = pgm_read_byte(&txtenthsdigit[power]);
265  if (tens == '0') {
266  printf_P(PSTR("%c%c.%cdBm"), sign, ones, tenths);
267  } else {
268  printf_P(PSTR("%c%c%c.%cdBm"), sign, tens, ones, tenths);
269  }
270 }
271 #endif
272 /*----------------------------------------------------------------------------*/
273 
274 // -- Bootscreen define parameters
275 
276 #ifndef INGA_CONF_BOOTSCREEN
277 #define INGA_BOOTSCREEN 1
278 #else /* INGA_CONF_BOOTSCREEN */
279 #define INGA_BOOTSCREEN INGA_CONF_BOOTSCREEN
280 #endif /* INGA_CONF_BOOTSCREEN */
281 
282 #if INGA_BOOTSCREEN
283 #ifndef INGA_CONF_BOOTSCREEN_NET
284 #define INGA_BOOTSCREEN_NET 1
285 #else /* INGA_CONF_BOOTSCREEN_NET */
286 #define INGA_BOOTSCREEN_NET INGA_CONF_BOOTSCREEN_NET
287 #endif /* INGA_CONF_BOOTSCREEN_NET */
288 
289 #ifndef INGA_CONF_BOOTSCREEN_NETSTACK
290 #define INGA_BOOTSCREEN_NETSTACK 1
291 #else /* INGA_CONF_BOOTSCREEN_NETSTACK */
292 #define INGA_BOOTSCREEN_NETSTACK INGA_CONF_BOOTSCREEN_NETSTACK
293 #endif /* INGA_CONF_BOOTSCREEN_NETSTACK */
294 
295 #ifndef INGA_CONF_BOOTSCREEN_RADIO
296 #define INGA_BOOTSCREEN_RADIO 1
297 #else /* INGA_CONF_BOOTSCREEN_RADIO */
298 #define INGA_BOOTSCREEN_RADIO INGA_CONF_BOOTSCREEN_RADIO
299 #endif /* INGA_CONF_BOOTSCREEN_RADIO */
300 
301 #ifndef INGA_CONF_BOOTSCREEN_SENSORS
302 #define INGA_BOOTSCREEN_SENSORS 1
303 #else /* INGA_CONF_BOOTSCREEN_SENSORS */
304 #define INGA_BOOTSCREEN_SENSORS INGA_CONF_BOOTSCREEN_SENSORS
305 #endif /* INGA_CONF_BOOTSCREEN_SENSORS */
306 
307 #else /* INGA_BOOTSCREEN */
308 #define INGA_BOOTSCREEN_NET 0
309 #define INGA_BOOTSCREEN_NETSTACK 0
310 #define INGA_BOOTSCREEN_RADIO 0
311 #define INGA_BOOTSCREEN_SENSORS 0
312 #endif /* INGA_BOOTSCREEN */
313 
314 #if INGA_BOOTSCREEN_SENSORS
315 const char msg_ok[6] PROGMEM = "[OK]\n";
316 const char msg_err[7] PROGMEM = "[N/A]\n";
317 #define CHECK_SENSOR(name, sensor) \
318  printf_P(PSTR(" " name ": ")); \
319  printf_P(sensor.status(SENSORS_READY) ? msg_ok : msg_err);
320 #endif
321 /*----------------------------------------------------------------------------*/
322 #define eui64_is_null(eui64) \
323  ((eui64[0] == 0x00) \
324  && (eui64[1] == 0x00) \
325  && (eui64[2] == 0x00) \
326  && (eui64[3] == 0x00) \
327  && (eui64[4] == 0x00) \
328  && (eui64[5] == 0x00) \
329  && (eui64[6] == 0x00) \
330  && (eui64[7] == 0x00))
331 /*----------------------------------------------------------------------------*/
332 #define pan_addr_from_eui64(eui64) \
333  (uint16_t) (eui64[0] + eui64[1] + eui64[2] + eui64[3] + eui64[4] + eui64[5] + eui64[6] + eui64[7]);
334 /*----------------------------------------------------------------------------*/
335 static void
336 load_config(struct inga_config_s* cfg)
337 {
338  /* EUI64 ADDR */
339 #ifndef NODE_CONF_EUI64
340  if (settings_check(SETTINGS_KEY_EUI64, 0) == true) {
341  settings_get(SETTINGS_KEY_EUI64, 0, (void*) &(cfg->eui64_addr), sizeof(cfg->eui64_addr));
342  } else {
343  PRINTD("EUI-64 not in EEPROM\n");
344  }
345 #else
346  cfg->eui64_addr = {NODE_EUI64};
347 #endif /* NODE_CONF_EUI64 */
348 
349  // PAN_ID
350 #ifndef RADIO_CONF_PAN_ID
351  if (settings_check(SETTINGS_KEY_PAN_ID, 0) == true) {
352  cfg->pan_id = settings_get_uint16(SETTINGS_KEY_PAN_ID, 0);
353  } else {
354  cfg->pan_id = RADIO_PAN_ID;
355  PRINTD("PanID not in EEPROM - using default (0x%04x)\n", cfg->pan_id);
356  }
357 #else /* RADIO_CONF_PAN_ID */
358  cfg->pan_id = RADIO_PAN_ID;
359 #endif /* RADIO_CONF_PAN_ID */
360 
361  // PAN_ADDR/NODE_ID
362 #ifndef NODE_CONF_ID
363  if (settings_check(SETTINGS_KEY_PAN_ADDR, 0) == true) {
364  cfg->pan_addr = settings_get_uint16(SETTINGS_KEY_PAN_ADDR, 0);
365  } else {
366  PRINTD("PanAddr not in EEPROM\n");
367  }
368 #else
369  cfg->pan_adr = NODE_ID;
370 #endif /* NODE_CONF_ID */
371 
372  /* TX_POWER */
373 #ifndef RADIO_CONF_TX_POWER
374  if (settings_check(SETTINGS_KEY_TXPOWER, 0) == true) {
375  cfg->radio_tx_power = settings_get_uint8(SETTINGS_KEY_TXPOWER, 0);
376  } else {
377  cfg->radio_tx_power = RADIO_TX_POWER;
378  PRINTD("Radio TXPower not in EEPROM - using default (%d)\n", cfg->radio_tx_power);
379  }
380 #else
381  cfg->radio_tx_power = RADIO_TX_POWER;
382 #endif /* RADIO_CONF_TX_POWER */
383 
384  /* CHANNEL */
385 #ifndef RADIO_CONF_CHANNEL
386  if (settings_check(SETTINGS_KEY_CHANNEL, 0) == true) {
387  cfg->radio_channel = settings_get_uint8(SETTINGS_KEY_CHANNEL, 0);
388  } else {
389  cfg->radio_channel = RADIO_CHANNEL;
390  PRINTD("Radio Channel not in EEPROM - using default (%d)\n", cfg->radio_channel);
391  }
392 #else
393  cfg->radio_channel = RADIO_CHANNEL;
394 #endif /* RADIO_CONF_CHANNEL */
395 
396 /* Write new settings */
397 #if WRITE_EUI64
398  if (settings_set(SETTINGS_KEY_EUI64, eui64_addr, sizeof (cfg->eui64_addr)) == SETTINGS_STATUS_OK) {
399  PRINTD("Wrote new IEEE Addr to EEPROM.\n");
400  } else {
401  PRINTD("Failed writing IEEE Addr to EEPROM.\n");
402  }
403 #endif /* WRITE_EUI64 */
404 
405  /* Overwrite with node id if set */
406  if (node_id > 0) {
407 #if UIP_CONF_IPV6
408  memset(cfg->eui64_addr, 0, sizeof(cfg->eui64_addr));
409  cfg->eui64_addr[6] = (node_id >> 8);
410  cfg->eui64_addr[7] = node_id & 0xFF;
411 #else /* UIP_CONF_IPV6 */
412  cfg->eui64_addr[0] = node_id & 0xFF;
413  cfg->eui64_addr[1] = (node_id >> 8);
414 #endif /* UIP_CONF_IPV6 */
415  cfg->pan_addr = node_id;
416  } else {
417  /* If we do not have a EUI64 we generate one */
418  if(eui64_is_null(cfg->eui64_addr)) {
419  generate_new_eui64(cfg->eui64_addr);
420  }
421  /* If we do not have a pan address, we generate one */
422  if(cfg->pan_addr == 0) {
423  cfg->pan_addr = pan_addr_from_eui64(cfg->eui64_addr);
424  }
425  }
426 
427 #if INGA_BOOTSCREEN_NET
428  PRINTA("WPAN Info:\n");
429  PRINTA(" EUI-64: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n\r",
430  cfg->eui64_addr[0],
431  cfg->eui64_addr[1],
432  cfg->eui64_addr[2],
433  cfg->eui64_addr[3],
434  cfg->eui64_addr[4],
435  cfg->eui64_addr[5],
436  cfg->eui64_addr[6],
437  cfg->eui64_addr[7]);
438  PRINTA(" PAN ID: 0x%04X\n", cfg->pan_id);
439  PRINTA(" PAN ADDR: 0x%04X\n", cfg->pan_addr);
440 #endif /* INGA_BOOTSCREEN_NET */
441 
442 }
443 /*----------------------------------------------------------------------------*/
444 void
445 platform_radio_init(struct inga_config_s* cfg)
446 {
447  /* Start radio and radio receive process */
448  NETSTACK_RADIO.init();
449 
450  if (eui64_is_null(cfg->eui64_addr)) {
451  rf230_set_pan_addr( cfg->pan_id, cfg->pan_addr, NULL);
452  } else {
453  rf230_set_pan_addr( cfg->pan_id, cfg->pan_addr, cfg->eui64_addr);
454  }
455 
456  rf230_set_channel(cfg->radio_channel);
457  rf230_set_txpower(cfg->radio_tx_power);
458 
459  /* Initialize stack protocols */
460  queuebuf_init();
461  NETSTACK_RDC.init();
462  NETSTACK_MAC.init();
463  NETSTACK_NETWORK.init();
464 
465 #if INGA_BOOTSCREEN_NETSTACK
466  PRINTA("Netstack info:\n");
467  PRINTA(" NET: %s\n MAC: %s\n RDC: %s\n",
468  NETSTACK_NETWORK.name,
469  NETSTACK_MAC.name,
470  NETSTACK_RDC.name);
471 #endif /* INGA_BOOTSCREEN_NETSTACK */
472 
473 #if INGA_BOOTSCREEN_RADIO
474  PRINTA("Radio info:\n");
475  PRINTA(" Check rate %lu Hz\n Channel: %u\n Power: %u",
476  CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1 :
477  NETSTACK_RDC.channel_check_interval()), // radio??
478  rf230_get_channel(),
479  rf230_get_txpower());
480 #if CONVERTTXPOWER
481  printf(" (");
482  printtxpower();
483  printf(")");
484 #endif /* CONVERTTXPOWER */
485  printf("\n");
486 #endif /* INGA_BOOTSCREEN_RADIO */
487 }
488 
489 /*-------------------------Low level initialization------------------------*/
490 /*------Done in a subroutine to keep main routine stack usage small--------*/
491 void
492 init(void)
493 {
494  extern void *watchdog_return_addr;
495  extern uint8_t mcusr_mirror;
496 
497  /* Save the address where the watchdog occurred */
498  void *wdt_addr = watchdog_return_addr;
499  MCUSR = 0;
500 
501  watchdog_init();
502  watchdog_start();
503 
504  /* Second rs232 port for debugging */
505  rs232_init(RS232_PORT_0, USART_BAUD_INGA, USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8);
506  /* Redirect stdout to second port */
507  rs232_redirect_stdout(RS232_PORT_0);
508 
509  /* wait here to get a chance to see boot screen. */
510  _delay_ms(200);
511 
512 #if INGA_BOOTSCREEN
513  PRINTA("\n*******Booting %s*******\nReset reason: ", CONTIKI_VERSION_STRING);
514  /* Print out reset reason */
515  if (mcusr_mirror & _BV(JTRF))
516  PRINTA("JTAG ");
517  if (mcusr_mirror & _BV(WDRF))
518  PRINTA("Watchdog ");
519  if (mcusr_mirror & _BV(BORF))
520  PRINTA("Brown-out ");
521  if (mcusr_mirror & _BV(EXTRF))
522  PRINTA("External ");
523  if (mcusr_mirror & _BV(PORF))
524  PRINTA("Power-on ");
525  PRINTA("\n");
526  if (mcusr_mirror & _BV(WDRF))
527  PRINTA("Watchdog possibly occured at address %p\n", wdt_addr);
528 #endif /* INGA_BOOTSCREEN */
529 
530  clock_init();
531 
532 #if INGA_PERIODIC_STACK
533 #define STACK_FREE_MARK 0x4242
534  /* Simple stack pointer highwater monitor.
535  * Places magic numbers in free RAM that are checked in the main loop.
536  * In conjuction with INGA_PERIODIC, never-used stack will be printed
537  * every INGA_PERIODIC_STACK seconds.
538  */
539  {
540  extern uint16_t __bss_end;
541  uint16_t p = (uint16_t) & __bss_end;
542  do {
543  *(uint16_t *) p = STACK_FREE_MARK;
544  p += 10;
545  } while (p < SP - 10); //don't overwrite our own stack
546  }
547 #endif
548 
549  /* Get a random (or probably different) seed for the 802.15.4 packet sequence number.
550  * Some layers will ignore duplicates found in a history (e.g. Contikimac)
551  * causing the initial packets to be ignored after a short-cycle restart.
552  */
553 #if INGA_CONF_RANDOM_BSN_SEQNO
554  random_init(rng_get_uint8());
555 #endif
556 
557 
558  /* Flash initialization */
559  at45db_init();
560 
561 #ifdef MICRO_SD_PWR_PIN
562  /* set pin for micro sd card power switch to output */
563  MICRO_SD_PWR_PORT_DDR |= (1 << MICRO_SD_PWR_PIN);
564 #endif
565 
566  /* rtimers needed for radio cycling */
567  rtimer_init();
568 
569  /* Initialize process subsystem */
570  process_init();
571 
572  /* etimers must be started before ctimer_init */
573  process_start(&etimer_process, NULL);
574 
575  ctimer_init();
576 
577 #if (APP_SETTINGS_SET == 1)
578  process_start(&settings_set_process, NULL);
579 #endif
580 
581 #if (APP_SETTINGS_DELETE == 1)
582  process_start(&settings_delete_process, NULL);
583 #endif
584 
585  /* load stuff from eeprom */
586  load_config(&inga_cfg); // TODO: variable placement?
587 
588  //--- Set Link address based on eui64
589  // TODO: copy address correctly!!!
590  linkaddr_t addr;
591 #if LINKADDR_SIZE == 2
592  linkaddr_set_node_addr(&(inga_cfg.pan_addr));
593 #elif LINKADDR_SIZE == 8
594  //memcpy(addr.u8, inga_cfg.eui64_addr, sizeof (linkaddr_t));
595  linkaddr_set_node_addr(&inga_cfg.eui64_addr);
596 #else
597 #error LINKADDR_SIZE not supported
598 #endif
599 
600 #if PLATFORM_RADIO
601  // Init radio
602  platform_radio_init(&inga_cfg);
603 #endif
604 
605 #if UIP_CONF_IPV6
606  // Copy EUI64 to the link local address
607  memcpy(&uip_lladdr.addr, &(inga_cfg.eui64_addr), sizeof (uip_lladdr.addr));
608 
609  process_start(&tcpip_process, NULL);
610 
611 #if INGA_BOOTSCREEN_NET
612  PRINTA("IPv6 info:\n");
613  PRINTA(" Tentative link-local IPv6 address ");
614  uip_ds6_addr_t *lladdr;
615  lladdr = uip_ds6_get_link_local(-1);
616  uip_debug_ipaddr_print(&(lladdr->ipaddr));
617  PRINTA("\n");
618 
619 #if UIP_CONF_IPV6_RPL
620  PRINTA(" RPL Enabled\n");
621 #endif
622 #if UIP_CONF_ROUTER
623  PRINTA(" Routing Enabled, TCP_MSS: %u\n", UIP_TCP_MSS);
624 #endif
625 #endif /* INGA_BOOTSCREEN_NET */
626 
627 #else /* UIP_CONF_IPV6 */
628 
629 #if INGA_BOOTSCREEN_NET
630  PRINTA("rime address:\n ");
631  int i;
632  for (i = 0; i < sizeof (linkaddr_t); i++) {
633  PRINTA("%02x.", addr.u8[i]);
634  }
635  PRINTA("\n");
636 #endif /* INGA_BOOTSCREEN_NET */
637 
638 #endif /* UIP_CONF_IPV6 */
639 
640  /* Start sensor init process */
641  process_start(&sensors_process, NULL);
642 
643 #if INGA_BOOTSCREEN_SENSORS
644  PRINTA("Sensors:\n");
645  CHECK_SENSOR("Button", button_sensor);
646  CHECK_SENSOR("Accelerometer", acc_sensor);
647  CHECK_SENSOR("Gyroscope", gyro_sensor);
648  CHECK_SENSOR("Pressure", pressure_sensor);
649  CHECK_SENSOR("Battery", battery_sensor);
650 #endif
651 
652 #if INGA_BOOTSCREEN
653  PRINTA("******* Online *******\n\n");
654 #endif
655 }
656 
657 /*---------------------------------------------------------------------------*/
658 #if INGA_PERIODIC
659 static void
660 periodic_prints()
661 {
662  static uint32_t clocktime;
663 
664  if (clocktime != clock_seconds()) {
665  clocktime = clock_seconds();
666 
667 #if PER_STAMPS
668  /* Print time stamps. */
669  if ((clocktime % PER_STAMPS) == 0) {
670 #if ENERGEST_CONF_ON
671 #include "lib/print-stats.h"
672  print_stats();
673 #elif RADIOSTATS
674  extern volatile unsigned long radioontime;
675  PRINTF("%u(%u)s\n", clocktime, radioontime);
676 #else /* RADIOSTATS */
677  PRINTF("%us\n", clocktime);
678 #endif /* RADIOSTATS */
679  }
680 #endif /* PER_STAMPS */
681 
682 #if INGA_PERIODIC_ROUTES
683  if ((clocktime % INGA_PERIODIC_ROUTES) == 2) {
684 
685  extern uip_ds6_netif_t uip_ds6_if;
686  uint8_t i, any;
687  uip_ds6_nbr_t *nbr;
688 
689  PRINTA("\nAddresses [%u max]\n", UIP_DS6_ADDR_NB);
690  for (i = 0; i < UIP_DS6_ADDR_NB; i++) {
691  if (uip_ds6_if.addr_list[i].isused) {
692  PRINTA(" ");
693  uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr);
694  PRINTA("\n");
695  }
696  }
697 
698  PRINTA("\nNeighbors [%u max]\n",NBR_TABLE_MAX_NEIGHBORS);
699  any = 0;
700  for(nbr = nbr_table_head(ds6_neighbors);
701  nbr != NULL;
702  nbr = nbr_table_next(ds6_neighbors, nbr)) {
703  PRINTA(" ");
704  uip_debug_ipaddr_print(&nbr->ipaddr);
705  PRINTA(" lladdr ");
706  uip_debug_lladdr_print(uip_ds6_nbr_get_ll(nbr));
707  if (nbr->isrouter) PRINTA(" router");
708  switch (nbr->state) {
709  case NBR_INCOMPLETE:
710  PRINTA(" INCOMPLETE");
711  break;
712  case NBR_REACHABLE:
713  PRINTA(" REACHABLE");
714  break;
715  case NBR_STALE:
716  PRINTA(" STALE");
717  break;
718  case NBR_DELAY:
719  PRINTA(" DELAY");
720  break;
721  case NBR_PROBE:
722  PRINTA(" PROBE");
723  break;
724  }
725  PRINTA("\n");
726  any = 1;
727  }
728  if (!any) PRINTA(" <none>\n");
729 
730  PRINTA("\nRoutes [%u max]\n",UIP_DS6_ROUTE_NB);
731  uip_ds6_route_t *r;
732  any = 0;
733  for(r = uip_ds6_route_head();
734  r != NULL;
735  r = uip_ds6_route_next(r)) {
736  PRINTA(" ");
737  uip_debug_ipaddr_print(&r->ipaddr);
738  PRINTA("/%u (via ", r->length);
739  uip_debug_ipaddr_print(uip_ds6_route_nexthop(r));
740  PRINTA(") %lus\n", r->state.lifetime);
741  any = 1;
742  }
743  if (!any) PRINTA(" <none>\n");
744  PRINTA("\n---------\n");
745  }
746 #endif /* INGA_PERIODIC_ROUTES */
747 
748 #if INGA_PERIODIC_STACK
749  /* Checks for highest address with STACK_FREE_MARKs in RAM */
750  if ((clocktime % INGA_PERIODIC_STACK) == 3) {
751  extern uint16_t __bss_end;
752  uint16_t p = (uint16_t) & __bss_end;
753  do {
754  if (*(uint16_t *) p != STACK_FREE_MARK) {
755  PRINTF("Never-used stack > %d bytes\n", p - (uint16_t) & __bss_end);
756  break;
757  }
758  p += 10;
759  } while (p < RAMEND - 10);
760  }
761 #endif /* INGA_PERIODIC_STACK */
762  }
763 }
764 #endif /* INGA_PERIODIC */
765 /*-------------------------------------------------------------------------*/
766 /*------------------------- Main Scheduler loop----------------------------*/
767 /*-------------------------------------------------------------------------*/
768 
769 // setup sensors
770 SENSORS(&button_sensor, &acc_sensor, &gyro_sensor, &pressure_sensor, &battery_sensor);
771 
772 int
773 main(void)
774 {
775  init();
776 
777  /* Autostart other processes */
778  autostart_start(autostart_processes);
779 
780  while (1) {
781  process_run();
783 
784 #if DEBUGFLOWSIZE
785  if (debugflowsize) {
786  debugflow[debugflowsize] = 0;
787  PRINTF("%s", debugflow);
788  debugflowsize = 0;
789  }
790 #endif
791 
793 
794 #if INGA_PERIODIC
795  periodic_prints();
796 #endif /* INGA_PERIODIC */
797 
798  }
799  return 0;
800 }
801 /*---------------------------------------------------------------------------*/
802 /* implements sys/log interface */
803 void
804 log_message(char *m1, char *m2)
805 {
806  PRINTF("%s%s\n", m1, m2);
807 }