Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2010, Swedish Institute of Computer Science. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * $Id: contiki-cooja-main.c,v 1.9 2010/09/24 12:59:06 fros4943 Exp $ 00030 */ 00031 00032 /** 00033 * \file 00034 * COOJA Contiki mote main file. 00035 * \author 00036 * Fredrik Osterlind <fros@sics.se> 00037 */ 00038 00039 #include <jni.h> 00040 #include <stdio.h> 00041 #include <string.h> 00042 00043 #include "contiki.h" 00044 00045 #include "sys/clock.h" 00046 #include "sys/etimer.h" 00047 #include "sys/cooja_mt.h" 00048 #include "sys/autostart.h" 00049 00050 #include "lib/random.h" 00051 #include "lib/simEnvChange.h" 00052 00053 #include "net/rime.h" 00054 #include "net/netstack.h" 00055 00056 #include "dev/serial-line.h" 00057 #include "dev/cooja-radio.h" 00058 #include "dev/button-sensor.h" 00059 #include "dev/pir-sensor.h" 00060 #include "dev/vib-sensor.h" 00061 00062 #include "node-id.h" 00063 00064 00065 /* JNI-defined functions, depends on the environment variable CLASSNAME */ 00066 #ifndef CLASSNAME 00067 #error CLASSNAME is undefined, required by contiki-cooja-main.c 00068 #endif /* CLASSNAME */ 00069 #define COOJA__QUOTEME(a,b,c) COOJA_QUOTEME(a,b,c) 00070 #define COOJA_QUOTEME(a,b,c) a##b##c 00071 #define COOJA_JNI_PATH Java_se_sics_cooja_corecomm_ 00072 #define Java_se_sics_cooja_corecomm_CLASSNAME_init COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_init) 00073 #define Java_se_sics_cooja_corecomm_CLASSNAME_getMemory COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_getMemory) 00074 #define Java_se_sics_cooja_corecomm_CLASSNAME_setMemory COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_setMemory) 00075 #define Java_se_sics_cooja_corecomm_CLASSNAME_tick COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_tick) 00076 #define Java_se_sics_cooja_corecomm_CLASSNAME_setReferenceAddress COOJA__QUOTEME(COOJA_JNI_PATH,CLASSNAME,_setReferenceAddress) 00077 00078 #ifndef WITH_UIP 00079 #define WITH_UIP 0 00080 #endif 00081 #if WITH_UIP 00082 #include "dev/rs232.h" 00083 #include "dev/slip.h" 00084 #include "net/uip.h" 00085 #include "net/uip-fw.h" 00086 #include "net/uip-fw-drv.h" 00087 #include "net/uip-over-mesh.h" 00088 static struct uip_fw_netif slipif = 00089 {UIP_FW_NETIF(0,0,0,0, 255,255,255,255, slip_send)}; 00090 static struct uip_fw_netif meshif = 00091 {UIP_FW_NETIF(172,16,0,0, 255,255,0,0, uip_over_mesh_send)}; 00092 00093 #define UIP_OVER_MESH_CHANNEL 8 00094 static uint8_t is_gateway; 00095 #endif /* WITH_UIP */ 00096 00097 #ifndef WITH_UIP6 00098 #define WITH_UIP6 0 00099 #endif 00100 #if WITH_UIP6 00101 #include "net/uip.h" 00102 #include "net/uip-ds6.h" 00103 #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]) 00104 #endif /* WITH_UIP6 */ 00105 00106 PROCINIT(&etimer_process,&sensors_process); 00107 00108 /* Simulation mote interfaces */ 00109 SIM_INTERFACE_NAME(moteid_interface); 00110 SIM_INTERFACE_NAME(vib_interface); 00111 SIM_INTERFACE_NAME(rs232_interface); 00112 SIM_INTERFACE_NAME(simlog_interface); 00113 SIM_INTERFACE_NAME(beep_interface); 00114 SIM_INTERFACE_NAME(radio_interface); 00115 SIM_INTERFACE_NAME(button_interface); 00116 SIM_INTERFACE_NAME(pir_interface); 00117 SIM_INTERFACE_NAME(clock_interface); 00118 SIM_INTERFACE_NAME(leds_interface); 00119 SIM_INTERFACE_NAME(cfs_interface); 00120 SIM_INTERFACES(&vib_interface, &moteid_interface, &rs232_interface, &simlog_interface, &beep_interface, &radio_interface, &button_interface, &pir_interface, &clock_interface, &leds_interface, &cfs_interface); 00121 /* Example: manually add mote interfaces */ 00122 //SIM_INTERFACE_NAME(dummy_interface); 00123 //SIM_INTERFACES(..., &dummy_interface); 00124 00125 /* Sensors */ 00126 SENSORS(&button_sensor, &pir_sensor, &vib_sensor); 00127 00128 /* 00129 * referenceVar is used for comparing absolute and process relative memory. 00130 * (this must not be static due to memory locations) 00131 */ 00132 long referenceVar; 00133 00134 /* 00135 * Contiki and rtimer threads. 00136 */ 00137 static struct cooja_mt_thread rtimer_thread; 00138 static struct cooja_mt_thread process_run_thread; 00139 00140 #define MIN(a, b) ( (a)<(b) ? (a) : (b) ) 00141 00142 /*---------------------------------------------------------------------------*/ 00143 #if WITH_UIP 00144 static void 00145 set_gateway(void) 00146 { 00147 if(!is_gateway) { 00148 printf("%d.%d: making myself the IP network gateway.\n\n", 00149 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); 00150 printf("IPv4 address of the gateway: %d.%d.%d.%d\n\n", 00151 uip_ipaddr_to_quad(&uip_hostaddr)); 00152 uip_over_mesh_set_gateway(&rimeaddr_node_addr); 00153 uip_over_mesh_make_announced_gateway(); 00154 is_gateway = 1; 00155 } 00156 } 00157 #endif /* WITH_UIP */ 00158 /*---------------------------------------------------------------------------*/ 00159 static void 00160 print_processes(struct process * const processes[]) 00161 { 00162 /* const struct process * const * p = processes;*/ 00163 printf("Starting"); 00164 while(*processes != NULL) { 00165 printf(" '%s'", (*processes)->name); 00166 processes++; 00167 } 00168 putchar('\n'); 00169 } 00170 /*---------------------------------------------------------------------------*/ 00171 static void 00172 rtimer_thread_loop(void *data) 00173 { 00174 while(1) 00175 { 00176 rtimer_arch_check(); 00177 00178 /* Return to COOJA */ 00179 cooja_mt_yield(); 00180 } 00181 } 00182 /*---------------------------------------------------------------------------*/ 00183 void 00184 contiki_init() 00185 { 00186 /* Initialize random generator (moved to moteid.c) */ 00187 00188 /* Start process handler */ 00189 process_init(); 00190 00191 /* Start Contiki processes */ 00192 procinit_init(); 00193 00194 /* Print startup information */ 00195 printf(CONTIKI_VERSION_STRING " started. "); 00196 if(node_id > 0) { 00197 printf("Node id is set to %u.\n", node_id); 00198 } else { 00199 printf("Node id is not set.\n"); 00200 } 00201 00202 /* RIME CONFIGURATION */ 00203 { 00204 int i; 00205 rimeaddr_t rimeaddr; 00206 00207 /* Init Rime */ 00208 ctimer_init(); 00209 rimeaddr.u8[0] = node_id & 0xff; 00210 rimeaddr.u8[1] = node_id >> 8; 00211 rimeaddr_set_node_addr(&rimeaddr); 00212 printf("Rime address: "); 00213 for(i = 0; i < sizeof(rimeaddr_node_addr.u8) - 1; i++) { 00214 printf("%d.", rimeaddr_node_addr.u8[i]); 00215 } 00216 printf("%d\n", rimeaddr_node_addr.u8[i]); 00217 } 00218 00219 queuebuf_init(); 00220 00221 /* Initialize communication stack */ 00222 netstack_init(); 00223 printf("MAC %s RDC %s NETWORK %s\n", NETSTACK_MAC.name, NETSTACK_RDC.name, NETSTACK_NETWORK.name); 00224 00225 #if WITH_UIP 00226 /* IPv4 CONFIGURATION */ 00227 { 00228 uip_ipaddr_t hostaddr, netmask; 00229 00230 process_start(&tcpip_process, NULL); 00231 process_start(&uip_fw_process, NULL); 00232 process_start(&slip_process, NULL); 00233 00234 slip_set_input_callback(set_gateway); 00235 00236 uip_init(); 00237 uip_fw_init(); 00238 uip_ipaddr(&hostaddr, 172,16,rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1]); 00239 uip_ipaddr(&netmask, 255,255,0,0); 00240 uip_ipaddr_copy(&meshif.ipaddr, &hostaddr); 00241 00242 uip_sethostaddr(&hostaddr); 00243 uip_setnetmask(&netmask); 00244 uip_over_mesh_set_net(&hostaddr, &netmask); 00245 uip_over_mesh_set_gateway_netif(&slipif); 00246 uip_fw_default(&meshif); 00247 uip_over_mesh_init(UIP_OVER_MESH_CHANNEL); 00248 00249 rs232_set_input(slip_input_byte); 00250 printf("IPv4 address: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&hostaddr)); 00251 } 00252 #endif /* WITH_UIP */ 00253 00254 #if WITH_UIP6 00255 /* IPv6 CONFIGURATION */ 00256 { 00257 int i; 00258 uint8_t addr[sizeof(uip_lladdr.addr)]; 00259 for (i=0; i < sizeof(uip_lladdr.addr); i++) { 00260 addr[i] = node_id & 0xff; 00261 } 00262 memcpy(&uip_lladdr.addr, addr, sizeof(uip_lladdr.addr)); 00263 process_start(&tcpip_process, NULL); 00264 00265 printf("Tentative link-local IPv6 address "); 00266 { 00267 int i, a; 00268 for(a = 0; a < UIP_DS6_ADDR_NB; a++) { 00269 if (uip_ds6_if.addr_list[a].isused) { 00270 for(i = 0; i < 7; ++i) { 00271 printf("%02x%02x:", 00272 uip_ds6_if.addr_list[a].ipaddr.u8[i * 2], 00273 uip_ds6_if.addr_list[a].ipaddr.u8[i * 2 + 1]); 00274 } 00275 printf("%02x%02x\n", 00276 uip_ds6_if.addr_list[a].ipaddr.u8[14], 00277 uip_ds6_if.addr_list[a].ipaddr.u8[15]); 00278 } 00279 } 00280 } 00281 00282 if(1) { 00283 uip_ipaddr_t ipaddr; 00284 int i; 00285 uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); 00286 uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); 00287 uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); 00288 printf("Tentative global IPv6 address "); 00289 for(i = 0; i < 7; ++i) { 00290 printf("%02x%02x:", 00291 ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]); 00292 } 00293 printf("%02x%02x\n", 00294 ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]); 00295 } 00296 } 00297 #endif /* WITH_UIP6 */ 00298 00299 /* Start serial process */ 00300 serial_line_init(); 00301 00302 /* Start autostart processes (defined in Contiki application) */ 00303 print_processes(autostart_processes); 00304 autostart_start(autostart_processes); 00305 } 00306 /*---------------------------------------------------------------------------*/ 00307 static void 00308 process_run_thread_loop(void *data) 00309 { 00310 /* Yield once during bootup */ 00311 simProcessRunValue = 1; 00312 cooja_mt_yield(); 00313 00314 contiki_init(); 00315 00316 while(1) 00317 { 00318 simProcessRunValue = process_run(); 00319 while(simProcessRunValue-- > 0) { 00320 process_run(); 00321 } 00322 simProcessRunValue = process_nevents(); 00323 00324 /* Check if we must stay awake */ 00325 if(simDontFallAsleep) { 00326 simDontFallAsleep=0; 00327 simProcessRunValue = 1; 00328 } 00329 00330 /* Return to COOJA */ 00331 cooja_mt_yield(); 00332 } 00333 } 00334 /*---------------------------------------------------------------------------*/ 00335 /** 00336 * \brief Initialize a mote by starting processes etc. 00337 * 00338 * This function initializes a mote by starting certain 00339 * processes and setting up the environment. 00340 * 00341 * This is a JNI function and should only be called via the 00342 * responsible Java part (MoteType.java). 00343 */ 00344 JNIEXPORT void JNICALL 00345 Java_se_sics_cooja_corecomm_CLASSNAME_init(JNIEnv *env, jobject obj) 00346 { 00347 /* Create rtimers and Contiki threads */ 00348 cooja_mt_start(&rtimer_thread, &rtimer_thread_loop, NULL); 00349 cooja_mt_start(&process_run_thread, &process_run_thread_loop, NULL); 00350 } 00351 /*---------------------------------------------------------------------------*/ 00352 /** 00353 * \brief Get a segment from the process memory. 00354 * \param start Start address of segment 00355 * \param length Size of memory segment 00356 * \return Java byte array containing a copy of memory segment. 00357 * 00358 * Fetches a memory segment from the process memory starting at 00359 * (start), with size (length). This function does not perform 00360 * ANY error checking, and the process may crash if addresses are 00361 * not available/readable. 00362 * 00363 * This is a JNI function and should only be called via the 00364 * responsible Java part (MoteType.java). 00365 */ 00366 JNIEXPORT void JNICALL 00367 Java_se_sics_cooja_corecomm_CLASSNAME_getMemory(JNIEnv *env, jobject obj, jint rel_addr, jint length, jbyteArray mem_arr) 00368 { 00369 (*env)->SetByteArrayRegion( 00370 env, 00371 mem_arr, 00372 0, 00373 (size_t) length, 00374 (jbyte *) (((long)rel_addr) + referenceVar) 00375 ); 00376 } 00377 /*---------------------------------------------------------------------------*/ 00378 /** 00379 * \brief Replace a segment of the process memory with given byte array. 00380 * \param start Start address of segment 00381 * \param length Size of memory segment 00382 * \param mem_arr Byte array contaning new memory 00383 * 00384 * Replaces a process memory segment with given byte array. 00385 * This function does not perform ANY error checking, and the 00386 * process may crash if addresses are not available/writable. 00387 * 00388 * This is a JNI function and should only be called via the 00389 * responsible Java part (MoteType.java). 00390 */ 00391 JNIEXPORT void JNICALL 00392 Java_se_sics_cooja_corecomm_CLASSNAME_setMemory(JNIEnv *env, jobject obj, jint rel_addr, jint length, jbyteArray mem_arr) 00393 { 00394 jbyte *mem = (*env)->GetByteArrayElements(env, mem_arr, 0); 00395 memcpy( 00396 (char*) (((long)rel_addr) + referenceVar), 00397 mem, 00398 length); 00399 (*env)->ReleaseByteArrayElements(env, mem_arr, mem, 0); 00400 } 00401 /*---------------------------------------------------------------------------*/ 00402 /** 00403 * \brief Let mote execute one "block" of code (tick mote). 00404 * 00405 * Let mote defined by the active contiki processes and current 00406 * process memory execute some program code. This code must not block 00407 * or else this function will never return. A typical contiki 00408 * process will return when it executes PROCESS_WAIT..() statements. 00409 * 00410 * Before the control is left to contiki processes, any messages 00411 * from the Java part are handled. These may for example be 00412 * incoming network data. After the contiki processes return control, 00413 * messages to the Java part are also handled (those which may need 00414 * special attention). 00415 * 00416 * This is a JNI function and should only be called via the 00417 * responsible Java part (MoteType.java). 00418 */ 00419 JNIEXPORT void JNICALL 00420 Java_se_sics_cooja_corecomm_CLASSNAME_tick(JNIEnv *env, jobject obj) 00421 { 00422 clock_time_t nextEtimer; 00423 rtimer_clock_t nextRtimer; 00424 00425 simProcessRunValue = 0; 00426 00427 /* Let all simulation interfaces act first */ 00428 doActionsBeforeTick(); 00429 00430 /* Poll etimer process */ 00431 if (etimer_pending()) { 00432 etimer_request_poll(); 00433 } 00434 00435 /* Let rtimers run. 00436 * Sets simProcessRunValue */ 00437 cooja_mt_exec(&rtimer_thread); 00438 00439 if(simProcessRunValue == 0) { 00440 /* Rtimers done: Let Contiki handle a few events. 00441 * Sets simProcessRunValue */ 00442 cooja_mt_exec(&process_run_thread); 00443 } 00444 00445 /* Let all simulation interfaces act before returning to java */ 00446 doActionsAfterTick(); 00447 00448 /* Do we have any pending timers */ 00449 simEtimerPending = etimer_pending() || rtimer_arch_pending(); 00450 if(!simEtimerPending) { 00451 return; 00452 } 00453 00454 /* Save nearest expiration time */ 00455 nextEtimer = etimer_next_expiration_time() - (clock_time_t) simCurrentTime; 00456 nextRtimer = rtimer_arch_next() - (rtimer_clock_t) simCurrentTime; 00457 if(etimer_pending() && rtimer_arch_pending()) { 00458 simNextExpirationTime = MIN(nextEtimer, nextRtimer); 00459 } else if (etimer_pending()) { 00460 simNextExpirationTime = nextEtimer; 00461 } else if (rtimer_arch_pending()) { 00462 simNextExpirationTime = nextRtimer; 00463 } 00464 } 00465 /*---------------------------------------------------------------------------*/ 00466 /** 00467 * \brief Set the relative memory address of the reference variable. 00468 * \return Relative memory address. 00469 * 00470 * This is a JNI function and should only be called via the 00471 * responsible Java part (MoteType.java). 00472 */ 00473 JNIEXPORT void JNICALL 00474 Java_se_sics_cooja_corecomm_CLASSNAME_setReferenceAddress(JNIEnv *env, jobject obj, jint addr) 00475 { 00476 referenceVar = (((long)&referenceVar) - ((long)addr)); 00477 }