Contiki 2.6

contiki-wismote-main.c

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 */