Contiki-Inga 3.x
contiki-cooja-main.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, 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 /**
32  * \file
33  * COOJA Contiki mote main file.
34  * \author
35  * Fredrik Osterlind <fros@sics.se>
36  */
37 
38 #include <jni.h>
39 #include <stdio.h>
40 #include <string.h>
41 
42 #include "contiki.h"
43 
44 #include "sys/clock.h"
45 #include "sys/etimer.h"
46 #include "sys/cooja_mt.h"
47 #include "sys/autostart.h"
48 
49 #include "lib/random.h"
50 #include "lib/simEnvChange.h"
51 
52 #include "net/rime/rime.h"
53 #include "net/netstack.h"
54 
55 #include "dev/serial-line.h"
56 #include "dev/cooja-radio.h"
57 #include "dev/button-sensor.h"
58 #include "dev/pir-sensor.h"
59 #include "dev/vib-sensor.h"
60 
61 #include "sys/node-id.h"
62 
63 
64 /* JNI-defined functions, depends on the environment variable CLASSNAME */
65 #ifndef CLASSNAME
66 #error CLASSNAME is undefined, required by contiki-cooja-main.c
67 #endif /* CLASSNAME */
68 #define COOJA__QUOTEME(a,b,c) COOJA_QUOTEME(a,b,c)
69 #define COOJA_QUOTEME(a,b,c) a##b##c
70 #define COOJA_JNI_PATH Java_org_contikios_cooja_corecomm_
71 #define Java_org_contikios_cooja_corecomm_CLASSNAME_init COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_init)
72 #define Java_org_contikios_cooja_corecomm_CLASSNAME_getMemory COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_getMemory)
73 #define Java_org_contikios_cooja_corecomm_CLASSNAME_setMemory COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_setMemory)
74 #define Java_org_contikios_cooja_corecomm_CLASSNAME_tick COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_tick)
75 #define Java_org_contikios_cooja_corecomm_CLASSNAME_setReferenceAddress COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_setReferenceAddress)
76 
77 #ifndef WITH_UIP
78 #define WITH_UIP 0
79 #endif
80 #if WITH_UIP
81 #include "dev/rs232.h"
82 #include "dev/slip.h"
83 #include "net/ip/uip.h"
84 #include "net/ipv4/uip-fw.h"
85 #include "net/uip-fw-drv.h"
86 #include "net/ipv4/uip-over-mesh.h"
87 static struct uip_fw_netif slipif =
88  {UIP_FW_NETIF(0,0,0,0, 255,255,255,255, slip_send)};
89 static struct uip_fw_netif meshif =
90  {UIP_FW_NETIF(172,16,0,0, 255,255,0,0, uip_over_mesh_send)};
91 
92 #define UIP_OVER_MESH_CHANNEL 8
93 static uint8_t is_gateway;
94 #endif /* WITH_UIP */
95 
96 #ifndef WITH_UIP6
97 #define WITH_UIP6 0
98 #endif
99 #if WITH_UIP6
100 #include "net/ip/uip.h"
101 #include "net/ipv6/uip-ds6.h"
102 #define PRINT6ADDR(addr) printf("%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", ((uint8_t *)addr)[0], ((uint8_t *)addr)[1], ((uint8_t *)addr)[2], ((uint8_t *)addr)[3], ((uint8_t *)addr)[4], ((uint8_t *)addr)[5], ((uint8_t *)addr)[6], ((uint8_t *)addr)[7], ((uint8_t *)addr)[8], ((uint8_t *)addr)[9], ((uint8_t *)addr)[10], ((uint8_t *)addr)[11], ((uint8_t *)addr)[12], ((uint8_t *)addr)[13], ((uint8_t *)addr)[14], ((uint8_t *)addr)[15])
103 #endif /* WITH_UIP6 */
104 
105 /* Simulation mote interfaces */
106 SIM_INTERFACE_NAME(moteid_interface);
107 SIM_INTERFACE_NAME(vib_interface);
108 SIM_INTERFACE_NAME(rs232_interface);
109 SIM_INTERFACE_NAME(simlog_interface);
110 SIM_INTERFACE_NAME(beep_interface);
111 SIM_INTERFACE_NAME(radio_interface);
112 SIM_INTERFACE_NAME(button_interface);
113 SIM_INTERFACE_NAME(pir_interface);
114 SIM_INTERFACE_NAME(clock_interface);
115 SIM_INTERFACE_NAME(leds_interface);
116 SIM_INTERFACE_NAME(cfs_interface);
117 SIM_INTERFACES(&vib_interface, &moteid_interface, &rs232_interface, &simlog_interface, &beep_interface, &radio_interface, &button_interface, &pir_interface, &clock_interface, &leds_interface, &cfs_interface);
118 /* Example: manually add mote interfaces */
119 //SIM_INTERFACE_NAME(dummy_interface);
120 //SIM_INTERFACES(..., &dummy_interface);
121 
122 /* Sensors */
123 SENSORS(&button_sensor, &pir_sensor, &vib_sensor);
124 
125 /*
126  * referenceVar is used for comparing absolute and process relative memory.
127  * (this must not be static due to memory locations)
128  */
129 long referenceVar;
130 
131 /*
132  * Contiki and rtimer threads.
133  */
134 static struct cooja_mt_thread rtimer_thread;
135 static struct cooja_mt_thread process_run_thread;
136 
137 #define MIN(a, b) ( (a)<(b) ? (a) : (b) )
138 
139 /*---------------------------------------------------------------------------*/
140 #if WITH_UIP
141 static void
142 set_gateway(void)
143 {
144  if(!is_gateway) {
145  printf("%d.%d: making myself the IP network gateway.\n\n",
147  printf("IPv4 address of the gateway: %d.%d.%d.%d\n\n",
148  uip_ipaddr_to_quad(&uip_hostaddr));
149  uip_over_mesh_set_gateway(&linkaddr_node_addr);
150  uip_over_mesh_make_announced_gateway();
151  is_gateway = 1;
152  }
153 }
154 #endif /* WITH_UIP */
155 /*---------------------------------------------------------------------------*/
156 static void
157 print_processes(struct process * const processes[])
158 {
159  /* const struct process * const * p = processes;*/
160  printf("Starting");
161  while(*processes != NULL) {
162  printf(" '%s'", (*processes)->name);
163  processes++;
164  }
165  putchar('\n');
166 }
167 /*---------------------------------------------------------------------------*/
168 static void
169 rtimer_thread_loop(void *data)
170 {
171  while(1)
172  {
173  rtimer_arch_check();
174 
175  /* Return to COOJA */
176  cooja_mt_yield();
177  }
178 }
179 /*---------------------------------------------------------------------------*/
180 static void
181 set_rime_addr(void)
182 {
183  linkaddr_t addr;
184  int i;
185 
186  memset(&addr, 0, sizeof(linkaddr_t));
187 #if WITH_UIP6
188  for(i = 0; i < sizeof(uip_lladdr.addr); i += 2) {
189  addr.u8[i + 1] = node_id & 0xff;
190  addr.u8[i + 0] = node_id >> 8;
191  }
192 #else /* WITH_UIP6 */
193  addr.u8[0] = node_id & 0xff;
194  addr.u8[1] = node_id >> 8;
195 #endif /* WITH_UIP6 */
196  linkaddr_set_node_addr(&addr);
197  printf("Rime started with address ");
198  for(i = 0; i < sizeof(addr.u8) - 1; i++) {
199  printf("%d.", addr.u8[i]);
200  }
201  printf("%d\n", addr.u8[i]);
202 }
203 /*---------------------------------------------------------------------------*/
204 void
205 contiki_init()
206 {
207  /* Initialize random generator (moved to moteid.c) */
208 
209  /* Start process handler */
210  process_init();
211 
212 
213  /* Start Contiki processes */
214 
215  process_start(&etimer_process, NULL);
216  process_start(&sensors_process, NULL);
217  ctimer_init();
218 
219  /* Print startup information */
220  printf(CONTIKI_VERSION_STRING " started. ");
221  if(node_id > 0) {
222  printf("Node id is set to %u.\n", node_id);
223  } else {
224  printf("Node id is not set.\n");
225  }
226 
227  set_rime_addr();
228  {
229  uint8_t longaddr[8];
230  uint16_t shortaddr;
231 
232  shortaddr = (linkaddr_node_addr.u8[0] << 8) +
233  linkaddr_node_addr.u8[1];
234  memset(longaddr, 0, sizeof(longaddr));
235  linkaddr_copy((linkaddr_t *)&longaddr, &linkaddr_node_addr);
236  printf("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ",
237  longaddr[0], longaddr[1], longaddr[2], longaddr[3],
238  longaddr[4], longaddr[5], longaddr[6], longaddr[7]);
239  }
240 
241  queuebuf_init();
242 
243  /* Initialize communication stack */
244  netstack_init();
245  printf("%s/%s/%s, channel check rate %lu Hz\n",
246  NETSTACK_NETWORK.name, NETSTACK_MAC.name, NETSTACK_RDC.name,
247  CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1:
248  NETSTACK_RDC.channel_check_interval()));
249 
250 #if WITH_UIP
251  /* IPv4 CONFIGURATION */
252  {
253  uip_ipaddr_t hostaddr, netmask;
254 
255  process_start(&tcpip_process, NULL);
256  process_start(&uip_fw_process, NULL);
257  process_start(&slip_process, NULL);
258 
259  slip_set_input_callback(set_gateway);
260 
261  uip_init();
262  uip_fw_init();
263  uip_ipaddr(&hostaddr, 172,16,linkaddr_node_addr.u8[0],linkaddr_node_addr.u8[1]);
264  uip_ipaddr(&netmask, 255,255,0,0);
265  uip_ipaddr_copy(&meshif.ipaddr, &hostaddr);
266 
267  uip_sethostaddr(&hostaddr);
268  uip_setnetmask(&netmask);
269  uip_over_mesh_set_net(&hostaddr, &netmask);
270  uip_over_mesh_set_gateway_netif(&slipif);
271  uip_fw_default(&meshif);
272  uip_over_mesh_init(UIP_OVER_MESH_CHANNEL);
273 
274  rs232_set_input(slip_input_byte);
275  printf("IPv4 address: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&hostaddr));
276  }
277 #endif /* WITH_UIP */
278 
279 #if WITH_UIP6
280  /* IPv6 CONFIGURATION */
281  {
282  int i;
283  uint8_t addr[sizeof(uip_lladdr.addr)];
284  for(i = 0; i < sizeof(uip_lladdr.addr); i += 2) {
285  addr[i + 1] = node_id & 0xff;
286  addr[i + 0] = node_id >> 8;
287  }
289  memcpy(&uip_lladdr.addr, addr, sizeof(uip_lladdr.addr));
290 
291  process_start(&tcpip_process, NULL);
292 
293  printf("Tentative link-local IPv6 address ");
294  {
295  uip_ds6_addr_t *lladdr;
296  int i;
297  lladdr = uip_ds6_get_link_local(-1);
298  for(i = 0; i < 7; ++i) {
299  printf("%02x%02x:", lladdr->ipaddr.u8[i * 2],
300  lladdr->ipaddr.u8[i * 2 + 1]);
301  }
302  printf("%02x%02x\n", lladdr->ipaddr.u8[14],
303  lladdr->ipaddr.u8[15]);
304  }
305 
306  if(1) {
307  uip_ipaddr_t ipaddr;
308  int i;
309  uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
310  uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
311  uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE);
312  printf("Tentative global IPv6 address ");
313  for(i = 0; i < 7; ++i) {
314  printf("%02x%02x:",
315  ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]);
316  }
317  printf("%02x%02x\n",
318  ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]);
319  }
320  }
321 #endif /* WITH_UIP6 */
322 
323  /* Start serial process */
324  serial_line_init();
325 
326  /* Start autostart processes (defined in Contiki application) */
327  print_processes(autostart_processes);
328  autostart_start(autostart_processes);
329 }
330 /*---------------------------------------------------------------------------*/
331 static void
332 process_run_thread_loop(void *data)
333 {
334  /* Yield once during bootup */
335  simProcessRunValue = 1;
336  cooja_mt_yield();
337 
338  contiki_init();
339 
340  while(1)
341  {
342  simProcessRunValue = process_run();
343  while(simProcessRunValue-- > 0) {
344  process_run();
345  }
346  simProcessRunValue = process_nevents();
347 
348  /* Check if we must stay awake */
349  if(simDontFallAsleep) {
350  simDontFallAsleep=0;
351  simProcessRunValue = 1;
352  }
353 
354  /* Return to COOJA */
355  cooja_mt_yield();
356  }
357 }
358 /*---------------------------------------------------------------------------*/
359 /**
360  * \brief Initialize a mote by starting processes etc.
361  *
362  * This function initializes a mote by starting certain
363  * processes and setting up the environment.
364  *
365  * This is a JNI function and should only be called via the
366  * responsible Java part (MoteType.java).
367  */
368 JNIEXPORT void JNICALL
370 {
371  /* Create rtimers and Contiki threads */
372  cooja_mt_start(&rtimer_thread, &rtimer_thread_loop, NULL);
373  cooja_mt_start(&process_run_thread, &process_run_thread_loop, NULL);
374  }
375 /*---------------------------------------------------------------------------*/
376 /**
377  * \brief Get a segment from the process memory.
378  * \param start Start address of segment
379  * \param length Size of memory segment
380  * \return Java byte array containing a copy of memory segment.
381  *
382  * Fetches a memory segment from the process memory starting at
383  * (start), with size (length). This function does not perform
384  * ANY error checking, and the process may crash if addresses are
385  * not available/readable.
386  *
387  * This is a JNI function and should only be called via the
388  * responsible Java part (MoteType.java).
389  */
390 JNIEXPORT void JNICALL
391 Java_org_contikios_cooja_corecomm_CLASSNAME_getMemory(JNIEnv *env, jobject obj, jint rel_addr, jint length, jbyteArray mem_arr)
392 {
393  (*env)->SetByteArrayRegion(
394  env,
395  mem_arr,
396  0,
397  (size_t) length,
398  (jbyte *) (((long)rel_addr) + referenceVar)
399  );
400 }
401 /*---------------------------------------------------------------------------*/
402 /**
403  * \brief Replace a segment of the process memory with given byte array.
404  * \param start Start address of segment
405  * \param length Size of memory segment
406  * \param mem_arr Byte array contaning new memory
407  *
408  * Replaces a process memory segment with given byte array.
409  * This function does not perform ANY error checking, and the
410  * process may crash if addresses are not available/writable.
411  *
412  * This is a JNI function and should only be called via the
413  * responsible Java part (MoteType.java).
414  */
415 JNIEXPORT void JNICALL
416 Java_org_contikios_cooja_corecomm_CLASSNAME_setMemory(JNIEnv *env, jobject obj, jint rel_addr, jint length, jbyteArray mem_arr)
417 {
418  jbyte *mem = (*env)->GetByteArrayElements(env, mem_arr, 0);
419  memcpy(
420  (char*) (((long)rel_addr) + referenceVar),
421  mem,
422  length);
423  (*env)->ReleaseByteArrayElements(env, mem_arr, mem, 0);
424 }
425 /*---------------------------------------------------------------------------*/
426 /**
427  * \brief Let mote execute one "block" of code (tick mote).
428  *
429  * Let mote defined by the active contiki processes and current
430  * process memory execute some program code. This code must not block
431  * or else this function will never return. A typical contiki
432  * process will return when it executes PROCESS_WAIT..() statements.
433  *
434  * Before the control is left to contiki processes, any messages
435  * from the Java part are handled. These may for example be
436  * incoming network data. After the contiki processes return control,
437  * messages to the Java part are also handled (those which may need
438  * special attention).
439  *
440  * This is a JNI function and should only be called via the
441  * responsible Java part (MoteType.java).
442  */
443 JNIEXPORT void JNICALL
445 {
446  clock_time_t nextEtimer;
447  rtimer_clock_t nextRtimer;
448 
449  simProcessRunValue = 0;
450 
451  /* Let all simulation interfaces act first */
452  doActionsBeforeTick();
453 
454  /* Poll etimer process */
455  if (etimer_pending()) {
457  }
458 
459  /* Let rtimers run.
460  * Sets simProcessRunValue */
461  cooja_mt_exec(&rtimer_thread);
462 
463  if(simProcessRunValue == 0) {
464  /* Rtimers done: Let Contiki handle a few events.
465  * Sets simProcessRunValue */
466  cooja_mt_exec(&process_run_thread);
467  }
468 
469  /* Let all simulation interfaces act before returning to java */
470  doActionsAfterTick();
471 
472  /* Do we have any pending timers */
473  simEtimerPending = etimer_pending() || rtimer_arch_pending();
474  if(!simEtimerPending) {
475  return;
476  }
477 
478  /* Save nearest expiration time */
479  nextEtimer = etimer_next_expiration_time() - (clock_time_t) simCurrentTime;
480  nextRtimer = rtimer_arch_next() - (rtimer_clock_t) simCurrentTime;
481  if(etimer_pending() && rtimer_arch_pending()) {
482  simNextExpirationTime = MIN(nextEtimer, nextRtimer);
483  } else if (etimer_pending()) {
484  simNextExpirationTime = nextEtimer;
485  } else if (rtimer_arch_pending()) {
486  simNextExpirationTime = nextRtimer;
487  }
488 }
489 /*---------------------------------------------------------------------------*/
490 /**
491  * \brief Set the relative memory address of the reference variable.
492  * \return Relative memory address.
493  *
494  * This is a JNI function and should only be called via the
495  * responsible Java part (MoteType.java).
496  */
497 JNIEXPORT void JNICALL
499 {
500  referenceVar = (((long)&referenceVar) - ((long)addr));
501 }