Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2006, 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-sky-main.c,v 1.87 2011/01/09 21:03:42 adamdunkels Exp $ 00030 */ 00031 00032 #include <stdio.h> 00033 #include <string.h> 00034 #include "contiki.h" 00035 #include "dev/cc2420.h" 00036 #include "dev/ds2411.h" 00037 #include "dev/leds.h" 00038 #include "dev/serial-line.h" 00039 #include "dev/slip.h" 00040 #include "dev/uart1.h" 00041 #include "dev/watchdog.h" 00042 #include "dev/xmem.h" 00043 #include "lib/random.h" 00044 #include "net/netstack.h" 00045 #include "net/mac/frame802154.h" 00046 00047 #if WITH_UIP6 00048 #include "net/uip-ds6.h" 00049 #endif /* WITH_UIP6 */ 00050 00051 #include "net/rime.h" 00052 00053 #include "node-id.h" 00054 #include "cfs-coffee-arch.h" 00055 #include "cfs/cfs-coffee.h" 00056 #include "sys/autostart.h" 00057 #include "sys/profile.h" 00058 00059 #if UIP_CONF_ROUTER 00060 00061 #ifndef UIP_ROUTER_MODULE 00062 #ifdef UIP_CONF_ROUTER_MODULE 00063 #define UIP_ROUTER_MODULE UIP_CONF_ROUTER_MODULE 00064 #else /* UIP_CONF_ROUTER_MODULE */ 00065 #define UIP_ROUTER_MODULE rimeroute 00066 #endif /* UIP_CONF_ROUTER_MODULE */ 00067 #endif /* UIP_ROUTER_MODULE */ 00068 00069 extern const struct uip_router UIP_ROUTER_MODULE; 00070 #endif /* UIP_CONF_ROUTER */ 00071 00072 #if DCOSYNCH_CONF_ENABLED 00073 static struct timer mgt_timer; 00074 #endif 00075 extern int msp430_dco_required; 00076 00077 #ifndef WITH_UIP 00078 #define WITH_UIP 0 00079 #endif 00080 00081 #if WITH_UIP 00082 #include "net/uip.h" 00083 #include "net/uip-fw.h" 00084 #include "net/uip-fw-drv.h" 00085 #include "net/uip-over-mesh.h" 00086 static struct uip_fw_netif slipif = 00087 {UIP_FW_NETIF(192,168,1,2, 255,255,255,255, slip_send)}; 00088 static struct uip_fw_netif meshif = 00089 {UIP_FW_NETIF(172,16,0,0, 255,255,0,0, uip_over_mesh_send)}; 00090 00091 #endif /* WITH_UIP */ 00092 00093 #define UIP_OVER_MESH_CHANNEL 8 00094 #if WITH_UIP 00095 static uint8_t is_gateway; 00096 #endif /* WITH_UIP */ 00097 00098 #ifdef EXPERIMENT_SETUP 00099 #include "experiment-setup.h" 00100 #endif 00101 00102 void init_platform(void); 00103 00104 /*---------------------------------------------------------------------------*/ 00105 #if 0 00106 int 00107 force_float_inclusion() 00108 { 00109 extern int __fixsfsi; 00110 extern int __floatsisf; 00111 extern int __mulsf3; 00112 extern int __subsf3; 00113 00114 return __fixsfsi + __floatsisf + __mulsf3 + __subsf3; 00115 } 00116 #endif 00117 /*---------------------------------------------------------------------------*/ 00118 void uip_log(char *msg) { puts(msg); } 00119 /*---------------------------------------------------------------------------*/ 00120 #ifndef RF_CHANNEL 00121 #define RF_CHANNEL 26 00122 #endif 00123 /*---------------------------------------------------------------------------*/ 00124 #if 0 00125 void 00126 force_inclusion(int d1, int d2) 00127 { 00128 snprintf(NULL, 0, "%d", d1 % d2); 00129 } 00130 #endif 00131 /*---------------------------------------------------------------------------*/ 00132 static void 00133 set_rime_addr(void) 00134 { 00135 rimeaddr_t addr; 00136 int i; 00137 00138 memset(&addr, 0, sizeof(rimeaddr_t)); 00139 #if UIP_CONF_IPV6 00140 memcpy(addr.u8, ds2411_id, sizeof(addr.u8)); 00141 #else 00142 if(node_id == 0) { 00143 for(i = 0; i < sizeof(rimeaddr_t); ++i) { 00144 addr.u8[i] = ds2411_id[7 - i]; 00145 } 00146 } else { 00147 addr.u8[0] = node_id & 0xff; 00148 addr.u8[1] = node_id >> 8; 00149 } 00150 #endif 00151 rimeaddr_set_node_addr(&addr); 00152 printf("Rime started with address "); 00153 for(i = 0; i < sizeof(addr.u8) - 1; i++) { 00154 printf("%d.", addr.u8[i]); 00155 } 00156 printf("%d\n", addr.u8[i]); 00157 } 00158 /*---------------------------------------------------------------------------*/ 00159 #if !PROCESS_CONF_NO_PROCESS_NAMES 00160 static void 00161 print_processes(struct process * const processes[]) 00162 { 00163 /* const struct process * const * p = processes;*/ 00164 printf("Starting"); 00165 while(*processes != NULL) { 00166 printf(" '%s'", (*processes)->name); 00167 processes++; 00168 } 00169 putchar('\n'); 00170 } 00171 #endif /* !PROCESS_CONF_NO_PROCESS_NAMES */ 00172 /*--------------------------------------------------------------------------*/ 00173 #if WITH_UIP 00174 static void 00175 set_gateway(void) 00176 { 00177 if(!is_gateway) { 00178 leds_on(LEDS_RED); 00179 printf("%d.%d: making myself the IP network gateway.\n\n", 00180 rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]); 00181 printf("IPv4 address of the gateway: %d.%d.%d.%d\n\n", 00182 uip_ipaddr_to_quad(&uip_hostaddr)); 00183 uip_over_mesh_set_gateway(&rimeaddr_node_addr); 00184 uip_over_mesh_make_announced_gateway(); 00185 is_gateway = 1; 00186 } 00187 } 00188 #endif /* WITH_UIP */ 00189 /*---------------------------------------------------------------------------*/ 00190 #if WITH_TINYOS_AUTO_IDS 00191 uint16_t TOS_NODE_ID = 0x1234; /* non-zero */ 00192 uint16_t TOS_LOCAL_ADDRESS = 0x1234; /* non-zero */ 00193 #endif /* WITH_TINYOS_AUTO_IDS */ 00194 int 00195 main(int argc, char **argv) 00196 { 00197 /* 00198 * Initalize hardware. 00199 */ 00200 msp430_cpu_init(); 00201 clock_init(); 00202 leds_init(); 00203 leds_on(LEDS_RED); 00204 00205 00206 uart1_init(BAUD2UBR(115200)); /* Must come before first printf */ 00207 00208 leds_on(LEDS_GREEN); 00209 ds2411_init(); 00210 00211 /* XXX hack: Fix it so that the 802.15.4 MAC address is compatible 00212 with an Ethernet MAC address - byte 0 (byte 2 in the DS ID) 00213 cannot be odd. */ 00214 ds2411_id[2] &= 0xfe; 00215 00216 leds_on(LEDS_BLUE); 00217 xmem_init(); 00218 00219 leds_off(LEDS_RED); 00220 rtimer_init(); 00221 /* 00222 * Hardware initialization done! 00223 */ 00224 00225 00226 #if WITH_TINYOS_AUTO_IDS 00227 node_id = TOS_NODE_ID; 00228 #else /* WITH_TINYOS_AUTO_IDS */ 00229 /* Restore node id if such has been stored in external mem */ 00230 node_id_restore(); 00231 #endif /* WITH_TINYOS_AUTO_IDS */ 00232 00233 /* for setting "hardcoded" IEEE 802.15.4 MAC addresses */ 00234 #ifdef IEEE_802154_MAC_ADDRESS 00235 { 00236 uint8_t ieee[] = IEEE_802154_MAC_ADDRESS; 00237 memcpy(ds2411_id, ieee, sizeof(uip_lladdr.addr)); 00238 ds2411_id[7] = node_id & 0xff; 00239 } 00240 #endif 00241 00242 random_init(ds2411_id[0] + node_id); 00243 00244 leds_off(LEDS_BLUE); 00245 /* 00246 * Initialize Contiki and our processes. 00247 */ 00248 process_init(); 00249 process_start(&etimer_process, NULL); 00250 00251 ctimer_init(); 00252 00253 #if WITH_UIP 00254 slip_arch_init(BAUD2UBR(115200)); 00255 #endif /* WITH_UIP */ 00256 00257 init_platform(); 00258 00259 set_rime_addr(); 00260 00261 cc2420_init(); 00262 { 00263 uint8_t longaddr[8]; 00264 uint16_t shortaddr; 00265 00266 shortaddr = (rimeaddr_node_addr.u8[0] << 8) + 00267 rimeaddr_node_addr.u8[1]; 00268 memset(longaddr, 0, sizeof(longaddr)); 00269 rimeaddr_copy((rimeaddr_t *)&longaddr, &rimeaddr_node_addr); 00270 printf("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ", 00271 longaddr[0], longaddr[1], longaddr[2], longaddr[3], 00272 longaddr[4], longaddr[5], longaddr[6], longaddr[7]); 00273 00274 cc2420_set_pan_addr(IEEE802154_PANID, shortaddr, longaddr); 00275 } 00276 cc2420_set_channel(RF_CHANNEL); 00277 00278 printf(CONTIKI_VERSION_STRING " started. "); 00279 if(node_id > 0) { 00280 printf("Node id is set to %u.\n", node_id); 00281 } else { 00282 printf("Node id is not set.\n"); 00283 } 00284 00285 /* printf("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", 00286 ds2411_id[0], ds2411_id[1], ds2411_id[2], ds2411_id[3], 00287 ds2411_id[4], ds2411_id[5], ds2411_id[6], ds2411_id[7]);*/ 00288 00289 #if WITH_UIP6 00290 memcpy(&uip_lladdr.addr, ds2411_id, sizeof(uip_lladdr.addr)); 00291 /* Setup nullmac-like MAC for 802.15.4 */ 00292 /* sicslowpan_init(sicslowmac_init(&cc2420_driver)); */ 00293 /* printf(" %s channel %u\n", sicslowmac_driver.name, RF_CHANNEL); */ 00294 00295 /* Setup X-MAC for 802.15.4 */ 00296 queuebuf_init(); 00297 NETSTACK_RDC.init(); 00298 NETSTACK_MAC.init(); 00299 NETSTACK_NETWORK.init(); 00300 00301 printf("%s %s, channel check rate %lu Hz, radio channel %u\n", 00302 NETSTACK_MAC.name, NETSTACK_RDC.name, 00303 CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1: 00304 NETSTACK_RDC.channel_check_interval()), 00305 RF_CHANNEL); 00306 00307 process_start(&tcpip_process, NULL); 00308 00309 printf("Tentative link-local IPv6 address "); 00310 { 00311 uip_ds6_addr_t *lladdr; 00312 int i; 00313 lladdr = uip_ds6_get_link_local(-1); 00314 for(i = 0; i < 7; ++i) { 00315 printf("%02x%02x:", lladdr->ipaddr.u8[i * 2], 00316 lladdr->ipaddr.u8[i * 2 + 1]); 00317 } 00318 printf("%02x%02x\n", lladdr->ipaddr.u8[14], lladdr->ipaddr.u8[15]); 00319 } 00320 00321 if(!UIP_CONF_IPV6_RPL) { 00322 uip_ipaddr_t ipaddr; 00323 int i; 00324 uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); 00325 uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); 00326 uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); 00327 printf("Tentative global IPv6 address "); 00328 for(i = 0; i < 7; ++i) { 00329 printf("%02x%02x:", 00330 ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]); 00331 } 00332 printf("%02x%02x\n", 00333 ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]); 00334 } 00335 00336 #else /* WITH_UIP6 */ 00337 00338 NETSTACK_RDC.init(); 00339 NETSTACK_MAC.init(); 00340 NETSTACK_NETWORK.init(); 00341 00342 printf("%s %s, channel check rate %lu Hz, radio channel %u\n", 00343 NETSTACK_MAC.name, NETSTACK_RDC.name, 00344 CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0? 1: 00345 NETSTACK_RDC.channel_check_interval()), 00346 RF_CHANNEL); 00347 #endif /* WITH_UIP6 */ 00348 00349 #if !WITH_UIP && !WITH_UIP6 00350 uart1_set_input(serial_line_input_byte); 00351 serial_line_init(); 00352 #endif 00353 00354 #if PROFILE_CONF_ON 00355 profile_init(); 00356 #endif /* PROFILE_CONF_ON */ 00357 00358 leds_off(LEDS_GREEN); 00359 00360 #if TIMESYNCH_CONF_ENABLED 00361 timesynch_init(); 00362 timesynch_set_authority_level((rimeaddr_node_addr.u8[0] << 4) + 16); 00363 #endif /* TIMESYNCH_CONF_ENABLED */ 00364 00365 #if WITH_UIP 00366 process_start(&tcpip_process, NULL); 00367 process_start(&uip_fw_process, NULL); /* Start IP output */ 00368 process_start(&slip_process, NULL); 00369 00370 slip_set_input_callback(set_gateway); 00371 00372 { 00373 uip_ipaddr_t hostaddr, netmask; 00374 00375 uip_init(); 00376 00377 uip_ipaddr(&hostaddr, 172,16, 00378 rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1]); 00379 uip_ipaddr(&netmask, 255,255,0,0); 00380 uip_ipaddr_copy(&meshif.ipaddr, &hostaddr); 00381 00382 uip_sethostaddr(&hostaddr); 00383 uip_setnetmask(&netmask); 00384 uip_over_mesh_set_net(&hostaddr, &netmask); 00385 /* uip_fw_register(&slipif);*/ 00386 uip_over_mesh_set_gateway_netif(&slipif); 00387 uip_fw_default(&meshif); 00388 uip_over_mesh_init(UIP_OVER_MESH_CHANNEL); 00389 printf("uIP started with IP address %d.%d.%d.%d\n", 00390 uip_ipaddr_to_quad(&hostaddr)); 00391 } 00392 #endif /* WITH_UIP */ 00393 00394 energest_init(); 00395 ENERGEST_ON(ENERGEST_TYPE_CPU); 00396 00397 watchdog_start(); 00398 00399 #if !PROCESS_CONF_NO_PROCESS_NAMES 00400 print_processes(autostart_processes); 00401 #else /* !PROCESS_CONF_NO_PROCESS_NAMES */ 00402 putchar('\n'); /* include putchar() */ 00403 #endif /* !PROCESS_CONF_NO_PROCESS_NAMES */ 00404 autostart_start(autostart_processes); 00405 00406 /* 00407 * This is the scheduler loop. 00408 */ 00409 #if DCOSYNCH_CONF_ENABLED 00410 timer_set(&mgt_timer, DCOSYNCH_PERIOD * CLOCK_SECOND); 00411 #endif 00412 00413 /* watchdog_stop();*/ 00414 while(1) { 00415 int r; 00416 #if PROFILE_CONF_ON 00417 profile_episode_start(); 00418 #endif /* PROFILE_CONF_ON */ 00419 do { 00420 /* Reset watchdog. */ 00421 watchdog_periodic(); 00422 r = process_run(); 00423 } while(r > 0); 00424 #if PROFILE_CONF_ON 00425 profile_episode_end(); 00426 #endif /* PROFILE_CONF_ON */ 00427 00428 /* 00429 * Idle processing. 00430 */ 00431 int s = splhigh(); /* Disable interrupts. */ 00432 /* uart1_active is for avoiding LPM3 when still sending or receiving */ 00433 if(process_nevents() != 0 || uart1_active()) { 00434 splx(s); /* Re-enable interrupts. */ 00435 } else { 00436 static unsigned long irq_energest = 0; 00437 00438 #if DCOSYNCH_CONF_ENABLED 00439 /* before going down to sleep possibly do some management */ 00440 if(timer_expired(&mgt_timer)) { 00441 watchdog_periodic(); 00442 timer_reset(&mgt_timer); 00443 msp430_sync_dco(); 00444 #if CC2420_CONF_SFD_TIMESTAMPS 00445 cc2420_arch_sfd_init(); 00446 #endif /* CC2420_CONF_SFD_TIMESTAMPS */ 00447 } 00448 #endif 00449 00450 /* Re-enable interrupts and go to sleep atomically. */ 00451 ENERGEST_OFF(ENERGEST_TYPE_CPU); 00452 ENERGEST_ON(ENERGEST_TYPE_LPM); 00453 /* We only want to measure the processing done in IRQs when we 00454 are asleep, so we discard the processing time done when we 00455 were awake. */ 00456 energest_type_set(ENERGEST_TYPE_IRQ, irq_energest); 00457 watchdog_stop(); 00458 /* check if the DCO needs to be on - if so - only LPM 1 */ 00459 if (msp430_dco_required) { 00460 _BIS_SR(GIE | CPUOFF); /* LPM1 sleep for DMA to work!. */ 00461 } else { 00462 _BIS_SR(GIE | SCG0 | SCG1 | CPUOFF); /* LPM3 sleep. This 00463 statement will block 00464 until the CPU is 00465 woken up by an 00466 interrupt that sets 00467 the wake up flag. */ 00468 } 00469 /* We get the current processing time for interrupts that was 00470 done during the LPM and store it for next time around. */ 00471 dint(); 00472 irq_energest = energest_type_time(ENERGEST_TYPE_IRQ); 00473 eint(); 00474 watchdog_start(); 00475 ENERGEST_OFF(ENERGEST_TYPE_LPM); 00476 ENERGEST_ON(ENERGEST_TYPE_CPU); 00477 } 00478 } 00479 00480 return 0; 00481 } 00482 /*---------------------------------------------------------------------------*/ 00483 #if LOG_CONF_ENABLED 00484 void 00485 log_message(char *m1, char *m2) 00486 { 00487 printf("%s%s\n", m1, m2); 00488 } 00489 #endif /* LOG_CONF_ENABLED */