Contiki 2.6

contiki-mc1322x-main.c

00001 /*
00002  * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors
00003  * to the MC1322x project (http://mc1322x.devl.org) and Contiki.
00004  *
00005  * Copyright (c) 2006, Technical University of Munich
00006  * All rights reserved.
00007  *
00008  * Redistribution and use in source and binary forms, with or without
00009  * modification, are permitted provided that the following conditions
00010  * are met:
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  * 3. Neither the name of the Institute nor the names of its contributors
00017  *    may be used to endorse or promote products derived from this software
00018  *    without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00021  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00022  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00023  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00024  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00025  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00026  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00027  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00028  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00029  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00030  * SUCH DAMAGE.
00031  *
00032  * This file is part of the Contiki operating system.
00033  *
00034  * @(#)$$
00035  */
00036 
00037 #include <signal.h>
00038 #include <stdio.h>
00039 #include <string.h>
00040 
00041 #include "contiki.h"
00042 
00043 #include "dev/leds.h"
00044 #include "dev/serial-line.h"
00045 #include "dev/slip.h"
00046 #include "dev/xmem.h"
00047 #include "dev/button-sensor.h"
00048 #include "lib/random.h"
00049 #include "net/netstack.h"
00050 #include "net/mac/frame802154.h"
00051 
00052 #if WITH_UIP6
00053 #include "net/sicslowpan.h"
00054 #include "net/uip-ds6.h"
00055 #include "net/mac/sicslowmac.h"
00056 #endif /* WITH_UIP6 */
00057 
00058 #include "net/rime.h"
00059 
00060 #include "sys/autostart.h"
00061 #include "sys/profile.h"
00062 
00063 /* from libmc1322x */
00064 #include "mc1322x.h"
00065 #include "default_lowlevel.h"
00066 #include "contiki-maca.h"
00067 #include "contiki-uart.h"
00068 
00069 #define DEBUG 1
00070 #if DEBUG
00071 #include <stdio.h>
00072 #define PRINTF(...) printf(__VA_ARGS__)
00073 #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])
00074 #define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",(lladdr)->addr[0], (lladdr)->addr[1], (lladdr)->addr[2], (lladdr)->addr[3],(lladdr)->addr[4], (lladdr)->addr[5])
00075 #else
00076 #define PRINTF(...)
00077 #define PRINT6ADDR(addr)
00078 #define PRINTLLADDR(addr)
00079 #endif
00080 
00081 #ifndef RIMEADDR_NVM
00082 #define RIMEADDR_NVM 0x1E000
00083 #endif
00084 
00085 #ifndef RIMEADDR_NBYTES
00086 #define RIMEADDR_NBYTES 8
00087 #endif
00088 
00089 #define PLATFORM_DEBUG 1
00090 #if PLATFORM_DEBUG
00091 #define PRINTF(...) printf(__VA_ARGS__)
00092 #else
00093 #define PRINTF(...)
00094 #endif
00095 
00096 
00097 #if UIP_CONF_ROUTER
00098 
00099 #ifndef UIP_ROUTER_MODULE
00100 #ifdef UIP_CONF_ROUTER_MODULE
00101 #define UIP_ROUTER_MODULE UIP_CONF_ROUTER_MODULE
00102 #else /* UIP_CONF_ROUTER_MODULE */
00103 #define UIP_ROUTER_MODULE rimeroute
00104 #endif /* UIP_CONF_ROUTER_MODULE */
00105 #endif /* UIP_ROUTER_MODULE */
00106 
00107 extern const struct uip_router UIP_ROUTER_MODULE;
00108 
00109 #endif /* UIP_CONF_ROUTER */
00110 
00111 #if DCOSYNCH_CONF_ENABLED
00112 static struct timer mgt_timer;
00113 #endif
00114 
00115 #ifndef WITH_UIP
00116 #define WITH_UIP 0
00117 #endif
00118 
00119 #if WITH_UIP
00120 #include "net/uip.h"
00121 #include "net/uip-fw.h"
00122 #include "net/uip-fw-drv.h"
00123 #include "net/uip-over-mesh.h"
00124 static struct uip_fw_netif slipif =
00125   {UIP_FW_NETIF(192,168,1,2, 255,255,255,255, slip_send)};
00126 static struct uip_fw_netif meshif =
00127   {UIP_FW_NETIF(172,16,0,0, 255,255,0,0, uip_over_mesh_send)};
00128 
00129 #endif /* WITH_UIP */
00130 
00131 #define UIP_OVER_MESH_CHANNEL 8
00132 #if WITH_UIP
00133 static uint8_t is_gateway;
00134 #endif /* WITH_UIP */
00135 
00136 /*---------------------------------------------------------------------------*/
00137 void uip_log(char *msg) { printf("%c",msg); }
00138 /*---------------------------------------------------------------------------*/
00139 #ifndef RF_CHANNEL
00140 #define RF_CHANNEL              26
00141 #endif
00142 /*---------------------------------------------------------------------------*/
00143 #if WITH_UIP
00144 static void
00145 set_gateway(void)
00146 {
00147   if(!is_gateway) {
00148 //    leds_on(LEDS_RED);
00149     printf("%d.%d: making myself the IP network gateway.\n\n",
00150            rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1]);
00151     printf("IPv4 address of the gateway: %d.%d.%d.%d\n\n",
00152            uip_ipaddr_to_quad(&uip_hostaddr));
00153     uip_over_mesh_set_gateway(&rimeaddr_node_addr);
00154     uip_over_mesh_make_announced_gateway();
00155     is_gateway = 1;
00156   }
00157 }
00158 #endif /* WITH_UIP */
00159 /*---------------------------------------------------------------------------*/
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   printf("\n");
00170 }
00171 /*--------------------------------------------------------------------------*/
00172 
00173 SENSORS(&button_sensor);
00174 
00175 void
00176 init_lowlevel(void)
00177 {
00178         /* led direction init */
00179         set_bit(*GPIO_PAD_DIR0,8);
00180         set_bit(*GPIO_PAD_DIR0,9);
00181         set_bit(*GPIO_PAD_DIR0,10);
00182         set_bit(*GPIO_PAD_DIR0,23);
00183         set_bit(*GPIO_PAD_DIR0,24);
00184         set_bit(*GPIO_PAD_DIR0,25);
00185 
00186         /* button init */
00187         /* set up kbi */
00188         enable_irq_kbi(4);
00189         kbi_edge(4);
00190         enable_ext_wu(4);
00191 //      kbi_pol_neg(7);
00192 //      kbi_pol_pos(7);
00193 //      gpio_sel0_pullup(29);
00194 //      gpio_pu0_disable(29);
00195 
00196         trim_xtal();
00197         
00198         /* uart init */
00199         uart_init(BRINC, BRMOD, SAMP);
00200         
00201         default_vreg_init();
00202 
00203         maca_init();
00204 
00205         set_channel(RF_CHANNEL - 11); /* channel 11 */
00206         set_power(0x12); /* 0x12 is the highest, not documented */
00207 
00208         /* control TX_ON with the radio */
00209         *GPIO_FUNC_SEL2 = (0x01 << ((44-16*2)*2));
00210         gpio_pad_dir_set( 1ULL << 44 );
00211 
00212         enable_irq(CRM);
00213 
00214 #if USE_32KHZ_XTAL
00215         enable_32khz_xtal();
00216 #else
00217         cal_ring_osc();
00218 #endif
00219 
00220 #if USE_32KHZ_XTAL
00221         *CRM_RTC_TIMEOUT = 32768 * 10; 
00222 #else 
00223         *CRM_RTC_TIMEOUT = cal_rtc_secs * 10;
00224 #endif
00225 
00226         /* XXX debug */
00227         /* trigger periodic rtc int */
00228 //      clear_rtc_wu_evt();
00229 //      enable_rtc_wu();
00230 //      enable_rtc_wu_irq();
00231 }
00232 
00233 #if RIMEADDR_SIZE == 1
00234 const rimeaddr_t addr_ff = { { 0xff } };
00235 #else /*RIMEADDR_SIZE == 2*/
00236 #if RIMEADDR_SIZE == 2
00237 const rimeaddr_t addr_ff = { { 0xff, 0xff } };
00238 #else /*RIMEADDR_SIZE == 2*/
00239 #if RIMEADDR_SIZE == 8
00240 const rimeaddr_t addr_ff = { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } };
00241 #endif /*RIMEADDR_SIZE == 8*/
00242 #endif /*RIMEADDR_SIZE == 2*/
00243 #endif /*RIMEADDR_SIZE == 1*/
00244 
00245 void iab_to_eui64(rimeaddr_t *eui64, uint32_t oui, uint16_t iab, uint32_t ext) {
00246         /* OUI for IABs */
00247         eui64->u8[0] =  0x00;
00248         eui64->u8[1] =  0x50;
00249         eui64->u8[2] =  0xc2;
00250 
00251         /* EUI64 field */
00252         eui64->u8[3] = 0xff;
00253         eui64->u8[4] = 0xfe;
00254 
00255         /* IAB */
00256         eui64->u8[5] = (iab >> 4)  & 0xff;      
00257         eui64->u8[6] = (iab & 0xf) << 4;
00258 
00259         /* EXT */
00260         eui64->u8[6] |= ((ext >> 8) &  0xf);    
00261         eui64->u8[7] =    ext       & 0xff;
00262 }
00263 
00264 void oui_to_eui64(rimeaddr_t *eui64, uint32_t oui, uint32_t ext) {
00265         /* OUI */
00266         eui64->u8[0] = (oui >> 16) & 0xff;
00267         eui64->u8[1] = (oui >> 8)  & 0xff;
00268         eui64->u8[2] =  oui        & 0xff;
00269 
00270         /* EUI64 field */
00271         eui64->u8[3] = 0xff;
00272         eui64->u8[4] = 0xfe;
00273 
00274         /* EXT */
00275         eui64->u8[5] = (ext >> 16) & 0xff;
00276         eui64->u8[6] = (ext >> 8)  & 0xff;
00277         eui64->u8[7] =  ext        & 0xff;
00278 }
00279 
00280 void
00281 set_rimeaddr(rimeaddr_t *addr) 
00282 {
00283         nvmType_t type=0;
00284         nvmErr_t err;   
00285         volatile uint8_t buf[RIMEADDR_NBYTES];
00286         rimeaddr_t eui64;
00287         int i;
00288                 
00289         err = nvm_detect(gNvmInternalInterface_c, &type);
00290 
00291         err = nvm_read(gNvmInternalInterface_c, type, (uint8_t *)buf, RIMEADDR_NVM, RIMEADDR_NBYTES);
00292 
00293         rimeaddr_copy(addr,&rimeaddr_null);
00294 
00295         for(i=0; i<RIMEADDR_CONF_SIZE; i++) {           
00296                 addr->u8[i] = buf[i];
00297         }
00298 
00299         if (memcmp(addr, &addr_ff, RIMEADDR_CONF_SIZE)==0) {
00300 
00301                 //set addr to EUI64
00302 #ifdef IAB              
00303    #ifdef EXT_ID
00304                 PRINTF("address in flash blank, setting to defined IAB and extension.\n\r");
00305                 iab_to_eui64(&eui64, OUI, IAB, EXT_ID);
00306    #else  /* ifdef EXT_ID */
00307                 PRINTF("address in flash blank, setting to defined IAB with a random extension.\n\r");
00308                 iab_to_eui64(&eui64, OUI, IAB, *MACA_RANDOM & 0xfff);
00309    #endif /* ifdef EXT_ID */
00310 
00311 #else  /* ifdef IAB */
00312 
00313    #ifdef EXT_ID
00314                 PRINTF("address in flash blank, setting to defined OUI and extension.\n\r");
00315                 oui_to_eui64(&eui64, OUI, EXT_ID);
00316    #else  /*ifdef EXT_ID */
00317                 PRINTF("address in flash blank, setting to defined OUI with a random extension.\n\r");
00318                 oui_to_eui64(&eui64, OUI, *MACA_RANDOM & 0xffffff);
00319    #endif /*endif EXTID */
00320 
00321 #endif /* ifdef IAB */
00322 
00323                 rimeaddr_copy(addr, &eui64);            
00324 #ifdef FLASH_BLANK_ADDR
00325                 PRINTF("flashing blank address\n\r");
00326                 err = nvm_write(gNvmInternalInterface_c, type, &(eui64.u8), RIMEADDR_NVM, RIMEADDR_NBYTES);             
00327 #endif /* ifdef FLASH_BLANK_ADDR */
00328         } else {
00329                 PRINTF("loading rime address from flash.\n\r");
00330         }
00331 
00332         rimeaddr_set_node_addr(addr);
00333 }
00334 
00335 int
00336 main(void)
00337 {
00338         volatile uint32_t i;
00339         rimeaddr_t addr;
00340 
00341         /* Initialize hardware and */
00342         /* go into user mode */
00343         init_lowlevel();
00344 
00345         /* Clock */
00346         clock_init();   
00347 
00348         /* Process subsystem */
00349         process_init();
00350         process_start(&etimer_process, NULL);
00351         process_start(&contiki_maca_process, NULL);
00352 
00353         ctimer_init();
00354 
00355         set_rimeaddr(&addr);
00356 
00357         printf("Rime started with address ");
00358         for(i = 0; i < sizeof(addr.u8) - 1; i++) {
00359                 printf("%02X:", addr.u8[i]);
00360         }
00361         printf("%02X\n", addr.u8[i]);
00362 
00363 
00364 #if WITH_UIP6
00365   memcpy(&uip_lladdr.addr, &addr.u8, sizeof(uip_lladdr.addr));
00366   /* Setup nullmac-like MAC for 802.15.4 */
00367 /*   sicslowpan_init(sicslowmac_init(&cc2420_driver)); */
00368 /*   printf(" %s channel %u\n", sicslowmac_driver.name, RF_CHANNEL); */
00369 
00370   /* Setup X-MAC for 802.15.4 */
00371   queuebuf_init();
00372   NETSTACK_RDC.init();
00373   NETSTACK_MAC.init();
00374   NETSTACK_NETWORK.init();
00375 
00376   printf("%s %s, channel check rate %lu Hz, radio channel %u\n",
00377          NETSTACK_MAC.name, NETSTACK_RDC.name,
00378          CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1:
00379                          NETSTACK_RDC.channel_check_interval()),
00380          RF_CHANNEL);
00381 
00382   process_start(&tcpip_process, NULL);
00383 
00384   printf("Tentative link-local IPv6 address ");
00385   {
00386     int i, a;
00387     for(a = 0; a < UIP_DS6_ADDR_NB; a++) {
00388       if (uip_ds6_if.addr_list[a].isused) {
00389         for(i = 0; i < 7; ++i) {
00390           printf("%02x%02x:",
00391                  uip_ds6_if.addr_list[a].ipaddr.u8[i * 2],
00392                  uip_ds6_if.addr_list[a].ipaddr.u8[i * 2 + 1]);
00393         }
00394         printf("%02x%02x\n",
00395                uip_ds6_if.addr_list[a].ipaddr.u8[14],
00396                uip_ds6_if.addr_list[a].ipaddr.u8[15]);
00397       }
00398     }
00399   }
00400   
00401   if(1) {
00402     uip_ipaddr_t ipaddr;
00403     int i;
00404     uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
00405     uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
00406     uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE);
00407     printf("Tentative global IPv6 address ");
00408     for(i = 0; i < 7; ++i) {
00409       printf("%02x%02x:",
00410              ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]);
00411     }
00412     printf("%02x%02x\n",
00413            ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]);
00414   }
00415 
00416   
00417 #else /* WITH_UIP6 */
00418 
00419   NETSTACK_RDC.init();
00420   NETSTACK_MAC.init();
00421   NETSTACK_NETWORK.init();
00422 
00423   printf("%s %s, channel check rate %lu Hz, radio channel %u\n",
00424          NETSTACK_MAC.name, NETSTACK_RDC.name,
00425          CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0? 1:
00426                          NETSTACK_RDC.channel_check_interval()),
00427          RF_CHANNEL);
00428 #endif /* WITH_UIP6 */
00429 
00430 #if PROFILE_CONF_ON
00431   profile_init();
00432 #endif /* PROFILE_CONF_ON */
00433 
00434 #if TIMESYNCH_CONF_ENABLED
00435   timesynch_init();
00436   timesynch_set_authority_level(rimeaddr_node_addr.u8[0]);
00437 #endif /* TIMESYNCH_CONF_ENABLED */
00438 
00439 #if WITH_UIP
00440   process_start(&tcpip_process, NULL);
00441   process_start(&uip_fw_process, NULL); /* Start IP output */
00442   process_start(&slip_process, NULL);
00443 
00444   slip_set_input_callback(set_gateway);
00445 
00446   {
00447     uip_ipaddr_t hostaddr, netmask;
00448 
00449     uip_init();
00450 
00451     uip_ipaddr(&hostaddr, 172,16,
00452                rimeaddr_node_addr.u8[0],rimeaddr_node_addr.u8[1]);
00453     uip_ipaddr(&netmask, 255,255,0,0);
00454     uip_ipaddr_copy(&meshif.ipaddr, &hostaddr);
00455 
00456     uip_sethostaddr(&hostaddr);
00457     uip_setnetmask(&netmask);
00458     uip_over_mesh_set_net(&hostaddr, &netmask);
00459     /*    uip_fw_register(&slipif);*/
00460     uip_over_mesh_set_gateway_netif(&slipif);
00461     uip_fw_default(&meshif);
00462     uip_over_mesh_init(UIP_OVER_MESH_CHANNEL);
00463     printf("uIP started with IP address %d.%d.%d.%d\n",
00464            uip_ipaddr_to_quad(&hostaddr));
00465   }
00466 #endif /* WITH_UIP */
00467 
00468   process_start(&sensors_process, NULL);
00469   
00470   print_processes(autostart_processes);
00471   autostart_start(autostart_processes);
00472  
00473   /* Main scheduler loop */
00474   while(1) {
00475           check_maca();
00476 
00477           /* TODO: replace this with a uart rx interrupt */
00478           if(uart1_input_handler != NULL) {
00479                   if(uart1_can_get()) {
00480                           uart1_input_handler(uart1_getc());
00481                   }
00482           }
00483                  
00484           process_run();
00485   }
00486   
00487   return 0;
00488 }
00489 
00490 /*---------------------------------------------------------------------------*/
00491 #if LOG_CONF_ENABLED
00492 void
00493 log_message(char *m1, char *m2)
00494 {
00495   printf("%s%s\n", m1, m2);
00496 }
00497 #endif /* LOG_CONF_ENABLED */