Contiki-Inga 3.x
contiki-z1-main.c
1 /*
2  * Copyright (c) 2006, Swedish Institute of Computer Science
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
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30 
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdarg.h>
34 
35 #include "contiki.h"
36 #include "cc2420.h"
37 #include "dev/leds.h"
38 #include "dev/serial-line.h"
39 #include "dev/slip.h"
40 #include "dev/uart0.h"
41 #include "dev/watchdog.h"
42 #include "dev/xmem.h"
43 #include "lib/random.h"
44 #include "net/netstack.h"
45 #include "net/mac/frame802154.h"
46 #include "dev/button-sensor.h"
47 #include "dev/adxl345.h"
48 #include "sys/clock.h"
49 
50 #if WITH_UIP6
51 #include "net/ipv6/uip-ds6.h"
52 #endif /* WITH_UIP6 */
53 
54 #include "net/rime/rime.h"
55 
56 #include "sys/node-id.h"
57 #include "cfs-coffee-arch.h"
58 #include "cfs/cfs-coffee.h"
59 #include "sys/autostart.h"
60 
61 #include "dev/battery-sensor.h"
62 #include "dev/button-sensor.h"
63 #include "dev/sht11/sht11-sensor.h"
64 
65 SENSORS(&button_sensor);
66 
67 extern unsigned char node_mac[8];
68 
69 #if DCOSYNCH_CONF_ENABLED
70 static struct timer mgt_timer;
71 #endif
72 
73 #ifndef WITH_UIP
74 #define WITH_UIP 0
75 #endif
76 
77 #if WITH_UIP
78 #include "net/ip/uip.h"
79 #include "net/ipv4/uip-fw.h"
80 #include "net/uip-fw-drv.h"
81 #include "net/ipv4/uip-over-mesh.h"
82 static struct uip_fw_netif slipif =
83  {UIP_FW_NETIF(192,168,1,2, 255,255,255,255, slip_send)};
84 static struct uip_fw_netif meshif =
85  {UIP_FW_NETIF(172,16,0,0, 255,255,0,0, uip_over_mesh_send)};
86 
87 #endif /* WITH_UIP */
88 
89 #define UIP_OVER_MESH_CHANNEL 8
90 #if WITH_UIP
91 static uint8_t is_gateway;
92 #endif /* WITH_UIP */
93 
94 #ifdef EXPERIMENT_SETUP
95 #include "experiment-setup.h"
96 #endif
97 
98 #define DEBUG 1
99 #if DEBUG
100 #include <stdio.h>
101 #define PRINTF(...) printf(__VA_ARGS__)
102 #else
103 #define PRINTF(...)
104 #endif
105 
106 void init_platform(void);
107 
108 /*---------------------------------------------------------------------------*/
109 #if 0
110 int
111 force_float_inclusion()
112 {
113  extern int __fixsfsi;
114  extern int __floatsisf;
115  extern int __mulsf3;
116  extern int __subsf3;
117 
118  return __fixsfsi + __floatsisf + __mulsf3 + __subsf3;
119 }
120 #endif
121 /*---------------------------------------------------------------------------*/
122 void uip_log(char *msg) { puts(msg); }
123 /*---------------------------------------------------------------------------*/
124 #if 0
125 void
126 force_inclusion(int d1, int d2)
127 {
128  snprintf(NULL, 0, "%d", d1 % d2);
129 }
130 #endif
131 /*---------------------------------------------------------------------------*/
132 static void
133 set_rime_addr(void)
134 {
135  linkaddr_t addr;
136  int i;
137 
138  memset(&addr, 0, sizeof(linkaddr_t));
139 #if UIP_CONF_IPV6
140  memcpy(addr.u8, node_mac, sizeof(addr.u8));
141 #else
142  if(node_id == 0) {
143  for(i = 0; i < sizeof(linkaddr_t); ++i) {
144  addr.u8[i] = node_mac[7 - i];
145  }
146  } else {
147  addr.u8[0] = node_id & 0xff;
148  addr.u8[1] = node_id >> 8;
149  }
150 #endif
151  linkaddr_set_node_addr(&addr);
152  printf("Rime started with address ");
153  for(i = 0; i < sizeof(addr.u8) - 1; i++) {
154  printf("%d.", addr.u8[i]);
155  }
156  printf("%d\n", addr.u8[i]);
157 }
158 /*---------------------------------------------------------------------------*/
159 static void
160 print_processes(struct process * const processes[])
161 {
162  /* const struct process * const * p = processes;*/
163  printf("Starting");
164  while(*processes != NULL) {
165  printf(" '%s'", (*processes)->name);
166  processes++;
167  }
168  putchar('\n');
169 }
170 /*--------------------------------------------------------------------------*/
171 #if WITH_UIP
172 static void
173 set_gateway(void)
174 {
175  if(!is_gateway) {
176  leds_on(LEDS_RED);
177  printf("%d.%d: making myself the IP network gateway.\n\n",
179  printf("IPv4 address of the gateway: %d.%d.%d.%d\n\n",
180  uip_ipaddr_to_quad(&uip_hostaddr));
181  uip_over_mesh_set_gateway(&linkaddr_node_addr);
182  uip_over_mesh_make_announced_gateway();
183  is_gateway = 1;
184  }
185 }
186 #endif /* WITH_UIP */
187 /*---------------------------------------------------------------------------*/
188 int
189 main(int argc, char **argv)
190 {
191  /*
192  * Initalize hardware.
193  */
194  msp430_cpu_init();
195  clock_init();
196  leds_init();
197  leds_on(LEDS_RED);
198 
199  clock_wait(100);
200 
201  uart0_init(BAUD2UBR(115200)); /* Must come before first printf */
202 #if WITH_UIP
203  slip_arch_init(BAUD2UBR(115200));
204 #endif /* WITH_UIP */
205 
206  xmem_init();
207 
208  rtimer_init();
209  /*
210  * Hardware initialization done!
211  */
212 
213  /* Restore node id if such has been stored in external mem */
214  node_id_restore();
215 
216  /* If no MAC address was burned, we use the node ID. */
217  if(!(node_mac[0] | node_mac[1] | node_mac[2] | node_mac[3] |
218  node_mac[4] | node_mac[5] | node_mac[6] | node_mac[7])) {
219  node_mac[0] = 0xc1; /* Hardcoded for Z1 */
220  node_mac[1] = 0x0c; /* Hardcoded for Revision C */
221  node_mac[2] = 0x00; /* Hardcoded to arbitrary even number so that
222  the 802.15.4 MAC address is compatible with
223  an Ethernet MAC address - byte 0 (byte 2 in
224  the DS ID) */
225  node_mac[3] = 0x00; /* Hardcoded */
226  node_mac[4] = 0x00; /* Hardcoded */
227  node_mac[5] = 0x00; /* Hardcoded */
228  node_mac[6] = node_id >> 8;
229  node_mac[7] = node_id & 0xff;
230  }
231 
232  /* Overwrite node MAC if desired at compile time */
233 #ifdef MACID
234  #warning "***** CHANGING DEFAULT MAC *****"
235  node_mac[0] = 0xc1; /* Hardcoded for Z1 */
236  node_mac[1] = 0x0c; /* Hardcoded for Revision C */
237  node_mac[2] = 0x00; /* Hardcoded to arbitrary even number so that
238  the 802.15.4 MAC address is compatible with
239  an Ethernet MAC address - byte 0 (byte 2 in
240  the DS ID) */
241  node_mac[3] = 0x00; /* Hardcoded */
242  node_mac[4] = 0x00; /* Hardcoded */
243  node_mac[5] = 0x00; /* Hardcoded */
244  node_mac[6] = MACID >> 8;
245  node_mac[7] = MACID & 0xff;
246 #endif
247 
248 #ifdef IEEE_802154_MAC_ADDRESS
249  /* for setting "hardcoded" IEEE 802.15.4 MAC addresses */
250  {
251  uint8_t ieee[] = IEEE_802154_MAC_ADDRESS;
252  memcpy(node_mac, ieee, sizeof(uip_lladdr.addr));
253  node_mac[7] = node_id & 0xff;
254  }
255 #endif /* IEEE_802154_MAC_ADDRESS */
256 
257  /*
258  * Initialize Contiki and our processes.
259  */
260  process_init();
261  process_start(&etimer_process, NULL);
262 
263  ctimer_init();
264 
265  init_platform();
266 
267  set_rime_addr();
268 
269  cc2420_init();
270  accm_init();
271 
272  {
273  uint8_t longaddr[8];
274  uint16_t shortaddr;
275 
276  shortaddr = (linkaddr_node_addr.u8[0] << 8) +
277  linkaddr_node_addr.u8[1];
278  memset(longaddr, 0, sizeof(longaddr));
279  linkaddr_copy((linkaddr_t *)&longaddr, &linkaddr_node_addr);
280  printf("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ",
281  longaddr[0], longaddr[1], longaddr[2], longaddr[3],
282  longaddr[4], longaddr[5], longaddr[6], longaddr[7]);
283 
284  cc2420_set_pan_addr(IEEE802154_PANID, shortaddr, longaddr);
285  }
286 
287  leds_off(LEDS_ALL);
288 
289  PRINTF(CONTIKI_VERSION_STRING " started. ");
290 
291  if(node_id > 0) {
292  PRINTF("Node id is set to %u.\n", node_id);
293  } else {
294  PRINTF("Node id is not set.\n");
295  }
296 
297 
298 #if WITH_UIP6
299  memcpy(&uip_lladdr.addr, node_mac, sizeof(uip_lladdr.addr));
300  /* Setup nullmac-like MAC for 802.15.4 */
301 /* sicslowpan_init(sicslowmac_init(&cc2420_driver)); */
302 /* printf(" %s channel %u\n", sicslowmac_driver.name, CC2420_CONF_CHANNEL); */
303 
304  /* Setup X-MAC for 802.15.4 */
305  queuebuf_init();
306 
307  NETSTACK_RDC.init();
308  NETSTACK_MAC.init();
309  NETSTACK_NETWORK.init();
310 
311  printf("%s %s, channel check rate %lu Hz, radio channel %u\n",
312  NETSTACK_MAC.name, NETSTACK_RDC.name,
313  CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1:
314  NETSTACK_RDC.channel_check_interval()),
315  CC2420_CONF_CHANNEL);
316 
317  process_start(&tcpip_process, NULL);
318 
319  printf("Tentative link-local IPv6 address ");
320  {
321  uip_ds6_addr_t *lladdr;
322  int i;
323  lladdr = uip_ds6_get_link_local(-1);
324  for(i = 0; i < 7; ++i) {
325  printf("%02x%02x:", lladdr->ipaddr.u8[i * 2],
326  lladdr->ipaddr.u8[i * 2 + 1]);
327  }
328  printf("%02x%02x\n", lladdr->ipaddr.u8[14], lladdr->ipaddr.u8[15]);
329  }
330 
331  if(!UIP_CONF_IPV6_RPL) {
332  uip_ipaddr_t ipaddr;
333  int i;
334  uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
335  uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
336  uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE);
337  printf("Tentative global IPv6 address ");
338  for(i = 0; i < 7; ++i) {
339  printf("%02x%02x:",
340  ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]);
341  }
342  printf("%02x%02x\n",
343  ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]);
344  }
345 
346 #else /* WITH_UIP6 */
347 
348  NETSTACK_RDC.init();
349  NETSTACK_MAC.init();
350  NETSTACK_NETWORK.init();
351 
352  printf("%s %s, channel check rate %lu Hz, radio channel %u\n",
353  NETSTACK_MAC.name, NETSTACK_RDC.name,
354  CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0? 1:
355  NETSTACK_RDC.channel_check_interval()),
356  CC2420_CONF_CHANNEL);
357 #endif /* WITH_UIP6 */
358 
359 #if !WITH_UIP && !WITH_UIP6
360  uart0_set_input(serial_line_input_byte);
361  serial_line_init();
362 #endif
363 
364  leds_off(LEDS_GREEN);
365 
366 #if TIMESYNCH_CONF_ENABLED
367  timesynch_init();
369 #endif /* TIMESYNCH_CONF_ENABLED */
370 
371 #if WITH_UIP
372  process_start(&tcpip_process, NULL);
373  process_start(&uip_fw_process, NULL); /* Start IP output */
374  process_start(&slip_process, NULL);
375 
376  slip_set_input_callback(set_gateway);
377 
378  {
379  uip_ipaddr_t hostaddr, netmask;
380 
381  uip_init();
382 
383  uip_ipaddr(&hostaddr, 172,16,
385  uip_ipaddr(&netmask, 255,255,0,0);
386  uip_ipaddr_copy(&meshif.ipaddr, &hostaddr);
387 
388  uip_sethostaddr(&hostaddr);
389  uip_setnetmask(&netmask);
390  uip_over_mesh_set_net(&hostaddr, &netmask);
391  /* uip_fw_register(&slipif);*/
392  uip_over_mesh_set_gateway_netif(&slipif);
393  uip_fw_default(&meshif);
394  uip_over_mesh_init(UIP_OVER_MESH_CHANNEL);
395  printf("uIP started with IP address %d.%d.%d.%d\n",
396  uip_ipaddr_to_quad(&hostaddr));
397  }
398 #endif /* WITH_UIP */
399 
400  energest_init();
401  ENERGEST_ON(ENERGEST_TYPE_CPU);
402 
403  print_processes(autostart_processes);
404  autostart_start(autostart_processes);
405 
406  /*
407  * This is the scheduler loop.
408  */
409 #if DCOSYNCH_CONF_ENABLED
410  timer_set(&mgt_timer, DCOSYNCH_PERIOD * CLOCK_SECOND);
411 #endif
412  watchdog_start();
413  /* watchdog_stop();*/
414  while(1) {
415  int r;
416  do {
417  /* Reset watchdog. */
419  r = process_run();
420  } while(r > 0);
421 
422  /*
423  * Idle processing.
424  */
425  int s = splhigh(); /* Disable interrupts. */
426  /* uart0_active is for avoiding LPM3 when still sending or receiving */
427  if(process_nevents() != 0 || uart0_active()) {
428  splx(s); /* Re-enable interrupts. */
429  } else {
430  static unsigned long irq_energest = 0;
431 
432 #if DCOSYNCH_CONF_ENABLED
433  /* before going down to sleep possibly do some management */
434  if (timer_expired(&mgt_timer)) {
435  timer_reset(&mgt_timer);
436  msp430_sync_dco();
437  }
438 #endif
439 
440  /* Re-enable interrupts and go to sleep atomically. */
441  ENERGEST_OFF(ENERGEST_TYPE_CPU);
442  ENERGEST_ON(ENERGEST_TYPE_LPM);
443  /* We only want to measure the processing done in IRQs when we
444  are asleep, so we discard the processing time done when we
445  were awake. */
446  energest_type_set(ENERGEST_TYPE_IRQ, irq_energest);
447  watchdog_stop();
448  _BIS_SR(GIE | SCG0 | SCG1 | CPUOFF); /* LPM3 sleep. This
449  statement will block
450  until the CPU is
451  woken up by an
452  interrupt that sets
453  the wake up flag. */
454 
455  /* We get the current processing time for interrupts that was
456  done during the LPM and store it for next time around. */
457  dint();
458  irq_energest = energest_type_time(ENERGEST_TYPE_IRQ);
459  eint();
460  watchdog_start();
461  ENERGEST_OFF(ENERGEST_TYPE_LPM);
462  ENERGEST_ON(ENERGEST_TYPE_CPU);
463  }
464  }
465 
466  return 0;
467 }
468 /*---------------------------------------------------------------------------*/
469 #if LOG_CONF_ENABLED
470 void
471 log_message(char *m1, char *m2)
472 {
473  printf("%s%s\n", m1, m2);
474 }
475 #endif /* LOG_CONF_ENABLED */
476