contiki-raven-main.c

00001 /*
00002  * Copyright (c) 2006, Technical University of Munich
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  * This file is part of the Contiki operating system.
00030  *
00031  * @(#)$$
00032  */
00033 #define ANNOUNCE_BOOT 1    //adds about 600 bytes to program size
00034 #define PRINTF(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
00035 
00036 #define DEBUG 0
00037 #if DEBUG
00038 #define PRINTFD(FORMAT,args...) printf_P(PSTR(FORMAT),##args)
00039 #else
00040 #define PRINTFD(...)
00041 #endif
00042 
00043 #include <avr/pgmspace.h>
00044 #include <avr/fuse.h>
00045 #include <avr/eeprom.h>
00046 #include <stdio.h>
00047 #include <string.h>
00048 #include <dev/watchdog.h>
00049 
00050 #include "loader/symbols-def.h"
00051 #include "loader/symtab.h"
00052 
00053 #if RF230BB        //radio driver using contiki core mac
00054 #include "radio/rf230bb/rf230bb.h"
00055 #include "net/mac/frame802154.h"
00056 #include "net/mac/framer-802154.h"
00057 #include "net/sicslowpan.h"
00058 
00059 #else                 //radio driver using Atmel/Cisco 802.15.4'ish MAC
00060 #include <stdbool.h>
00061 #include "mac.h"
00062 #include "sicslowmac.h"
00063 #include "sicslowpan.h"
00064 #include "ieee-15-4-manager.h"
00065 #endif /*RF230BB*/
00066 
00067 #include "contiki.h"
00068 #include "contiki-net.h"
00069 #include "contiki-lib.h"
00070 
00071 #include "dev/rs232.h"
00072 #include "dev/serial-line.h"
00073 #include "dev/slip.h"
00074 
00075 #ifdef RAVEN_LCD_INTERFACE
00076 #include "raven-lcd.h"
00077 #endif
00078 
00079 #if WEBSERVER
00080 #include "httpd-fs.h"
00081 #include "httpd-cgi.h"
00082 #endif
00083 
00084 #ifdef COFFEE_FILES
00085 #include "cfs/cfs.h"
00086 #include "cfs/cfs-coffee.h"
00087 #endif
00088 
00089 #if UIP_CONF_ROUTER&&0
00090 #include "net/routing/rimeroute.h"
00091 #include "net/rime/rime-udp.h"
00092 #endif
00093 
00094 #include "net/rime.h"
00095 
00096 /* Test rtimers, also for pings, stack monitor, neighbor/route printout and time stamps */
00097 #define TESTRTIMER 0
00098 #if TESTRTIMER
00099 //#define PINGS 64
00100 #define ROUTES 64
00101 #define STAMPS 30
00102 #define STACKMONITOR 128
00103 
00104 uint8_t rtimerflag=1;
00105 uint16_t rtime;
00106 struct rtimer rt;
00107 void rtimercycle(void) {rtimerflag=1;}
00108 static void ipaddr_add(const uip_ipaddr_t *addr);
00109 
00110 #endif /* TESTRTIMER */
00111 
00112 /*-------------------------------------------------------------------------*/
00113 /*----------------------Configuration of the .elf file---------------------*/
00114 typedef struct {unsigned char B2;unsigned char B1;unsigned char B0;} __signature_t;
00115 #define SIGNATURE __signature_t __signature __attribute__((section (".signature")))
00116 SIGNATURE = {
00117 /* Older AVR-GCCs may not define the SIGNATURE_n bytes so use explicit 1284p values */
00118   .B2 = 0x05,//SIGNATURE_2,
00119   .B1 = 0x97,//SIGNATURE_1,
00120   .B0 = 0x1E,//SIGNATURE_0,
00121 };
00122 FUSES ={.low = 0xe2, .high = 0x99, .extended = 0xff,};
00123 
00124 /*----------------------Configuration of EEPROM---------------------------*/
00125 /* Use existing EEPROM if it passes the integrity test, else reinitialize with build values */
00126 
00127 /* Put default MAC address in EEPROM */
00128 #if WEBSERVER
00129 extern uint8_t mac_address[8];     //These are defined in httpd-fsdata.c via makefsdata.h
00130 extern uint8_t server_name[16];
00131 extern uint8_t domain_name[30];
00132 #else
00133 uint8_t mac_address[8] EEMEM = {0x02, 0x11, 0x22, 0xff, 0xfe, 0x33, 0x44, 0x55};
00134 #endif
00135 
00136 
00137 #ifdef CHANNEL_802_15_4
00138 uint8_t rf_channel[2] EEMEM = {CHANNEL_802_15_4, ~CHANNEL_802_15_4};
00139 #else
00140 uint8_t rf_channel[2] EEMEM = {22, ~22};
00141 #endif
00142         volatile uint8_t eeprom_channel;
00143 static uint8_t get_channel_from_eeprom() {
00144 //      volatile uint8_t eeprom_channel;
00145         uint8_t eeprom_check;
00146         eeprom_channel = eeprom_read_byte(&rf_channel[0]);
00147         eeprom_check = eeprom_read_byte(&rf_channel[1]);
00148 
00149         if(eeprom_channel==~eeprom_check)
00150                 return eeprom_channel;
00151 
00152 #ifdef CHANNEL_802_15_4
00153         return(CHANNEL_802_15_4);
00154 #else
00155         return 26;
00156 #endif
00157 }
00158 
00159 static bool get_mac_from_eeprom(uint8_t* macptr) {
00160         eeprom_read_block ((void *)macptr,  &mac_address, 8);
00161         return true;
00162 }
00163 
00164 static uint16_t get_panid_from_eeprom(void) {
00165         // TODO: Writeme!
00166         return IEEE802154_PANID;
00167 }
00168 
00169 static uint16_t get_panaddr_from_eeprom(void) {
00170         // TODO: Writeme!
00171         return 0;
00172 }
00173 
00174 void calibrate_rc_osc_32k();
00175 
00176 /*-------------------------Low level initialization------------------------*/
00177 /*------Done in a subroutine to keep main routine stack usage small--------*/
00178 void initialize(void)
00179 {
00180   watchdog_init();
00181   watchdog_start();
00182 
00183 #ifdef RAVEN_LCD_INTERFACE
00184   /* First rs232 port for Raven 3290 port */
00185   rs232_init(RS232_PORT_0, USART_BAUD_38400,USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8);
00186   /* Set input handler for 3290 port */
00187   rs232_set_input(0,raven_lcd_serial_input);
00188 #endif
00189 
00190   /* Second rs232 port for debugging */
00191   rs232_init(RS232_PORT_1, USART_BAUD_57600,USART_PARITY_NONE | USART_STOP_BITS_1 | USART_DATA_BITS_8);
00192   /* Redirect stdout to second port */
00193   rs232_redirect_stdout(RS232_PORT_1);
00194   clock_init();
00195 
00196 #if STACKMONITOR
00197   /* Simple stack pointer highwater monitor. Checks for magic numbers in the main
00198    * loop. In conjuction with TESTRTIMER, never-used stack will be printed
00199    * every STACKMONITOR seconds.
00200    */
00201 {
00202 extern uint16_t __bss_end;
00203 uint16_t p=(uint16_t)&__bss_end;
00204     do {
00205       *(uint16_t *)p = 0x4242;
00206       p+=10;
00207     } while (p<SP-10); //don't overwrite our own stack
00208 }
00209 #endif
00210   
00211 #define CONF_CALIBRATE_OSCCAL 0
00212 #if CONF_CALIBRATE_OSCCAL
00213 {
00214 extern uint8_t osccal_calibrated;
00215 uint8_t i;
00216   PRINTF("\nBefore calibration OSCCAL=%x\n",OSCCAL);
00217   for (i=0;i<10;i++) { 
00218     calibrate_rc_osc_32k();  
00219     PRINTF("Calibrated=%x\n",osccal_calibrated);
00220 //#include <util/delay_basic.h>
00221 //#define delay_us( us )   ( _delay_loop_2(1+(us*F_CPU)/4000000UL) ) 
00222 //   delay_us(50000);
00223  }
00224    clock_init();
00225 }
00226 #endif 
00227 
00228 #if ANNOUNCE_BOOT
00229   PRINTF("\n*******Booting %s*******\n",CONTIKI_VERSION_STRING);
00230 #endif
00231 
00232 /* rtimers needed for radio cycling */
00233   rtimer_init();
00234 
00235  /* Initialize process subsystem */
00236   process_init();
00237  /* etimers must be started before ctimer_init */
00238   process_start(&etimer_process, NULL);
00239 
00240 #if RF230BB
00241 
00242   ctimer_init();
00243   /* Start radio and radio receive process */
00244   NETSTACK_RADIO.init();
00245 
00246   /* Set addresses BEFORE starting tcpip process */
00247 
00248   rimeaddr_t addr;
00249   memset(&addr, 0, sizeof(rimeaddr_t));
00250   get_mac_from_eeprom(addr.u8);
00251  
00252 #if UIP_CONF_IPV6 
00253   memcpy(&uip_lladdr.addr, &addr.u8, 8);
00254 #endif  
00255   rf230_set_pan_addr(
00256         get_panid_from_eeprom(),
00257         get_panaddr_from_eeprom(),
00258         (uint8_t *)&addr.u8
00259   );
00260   rf230_set_channel(get_channel_from_eeprom());
00261 
00262   rimeaddr_set_node_addr(&addr); 
00263 
00264   PRINTFD("MAC address %x:%x:%x:%x:%x:%x:%x:%x\n",addr.u8[0],addr.u8[1],addr.u8[2],addr.u8[3],addr.u8[4],addr.u8[5],addr.u8[6],addr.u8[7]);
00265 
00266   /* Initialize stack protocols */
00267   queuebuf_init();
00268   NETSTACK_RDC.init();
00269   NETSTACK_MAC.init();
00270   NETSTACK_NETWORK.init();
00271 
00272 #if ANNOUNCE_BOOT
00273   PRINTF("%s %s, channel %u",NETSTACK_MAC.name, NETSTACK_RDC.name,rf230_get_channel());
00274   if (NETSTACK_RDC.channel_check_interval) {//function pointer is zero for sicslowmac
00275     unsigned short tmp;
00276     tmp=CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval == 0 ? 1:\
00277                                    NETSTACK_RDC.channel_check_interval());
00278     if (tmp<65535) printf_P(PSTR(", check rate %u Hz"),tmp);
00279   }
00280   PRINTF("\n");
00281 
00282 #if UIP_CONF_IPV6_RPL
00283   PRINTF("RPL Enabled\n");
00284 #endif
00285 #if UIP_CONF_ROUTER
00286   PRINTF("Routing Enabled\n");
00287 #endif
00288 
00289 #endif /* ANNOUNCE_BOOT */
00290 
00291 // rime_init(rime_udp_init(NULL));
00292 // uip_router_register(&rimeroute);
00293 
00294   process_start(&tcpip_process, NULL);
00295 
00296 #else
00297 /* Original RF230 combined mac/radio driver */
00298 /* mac process must be started before tcpip process! */
00299   process_start(&mac_process, NULL);
00300   process_start(&tcpip_process, NULL);
00301 #endif /*RF230BB*/
00302 
00303 #ifdef RAVEN_LCD_INTERFACE
00304   process_start(&raven_lcd_process, NULL);
00305 #endif
00306 
00307   /* Autostart other processes */
00308   autostart_start(autostart_processes);
00309 
00310   //Give ourselves a prefix
00311   // init_net();
00312 
00313   /*---If using coffee file system create initial web content if necessary---*/
00314 #if COFFEE_FILES
00315   int fa = cfs_open( "/index.html", CFS_READ);
00316   if (fa<0) {     //Make some default web content
00317     PRINTF("No index.html file found, creating upload.html!\n");
00318     PRINTF("Formatting FLASH file system for coffee...");
00319     cfs_coffee_format();
00320     PRINTF("Done!\n");
00321     fa = cfs_open( "/index.html", CFS_WRITE);
00322     int r = cfs_write(fa, &"It works!", 9);
00323     if (r<0) PRINTF("Can''t create /index.html!\n");
00324     cfs_close(fa);
00325 //  fa = cfs_open("upload.html"), CFW_WRITE);
00326 // <html><body><form action="upload.html" enctype="multipart/form-data" method="post"><input name="userfile" type="file" size="50" /><input value="Upload" type="submit" /></form></body></html>
00327   }
00328 #endif /* COFFEE_FILES */
00329 
00330 /* Add addresses for testing */
00331 #if 0
00332 {  
00333   uip_ip6addr_t ipaddr;
00334   uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
00335   uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
00336 //  uip_ds6_prefix_add(&ipaddr,64,0);
00337 }
00338 #endif
00339 
00340 /*--------------------------Announce the configuration---------------------*/
00341 #if ANNOUNCE_BOOT
00342 
00343 #if WEBSERVER
00344   uint8_t i;
00345   char buf[80];
00346   unsigned int size;
00347 
00348   for (i=0;i<UIP_DS6_ADDR_NB;i++) {
00349         if (uip_ds6_if.addr_list[i].isused) {     
00350            httpd_cgi_sprint_ip6(uip_ds6_if.addr_list[i].ipaddr,buf);
00351        PRINTF("IPv6 Address: %s\n",buf);
00352         }
00353   }
00354    eeprom_read_block (buf,server_name, sizeof(server_name));
00355    buf[sizeof(server_name)]=0;
00356    PRINTF("%s",buf);
00357    eeprom_read_block (buf,domain_name, sizeof(domain_name));
00358    buf[sizeof(domain_name)]=0;
00359    size=httpd_fs_get_size();
00360 #ifndef COFFEE_FILES
00361    PRINTF(".%s online with fixed %u byte web content\n",buf,size);
00362 #elif COFFEE_FILES==1
00363    PRINTF(".%s online with static %u byte EEPROM file system\n",buf,size);
00364 #elif COFFEE_FILES==2
00365    PRINTF(".%s online with dynamic %u KB EEPROM file system\n",buf,size>>10);
00366 #elif COFFEE_FILES==3
00367    PRINTF(".%s online with static %u byte program memory file system\n",buf,size);
00368 #elif COFFEE_FILES==4
00369    PRINTF(".%s online with dynamic %u KB program memory file system\n",buf,size>>10);
00370 #endif /* COFFEE_FILES */
00371 
00372 #else
00373    PRINTF("Online\n");
00374 #endif /* WEBSERVER */
00375 
00376 #endif /* ANNOUNCE_BOOT */
00377 }
00378 
00379 #if RF230BB
00380 extern char rf230_interrupt_flag, rf230processflag;
00381 #endif
00382 
00383 /*-------------------------------------------------------------------------*/
00384 /*------------------------- Main Scheduler loop----------------------------*/
00385 /*-------------------------------------------------------------------------*/
00386 int
00387 main(void)
00388 {
00389   initialize();
00390 
00391   while(1) {
00392     process_run();
00393     watchdog_periodic();
00394 
00395 #if 0
00396 /* Various entry points for debugging in the AVR Studio simulator.
00397  * Set as next statement and step into the routine.
00398  */
00399     NETSTACK_RADIO.send(packetbuf_hdrptr(), 42);
00400     process_poll(&rf230_process);
00401     packetbuf_clear();
00402     len = rf230_read(packetbuf_dataptr(), PACKETBUF_SIZE);
00403     packetbuf_set_datalen(42);
00404     NETSTACK_RDC.input();
00405 #endif
00406 
00407 #if 0
00408 /* Clock.c can trigger a periodic PLL calibration in the RF230BB driver.
00409  * This can show when that happens.
00410  */
00411     extern uint8_t rf230_calibrated;
00412     if (rf230_calibrated) {
00413       PRINTF("\nRF230 calibrated!\n");
00414       rf230_calibrated=0;
00415     }
00416 #endif
00417 
00418 #if TESTRTIMER
00419 /* Timeout can be increased up to 8 seconds maximum.
00420  * A one second cycle is convenient for triggering the various debug printouts.
00421  * The triggers are staggered to avoid printing everything at once.
00422  * My raven is 6% slow.
00423  */
00424     if (rtimerflag) {
00425       rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL);
00426       rtimerflag=0;
00427 
00428 #if STAMPS
00429 if ((rtime%STAMPS)==0) {
00430   PRINTF("%us ",rtime);
00431 }
00432 #endif
00433       rtime+=1;
00434 
00435 #if PINGS
00436 if ((rtime%PINGS)==1) {
00437   PRINTF("**Ping\n");
00438   raven_ping6();
00439 }
00440 #endif
00441 
00442 #if ROUTES
00443 if ((rtime%ROUTES)==2) {
00444       
00445  //#if UIP_CONF_IPV6_RPL
00446 //#include "rpl.h"
00447 extern uip_ds6_nbr_t uip_ds6_nbr_cache[];
00448 extern uip_ds6_route_t uip_ds6_routing_table[];
00449 extern uip_ds6_netif_t uip_ds6_if;
00450 
00451   uint8_t i,j;
00452   PRINTF("\nAddresses [%u max]\n",UIP_DS6_ADDR_NB);
00453   for (i=0;i<UIP_DS6_ADDR_NB;i++) {
00454     if (uip_ds6_if.addr_list[i].isused) {         
00455       ipaddr_add(&uip_ds6_if.addr_list[i].ipaddr);
00456       PRINTF("\n");
00457     }
00458   }
00459   PRINTF("\nNeighbors [%u max]\n",UIP_DS6_NBR_NB);
00460   for(i = 0,j=1; i < UIP_DS6_NBR_NB; i++) {
00461     if(uip_ds6_nbr_cache[i].isused) {
00462       ipaddr_add(&uip_ds6_nbr_cache[i].ipaddr);
00463       PRINTF("\n");
00464       j=0;
00465     }
00466   }
00467   if (j) PRINTF("  <none>");
00468   PRINTF("\nRoutes [%u max]\n",UIP_DS6_ROUTE_NB);
00469   for(i = 0,j=1; i < UIP_DS6_ROUTE_NB; i++) {
00470     if(uip_ds6_routing_table[i].isused) {
00471       ipaddr_add(&uip_ds6_routing_table[i].ipaddr);
00472       PRINTF("/%u (via ", uip_ds6_routing_table[i].length);
00473       ipaddr_add(&uip_ds6_routing_table[i].nexthop);
00474  //     if(uip_ds6_routing_table[i].state.lifetime < 600) {
00475         PRINTF(") %lus\n", uip_ds6_routing_table[i].state.lifetime);
00476  //     } else {
00477  //       PRINTF(")\n");
00478  //     }
00479       j=0;
00480     }
00481   }
00482   if (j) PRINTF("  <none>");
00483   PRINTF("\n---------\n");
00484 }
00485 #endif
00486 
00487 #if STACKMONITOR
00488 if ((rtime%STACKMONITOR)==3) {
00489   extern uint16_t __bss_end;
00490   uint16_t p=(uint16_t)&__bss_end;
00491   do {
00492     if (*(uint16_t *)p != 0x4242) {
00493       PRINTF("Never-used stack > %d bytes\n",p-(uint16_t)&__bss_end);
00494       break;
00495     }
00496     p+=10;
00497   } while (p<RAMEND-10);
00498 }
00499 #endif
00500 
00501     }
00502 #endif /* TESTRTIMER */
00503 
00504 //Use with RF230BB DEBUGFLOW to show path through driver
00505 #if RF230BB&&0
00506 extern uint8_t debugflowsize,debugflow[];
00507   if (debugflowsize) {
00508     debugflow[debugflowsize]=0;
00509     PRINTF("%s",debugflow);
00510     debugflowsize=0;
00511    }
00512 #endif
00513 
00514 #if RF230BB&&0
00515     if (rf230processflag) {
00516       PRINTF("rf230p%d",rf230processflag);
00517       rf230processflag=0;
00518     }
00519 #endif
00520 
00521 #if RF230BB&&0
00522     if (rf230_interrupt_flag) {
00523  //   if (rf230_interrupt_flag!=11) {
00524         PRINTF("**RI%u",rf230_interrupt_flag);
00525  //   }
00526       rf230_interrupt_flag=0;
00527     }
00528 #endif
00529   }
00530   return 0;
00531 }
00532 
00533 /*---------------------------------------------------------------------------*/
00534 
00535 void log_message(char *m1, char *m2)
00536 {
00537   PRINTF("%s%s\n", m1, m2);
00538 }
00539 
00540 #if ROUTES
00541 static void
00542 ipaddr_add(const uip_ipaddr_t *addr)
00543 {
00544   uint16_t a;
00545   int8_t i, f;
00546   for(i = 0, f = 0; i < sizeof(uip_ipaddr_t); i += 2) {
00547     a = (addr->u8[i] << 8) + addr->u8[i + 1];
00548     if(a == 0 && f >= 0) {
00549       if(f++ == 0) PRINTF("::");
00550     } else {
00551       if(f > 0) {
00552         f = -1;
00553       } else if(i > 0) {
00554         PRINTF(":");
00555       }
00556       PRINTF("%x",a);
00557     }
00558   }
00559 }
00560 #endif

Generated on Mon Apr 11 14:23:42 2011 for Contiki 2.5 by  doxygen 1.6.1