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