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