Contiki 2.5
contiki-mc1322x-main.c
1 /*
2  * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors
3  * to the MC1322x project (http://mc1322x.devl.org) and Contiki.
4  *
5  * Copyright (c) 2006, Technical University of Munich
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  * notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  * notice, this list of conditions and the following disclaimer in the
15  * documentation and/or other materials provided with the distribution.
16  * 3. Neither the name of the Institute nor the names of its contributors
17  * may be used to endorse or promote products derived from this software
18  * without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * This file is part of the Contiki operating system.
33  *
34  * @(#)$$
35  */
36 
37 #include <signal.h>
38 #include <stdio.h>
39 #include <string.h>
40 
41 #include "contiki.h"
42 
43 #include "dev/leds.h"
44 #include "dev/serial-line.h"
45 #include "dev/slip.h"
46 #include "dev/xmem.h"
47 #include "dev/button-sensor.h"
48 #include "lib/random.h"
49 #include "net/netstack.h"
50 #include "net/mac/frame802154.h"
51 #include "lib/include/mc1322x.h"
52 
53 #if WITH_UIP6
54 #include "net/sicslowpan.h"
55 #include "net/uip-ds6.h"
56 #include "net/mac/sicslowmac.h"
57 #endif /* WITH_UIP6 */
58 
59 #include "net/rime.h"
60 
61 #include "sys/autostart.h"
62 #include "sys/profile.h"
63 
64 /* from libmc1322x */
65 #include "mc1322x.h"
66 #include "default_lowlevel.h"
67 #include "contiki-maca.h"
68 #include "contiki-uart.h"
69 
70 /* Get periodic prints from idle loop, from clock seconds or rtimer interrupts */
71 /* Use of rtimer will conflict with other rtimer interrupts such as contikimac radio cycling */
72 #define PERIODICPRINTS 0
73 #if PERIODICPRINTS
74 //#define PINGS 64
75 #define ROUTES 300
76 #define STAMPS 60
77 #define STACKMONITOR 600
78 //#define HEAPMONITOR 60
79 uint16_t clocktime;
80 #define TESTRTIMER 0
81 #if TESTRTIMER
82 uint8_t rtimerflag=1;
83 struct rtimer rt;
84 void rtimercycle(void) {rtimerflag=1;}
85 #endif
86 #endif
87 
88 #define DEBUG 0
89 #if DEBUG
90 #include <stdio.h>
91 #define PRINTF(...) printf(__VA_ARGS__)
92 #define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15])
93 #define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",(lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3],(lladdr)->addr[4], (lladdr)->addr[5])
94 #else
95 #define PRINTF(...)
96 #define PRINT6ADDR(addr)
97 #define PRINTLLADDR(addr)
98 #endif
99 
100 #ifndef RIMEADDR_NVM
101 #define RIMEADDR_NVM 0x1E000
102 #endif
103 
104 #ifndef RIMEADDR_NBYTES
105 #define RIMEADDR_NBYTES 8
106 #endif
107 
108 #if UIP_CONF_ROUTER
109 
110 #ifndef UIP_ROUTER_MODULE
111 #ifdef UIP_CONF_ROUTER_MODULE
112 #define UIP_ROUTER_MODULE UIP_CONF_ROUTER_MODULE
113 #else /* UIP_CONF_ROUTER_MODULE */
114 #define UIP_ROUTER_MODULE rimeroute
115 #endif /* UIP_CONF_ROUTER_MODULE */
116 #endif /* UIP_ROUTER_MODULE */
117 
118 extern const struct uip_router UIP_ROUTER_MODULE;
119 
120 #endif /* UIP_CONF_ROUTER */
121 
122 #if DCOSYNCH_CONF_ENABLED
123 static struct timer mgt_timer;
124 #endif
125 
126 #ifndef WITH_UIP
127 #define WITH_UIP 0
128 #endif
129 
130 #if WITH_UIP
131 #include "net/uip.h"
132 #include "net/uip-fw.h"
133 #include "net/uip-fw-drv.h"
134 #include "net/uip-over-mesh.h"
135 static struct uip_fw_netif slipif =
136  {UIP_FW_NETIF(192,168,1,2, 255,255,255,255, slip_send)};
137 static struct uip_fw_netif meshif =
138  {UIP_FW_NETIF(172,16,0,0, 255,255,0,0, uip_over_mesh_send)};
139 
140 #endif /* WITH_UIP */
141 
142 #define UIP_OVER_MESH_CHANNEL 8
143 #if WITH_UIP
144 static uint8_t is_gateway;
145 #endif /* WITH_UIP */
146 
147 /*---------------------------------------------------------------------------*/
148 void uip_log(char *msg) { printf("%c",msg); }
149 /*---------------------------------------------------------------------------*/
150 #ifndef RF_CHANNEL
151 #define RF_CHANNEL 26
152 #endif
153 /*---------------------------------------------------------------------------*/
154 #if WITH_UIP
155 static void
156 set_gateway(void)
157 {
158  if(!is_gateway) {
159  leds_on(LEDS_RED);
160  printf("%d.%d: making myself the IP network gateway.\n\n",
162  printf("IPv4 address of the gateway: %d.%d.%d.%d\n\n",
163  uip_ipaddr_to_quad(&uip_hostaddr));
164  uip_over_mesh_set_gateway(&rimeaddr_node_addr);
165  uip_over_mesh_make_announced_gateway();
166  is_gateway = 1;
167  }
168 }
169 #endif /* WITH_UIP */
170 /*---------------------------------------------------------------------------*/
171 static void
172 print_processes(struct process * const processes[])
173 {
174  /* const struct process * const * p = processes;*/
175  printf("Starting");
176  while(*processes != NULL) {
177  printf(" '%s'", (*processes)->name);
178  processes++;
179  }
180  printf("\n");
181 }
182 /*--------------------------------------------------------------------------*/
183 
184 SENSORS(&button_sensor);
185 
186 void
187 init_lowlevel(void)
188 {
189  /* button init */
190  /* set up kbi */
191  enable_irq_kbi(4);
192  kbi_edge(4);
193  enable_ext_wu(4);
194 // kbi_pol_neg(7);
195 // kbi_pol_pos(7);
196 // gpio_sel0_pullup(29);
197 // gpio_pu0_disable(29);
198 
199  trim_xtal();
200 
201  /* uart init */
202  uart_init(BRINC, BRMOD, SAMP);
203 
204  default_vreg_init();
205 
206  maca_init();
207 
208  set_channel(RF_CHANNEL - 11); /* channel 11 */
209  set_power(0x12); /* 0x12 is the highest, not documented */
210 
211  enable_irq(CRM);
212 
213 #if USE_32KHZ_XTAL
214  enable_32khz_xtal();
215 #else
216  cal_ring_osc();
217 #endif
218 
219 #if USE_32KHZ_XTAL
220  *CRM_RTC_TIMEOUT = 32768 * 10;
221 #else
222  *CRM_RTC_TIMEOUT = cal_rtc_secs * 10;
223 #endif
224 
225 #if (USE_WDT == 1)
226  /* set the watchdog timer timeout to 1 sec */
227  cop_timeout_ms(WDT_TIMEOUT);
228  /* enable the watchdog timer */
229  CRM->COP_CNTLbits.COP_EN = 1;
230 #endif
231 
232  /* XXX debug */
233  /* trigger periodic rtc int */
234 // clear_rtc_wu_evt();
235 // enable_rtc_wu();
236 // enable_rtc_wu_irq();
237 }
238 
239 #if RIMEADDR_SIZE == 1
240 const rimeaddr_t addr_ff = { { 0xff } };
241 #else /*RIMEADDR_SIZE == 2*/
242 #if RIMEADDR_SIZE == 2
243 const rimeaddr_t addr_ff = { { 0xff, 0xff } };
244 #else /*RIMEADDR_SIZE == 2*/
245 #if RIMEADDR_SIZE == 8
246 const rimeaddr_t addr_ff = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
247 #endif /*RIMEADDR_SIZE == 8*/
248 #endif /*RIMEADDR_SIZE == 2*/
249 #endif /*RIMEADDR_SIZE == 1*/
250 
251 void iab_to_eui64(rimeaddr_t *eui64, uint32_t oui, uint16_t iab, uint32_t ext) {
252  /* OUI for IABs */
253  eui64->u8[0] = 0x00;
254  eui64->u8[1] = 0x50;
255  eui64->u8[2] = 0xc2;
256 
257  /* IAB */
258  eui64->u8[3] = (iab >> 4) & 0xff;
259  eui64->u8[4] = (iab << 4) & 0xf0;
260 
261  /* EXT */
262 
263  eui64->u8[4] |= (ext >> 24) & 0xf;
264  eui64->u8[5] = (ext >> 16) & 0xff;
265  eui64->u8[6] = (ext >> 8) & 0xff;
266  eui64->u8[7] = ext & 0xff;
267 }
268 
269 void oui_to_eui64(rimeaddr_t *eui64, uint32_t oui, uint64_t ext) {
270  /* OUI */
271  eui64->u8[0] = (oui >> 16) & 0xff;
272  eui64->u8[1] = (oui >> 8) & 0xff;
273  eui64->u8[2] = oui & 0xff;
274 
275  /* EXT */
276  eui64->u8[3] = (ext >> 32) & 0xff;
277  eui64->u8[4] = (ext >> 24) & 0xff;
278  eui64->u8[5] = (ext >> 16) & 0xff;
279  eui64->u8[6] = (ext >> 8) & 0xff;
280  eui64->u8[7] = ext & 0xff;
281 }
282 
283 void
284 set_rimeaddr(rimeaddr_t *addr)
285 {
286  nvmType_t type=0;
287  nvmErr_t err;
288  volatile uint8_t buf[RIMEADDR_NBYTES];
289  rimeaddr_t eui64;
290  int i;
291 
292  err = nvm_detect(gNvmInternalInterface_c, &type);
293 
294  err = nvm_read(gNvmInternalInterface_c, type, (uint8_t *)buf, RIMEADDR_NVM, RIMEADDR_NBYTES);
295 
297 
298  for(i=0; i<RIMEADDR_CONF_SIZE; i++) {
299  addr->u8[i] = buf[i];
300  }
301 
302  if (memcmp(addr, &addr_ff, RIMEADDR_CONF_SIZE)==0) {
303 
304  //set addr to EUI64
305 #ifdef IAB
306  #ifdef EXT_ID
307  PRINTF("address in flash blank, setting to defined IAB and extension.\n\r");
308  iab_to_eui64(&eui64, OUI, IAB, EXT_ID);
309  #else /* ifdef EXT_ID */
310  PRINTF("address in flash blank, setting to defined IAB with a random extension.\n\r");
311  iab_to_eui64(&eui64, OUI, IAB, *MACA_RANDOM);
312  #endif /* ifdef EXT_ID */
313 
314 #else /* ifdef IAB */
315 
316  #ifdef EXT_ID
317  PRINTF("address in flash blank, setting to defined OUI and extension.\n\r");
318  oui_to_eui64(&eui64, OUI, EXT_ID);
319  #else /*ifdef EXT_ID */
320  PRINTF("address in flash blank, setting to defined OUI with a random extension.\n\r");
321  oui_to_eui64(&eui64, OUI, ((*MACA_RANDOM << 32) | *MACA_RANDOM));
322  #endif /*endif EXTID */
323 
324 #endif /* ifdef IAB */
325 
326  rimeaddr_copy(addr, &eui64);
327 #ifdef FLASH_BLANK_ADDR
328  PRINTF("flashing blank address\n\r");
329  err = nvm_write(gNvmInternalInterface_c, type, &(eui64.u8), RIMEADDR_NVM, RIMEADDR_NBYTES);
330 #endif /* ifdef FLASH_BLANK_ADDR */
331  } else {
332  PRINTF("loading rime address from flash.\n\r");
333  }
334 
336 }
337 
338 int
339 main(void)
340 {
341  volatile uint32_t i;
342  rimeaddr_t addr;
343 
344  /* Initialize hardware and */
345  /* go into user mode */
346  init_lowlevel();
347 
348 #if STACKMONITOR
349  /* Simple stack pointer highwater monitor. Checks for magic numbers in the main
350  * loop. In conjuction with PERIODICPRINTS, never-used stack will be printed
351  * every STACKMONITOR seconds.
352  */
353 {
354 extern uint32_t __und_stack_top__, __sys_stack_top__;
355 uint32_t p=(uint32_t)&__und_stack_top__;
356  do {
357  *(uint32_t *)p = 0x42424242;
358  p+=16;
359  } while (p<(uint32_t)&__sys_stack_top__-100); //don't overwrite our own stack
360 }
361 #endif
362 #if HEAPMONITOR
363  /* Simple heap pointer highwater monitor. Checks for magic numbers in the main
364  * loop. In conjuction with PERIODICPRINTS, never-used heap will be printed
365  * every HEAPMONITOR seconds.
366  * This routine assumes a linear FIFO heap as used by the printf _sbrk call.
367  */
368 {
369 extern uint32_t __heap_start__, __heap_end__;
370 uint32_t p=(uint32_t)&__heap_end__-4;
371  do {
372  *(uint32_t *)p = 0x42424242;
373  p-=4;
374  } while (p>=(uint32_t)&__heap_start__);
375 }
376 #endif
377 
378  /* Clock */
379  clock_init();
380 
381  /* LED driver */
382  leds_init();
383 
384  /* control TX_ON with the radio */
385  GPIO->FUNC_SEL.GPIO_44 = 2;
386  GPIO->PAD_DIR.GPIO_44 = 1;
387 
388  /* Process subsystem */
389  process_init();
390  process_start(&etimer_process, NULL);
391  process_start(&contiki_maca_process, NULL);
392 
393  ctimer_init();
394 
395  set_rimeaddr(&addr);
396 
397  printf("Rime started with address ");
398  for(i = 0; i < sizeof(addr.u8) - 1; i++) {
399  printf("%02X:", addr.u8[i]);
400  }
401  printf("%02X\n", addr.u8[i]);
402 
403 
404 #if WITH_UIP6
405  memcpy(&uip_lladdr.addr, &addr.u8, sizeof(uip_lladdr.addr));
406  /* Setup nullmac-like MAC for 802.15.4 */
407 /* sicslowpan_init(sicslowmac_init(&cc2420_driver)); */
408 /* printf(" %s channel %u\n", sicslowmac_driver.name, RF_CHANNEL); */
409 
410  /* Setup X-MAC for 802.15.4 */
411  queuebuf_init();
412  NETSTACK_RDC.init();
413  NETSTACK_MAC.init();
414  NETSTACK_NETWORK.init();
415 
416  printf("%s %s, channel check rate %lu Hz, radio channel %u\n",
417  NETSTACK_MAC.name, NETSTACK_RDC.name,
418  CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1:
419  NETSTACK_RDC.channel_check_interval()),
420  RF_CHANNEL);
421 
422  process_start(&tcpip_process, NULL);
423 
424  printf("Tentative link-local IPv6 address ");
425  {
426  int i, a;
427  for(a = 0; a < UIP_DS6_ADDR_NB; a++) {
428  if (uip_ds6_if.addr_list[a].isused) {
429  for(i = 0; i < 7; ++i) {
430  printf("%02x%02x:",
431  uip_ds6_if.addr_list[a].ipaddr.u8[i * 2],
432  uip_ds6_if.addr_list[a].ipaddr.u8[i * 2 + 1]);
433  }
434  printf("%02x%02x\n",
435  uip_ds6_if.addr_list[a].ipaddr.u8[14],
436  uip_ds6_if.addr_list[a].ipaddr.u8[15]);
437  }
438  }
439  }
440 
441  if(1) {
443  int i;
444  uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
445  uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
446  uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE);
447  printf("Tentative global IPv6 address ");
448  for(i = 0; i < 7; ++i) {
449  printf("%02x%02x:",
450  ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]);
451  }
452  printf("%02x%02x\n",
453  ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]);
454  }
455 
456 
457 #else /* WITH_UIP6 */
458 
459  NETSTACK_RDC.init();
460  NETSTACK_MAC.init();
461  NETSTACK_NETWORK.init();
462 
463  printf("%s %s, channel check rate %lu Hz, radio channel %u\n",
464  NETSTACK_MAC.name, NETSTACK_RDC.name,
465  CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0? 1:
466  NETSTACK_RDC.channel_check_interval()),
467  RF_CHANNEL);
468 #endif /* WITH_UIP6 */
469 
470  *MACA_MACPANID = 0xcdab; /* this is the hardcoded contiki pan, register is PACKET order */
471  *MACA_MAC16ADDR = 0xffff; /* short addressing isn't used, set this to 0xffff for now */
472 
473  *MACA_MAC64HI =
474  addr.u8[0] << 24 |
475  addr.u8[1] << 16 |
476  addr.u8[2] << 8 |
477  addr.u8[3];
478  *MACA_MAC64LO =
479  addr.u8[4] << 24 |
480  addr.u8[5] << 16 |
481  addr.u8[6] << 8 |
482  addr.u8[7];
483  PRINTF("setting panid 0x%04x\n\r", *MACA_MACPANID);
484  PRINTF("setting short mac 0x%04x\n\r", *MACA_MAC16ADDR);
485  PRINTF("setting long mac 0x%08x_%08x\n\r", *MACA_MAC64HI, *MACA_MAC64LO);
486 
487 #if MACA_AUTOACK
488  set_prm_mode(AUTOACK);
489 #endif
490 
491 #if PROFILE_CONF_ON
492  profile_init();
493 #endif /* PROFILE_CONF_ON */
494 
495 #if TIMESYNCH_CONF_ENABLED
496  timesynch_init();
498 #endif /* TIMESYNCH_CONF_ENABLED */
499 
500 #if WITH_UIP
501  process_start(&tcpip_process, NULL);
502  process_start(&uip_fw_process, NULL); /* Start IP output */
503  process_start(&slip_process, NULL);
504 
505  slip_set_input_callback(set_gateway);
506 
507  {
508  uip_ipaddr_t hostaddr, netmask;
509 
510  uip_init();
511 
512  uip_ipaddr(&hostaddr, 172,16,
514  uip_ipaddr(&netmask, 255,255,0,0);
515  uip_ipaddr_copy(&meshif.ipaddr, &hostaddr);
516 
517  uip_sethostaddr(&hostaddr);
518  uip_setnetmask(&netmask);
519  uip_over_mesh_set_net(&hostaddr, &netmask);
520  /* uip_fw_register(&slipif);*/
521  uip_over_mesh_set_gateway_netif(&slipif);
522  uip_fw_default(&meshif);
523  uip_over_mesh_init(UIP_OVER_MESH_CHANNEL);
524  printf("uIP started with IP address %d.%d.%d.%d\n",
525  uip_ipaddr_to_quad(&hostaddr));
526  }
527 #endif /* WITH_UIP */
528 
529  process_start(&sensors_process, NULL);
530 
531  print_processes(autostart_processes);
532  autostart_start(autostart_processes);
533 
534  /* Main scheduler loop */
535  while(1) {
536  check_maca();
537 
538 #if (USE_WDT == 1)
539  cop_service();
540 #endif
541 
542  if(uart1_input_handler != NULL) {
543  if(uart1_can_get()) {
544  uart1_input_handler(uart1_getc());
545  }
546  }
547 
548  process_run();
549 
550 #if PERIODICPRINTS
551 #if TESTRTIMER
552 /* Timeout can be increased up to 8 seconds maximum.
553  * A one second cycle is convenient for triggering the various debug printouts.
554  * The triggers are staggered to avoid printing everything at once.
555  */
556  if (rtimerflag) {
557  rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL);
558  rtimerflag=0;
559 #else
560  if (clocktime!=clock_seconds()) {
561  clocktime=clock_seconds();
562 #endif
563 
564 #if STAMPS
565 if ((clocktime%STAMPS)==0) {
566 #if ENERGEST_CONF_ON
567 #include "lib/print-stats.h"
568  print_stats();
569 #elif RADIOSTATS
570 extern volatile unsigned long radioontime;
571  printf("\r%u(%u)s ",clocktime,radioontime);
572 #else
573  printf("%us\n",clocktime);
574 #endif
575 
576 }
577 #endif
578 #if TESTRTIMER
579  clocktime+=1;
580 #endif
581 
582 #if PINGS && UIP_CONF_IPV6
583 extern void raven_ping6(void);
584 if ((clocktime%PINGS)==1) {
585  printf("**Ping\n");
586  raven_ping6();
587 }
588 #endif
589 
590 #if ROUTES && UIP_CONF_IPV6
591 if ((clocktime%ROUTES)==2) {
592 
595 extern uip_ds6_netif_t uip_ds6_if;
596 
597  uint8_t i,j;
598  printf("\nAddresses [%u max]\n",UIP_DS6_ADDR_NB);
599  for (i=0;i<UIP_DS6_ADDR_NB;i++) {
600  if (uip_ds6_if.addr_list[i].isused) {
601  uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr);
602  printf("\n");
603  }
604  }
605  printf("\nNeighbors [%u max]\n",UIP_DS6_NBR_NB);
606  for(i = 0,j=1; i < UIP_DS6_NBR_NB; i++) {
607  if(uip_ds6_nbr_cache[i].isused) {
608  uip_debug_ipaddr_print(&uip_ds6_nbr_cache[i].ipaddr);
609  printf("\n");
610  j=0;
611  }
612  }
613  if (j) printf(" <none>");
614  printf("\nRoutes [%u max]\n",UIP_DS6_ROUTE_NB);
615  for(i = 0,j=1; i < UIP_DS6_ROUTE_NB; i++) {
616  if(uip_ds6_routing_table[i].isused) {
617  uip_debug_ipaddr_print(&uip_ds6_routing_table[i].ipaddr);
618  printf("/%u (via ", uip_ds6_routing_table[i].length);
619  uip_debug_ipaddr_print(&uip_ds6_routing_table[i].nexthop);
620  // if(uip_ds6_routing_table[i].state.lifetime < 600) {
621  printf(") %lus\n", uip_ds6_routing_table[i].state.lifetime);
622  // } else {
623  // printf(")\n");
624  // }
625  j=0;
626  }
627  }
628  if (j) printf(" <none>");
629  printf("\n---------\n");
630 }
631 #endif
632 
633 #if STACKMONITOR
634 if ((clocktime%STACKMONITOR)==3) {
635 extern uint32_t __und_stack_top__, __sys_stack_top__;
636 uint32_t p=(uint32_t)&__und_stack_top__;
637  do {
638  if (*(uint32_t *)p != 0x42424242) {
639  printf("Never-Used stack > %d bytes\n",p-(uint32_t)&__und_stack_top__);
640  break;
641  }
642  p+=16;
643  } while (p<(uint32_t)&__sys_stack_top__-100);
644 }
645 #endif
646 #if HEAPMONITOR
647 if ((clocktime%HEAPMONITOR)==4) {
648 extern uint32_t __heap_start__, __heap_end__;
649 uint32_t p=(uint32_t)&__heap_end__-4;
650  do {
651  if (*(uint32_t *)p != 0x42424242) {
652  break;
653  }
654  p-=4;
655  } while (p>=(uint32_t)&__heap_start__);
656  printf("Never-used heap >= %d bytes\n",(uint32_t)&__heap_end__-p-4);
657 #if 0
658 #include <stdlib.h>
659 char *ptr=malloc(1); //allocates 16 bytes from the heap
660 printf("********Got pointer %x\n",ptr);
661 #endif
662 }
663 #endif
664 
665  }
666 #endif /* PERIODICPRINTS */
667  }
668 
669  return 0;
670 }
671 
672 /*---------------------------------------------------------------------------*/
673 #if LOG_CONF_ENABLED
674 void
675 log_message(char *m1, char *m2)
676 {
677  printf("%s%s\n", m1, m2);
678 }
679 #endif /* LOG_CONF_ENABLED */