Contiki 2.6

contiki-z1-main.c

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