Contiki 2.6

contiki-main.c

00001 #include "contiki.h"
00002 #include "soc.h"
00003 #include "sys/clock.h"
00004 #include "sys/autostart.h"
00005 #include "dev/serial-line.h"
00006 #include "dev/slip.h"
00007 #include "dev/leds.h"
00008 #include "dev/uart0.h"
00009 #include "dev/dma.h"
00010 #include "dev/cc2530-rf.h"
00011 #include "dev/watchdog.h"
00012 #include "dev/clock-isr.h"
00013 #include "dev/lpm.h"
00014 #include "dev/button-sensor.h"
00015 #include "dev/adc-sensor.h"
00016 #include "dev/leds-arch.h"
00017 #include "net/rime.h"
00018 #include "net/netstack.h"
00019 #include "net/mac/frame802154.h"
00020 #include "debug.h"
00021 #include "cc253x.h"
00022 #include "sfr-bits.h"
00023 #include "contiki-lib.h"
00024 #include "contiki-net.h"
00025 /*---------------------------------------------------------------------------*/
00026 #if VIZTOOL_CONF_ON
00027 PROCESS_NAME(viztool_process);
00028 #endif
00029 /*---------------------------------------------------------------------------*/
00030 #if STARTUP_CONF_VERBOSE
00031 #define PUTSTRING(...) putstring(__VA_ARGS__)
00032 #define PUTHEX(...) puthex(__VA_ARGS__)
00033 #define PUTBIN(...) putbin(__VA_ARGS__)
00034 #define PUTCHAR(...) putchar(__VA_ARGS__)
00035 #else
00036 #define PUTSTRING(...)
00037 #define PUTHEX(...)
00038 #define PUTBIN(...)
00039 #define PUTCHAR(...)
00040 #endif
00041 /*---------------------------------------------------------------------------*/
00042 #if CLOCK_CONF_STACK_FRIENDLY
00043 extern volatile __bit sleep_flag;
00044 #endif
00045 /*---------------------------------------------------------------------------*/
00046 extern rimeaddr_t rimeaddr_node_addr;
00047 static __data int r;
00048 static __data int len;
00049 /*---------------------------------------------------------------------------*/
00050 #if ENERGEST_CONF_ON
00051 static unsigned long irq_energest = 0;
00052 #define ENERGEST_IRQ_SAVE(a) do { \
00053     a = energest_type_time(ENERGEST_TYPE_IRQ); } while(0)
00054 #define ENERGEST_IRQ_RESTORE(a) do { \
00055     energest_type_set(ENERGEST_TYPE_IRQ, a); } while(0)
00056 #else
00057 #define ENERGEST_IRQ_SAVE(a) do {} while(0)
00058 #define ENERGEST_IRQ_RESTORE(a) do {} while(0)
00059 #endif
00060 /*---------------------------------------------------------------------------*/
00061 static void
00062 fade(int l) CC_NON_BANKED
00063 {
00064   volatile int i, a;
00065   int k, j;
00066   for(k = 0; k < 400; ++k) {
00067     j = k > 200? 400 - k: k;
00068 
00069     leds_on(l);
00070     for(i = 0; i < j; ++i) {
00071       a = i;
00072     }
00073     leds_off(l);
00074     for(i = 0; i < 200 - j; ++i) {
00075       a = i;
00076     }
00077   }
00078 }
00079 /*---------------------------------------------------------------------------*/
00080 static void
00081 set_rime_addr(void) CC_NON_BANKED
00082 {
00083   char i;
00084 
00085 #if CC2530_CONF_MAC_FROM_PRIMARY
00086   __xdata unsigned char * macp = &X_IEEE_ADDR;
00087 #else
00088   __code unsigned char * macp = (__code unsigned char *) 0xFFE8;
00089 #endif
00090 
00091   PUTSTRING("Rime is 0x");
00092   PUTHEX(sizeof(rimeaddr_t));
00093   PUTSTRING(" bytes long\n");
00094 
00095 #if CC2530_CONF_MAC_FROM_PRIMARY
00096   PUTSTRING("Reading MAC from Info Page\n");
00097 #else
00098   PUTSTRING("Reading MAC from flash\n");
00099 
00100   /*
00101    * The MAC is always stored in 0xFFE8 of the highest BANK of our flash. This
00102    * maps to address 0xFFF8 of our CODE segment, when this BANK is selected.
00103    * Load the bank, read 8 bytes starting at 0xFFE8 and restore last BANK.
00104    * Since we are called from main(), this MUST be BANK1 or something is very
00105    * wrong. This code can be used even without a bankable firmware.
00106    */
00107 
00108   /* Don't interrupt us to make sure no BANK switching happens while working */
00109   DISABLE_INTERRUPTS();
00110 
00111   /* Switch to the BANKn,
00112    * map CODE: 0x8000 - 0xFFFF to FLASH: 0xn8000 - 0xnFFFF */
00113   FMAP = CC2530_LAST_FLASH_BANK;
00114 #endif
00115 
00116   for(i = (RIMEADDR_SIZE - 1); i >= 0; --i) {
00117     rimeaddr_node_addr.u8[i] = *macp;
00118     macp++;
00119   }
00120 
00121 #if !CC2530_CONF_MAC_FROM_PRIMARY
00122   /* Remap 0x8000 - 0xFFFF to BANK1 */
00123   FMAP = 1;
00124   ENABLE_INTERRUPTS();
00125 #endif
00126 
00127   /* Now the address is stored MSB first */
00128 #if STARTUP_CONF_VERBOSE
00129   PUTSTRING("Rime configured with address ");
00130   for(i = 0; i < RIMEADDR_SIZE - 1; i++) {
00131     PUTHEX(rimeaddr_node_addr.u8[i]);
00132     PUTCHAR(':');
00133   }
00134   PUTHEX(rimeaddr_node_addr.u8[i]);
00135   PUTCHAR('\n');
00136 #endif
00137 
00138   cc2530_rf_set_addr(IEEE802154_PANID);
00139   return;
00140 }
00141 /*---------------------------------------------------------------------------*/
00142 int
00143 main(void) CC_NON_BANKED
00144 {
00145   /* Hardware initialization */
00146   clock_init();
00147   soc_init();
00148   rtimer_init();
00149 
00150   /* Init LEDs here */
00151   leds_init();
00152   leds_off(LEDS_ALL);
00153   fade(LEDS_GREEN);
00154 
00155   /* initialize process manager. */
00156   process_init();
00157 
00158   /* Init UART */
00159   uart0_init();
00160 
00161 #if DMA_ON
00162   dma_init();
00163 #endif
00164 
00165 #if SLIP_ARCH_CONF_ENABLE
00166   slip_arch_init(0);
00167 #else
00168   uart0_set_input(serial_line_input_byte);
00169   serial_line_init();
00170 #endif
00171   fade(LEDS_RED);
00172 
00173   PUTSTRING("##########################################\n");
00174   putstring(CONTIKI_VERSION_STRING "\n");
00175   putstring("TI SmartRF05 EB\n");
00176   switch(CHIPID) {
00177   case 0xA5:
00178     putstring("cc2530");
00179     break;
00180   case 0xB5:
00181     putstring("cc2531");
00182     break;
00183   case 0x95:
00184     putstring("cc2533");
00185     break;
00186   case 0x8D:
00187     putstring("cc2540");
00188     break;
00189   }
00190 
00191   putstring("-" CC2530_FLAVOR_STRING ", ");
00192   puthex(CHIPINFO1 + 1);
00193   putstring("KB SRAM\n");
00194 
00195   PUTSTRING("\nSDCC Build:\n");
00196 #if STARTUP_CONF_VERBOSE
00197 #ifdef HAVE_SDCC_BANKING
00198   PUTSTRING("  With Banking.\n");
00199 #endif /* HAVE_SDCC_BANKING */
00200 #ifdef SDCC_MODEL_LARGE
00201   PUTSTRING("  --model-large\n");
00202 #endif /* SDCC_MODEL_LARGE */
00203 #ifdef SDCC_MODEL_HUGE
00204   PUTSTRING("  --model-huge\n");
00205 #endif /* SDCC_MODEL_HUGE */
00206 #ifdef SDCC_STACK_AUTO
00207   PUTSTRING("  --stack-auto\n");
00208 #endif /* SDCC_STACK_AUTO */
00209 
00210   PUTCHAR('\n');
00211 
00212   PUTSTRING(" Net: ");
00213   PUTSTRING(NETSTACK_NETWORK.name);
00214   PUTCHAR('\n');
00215   PUTSTRING(" MAC: ");
00216   PUTSTRING(NETSTACK_MAC.name);
00217   PUTCHAR('\n');
00218   PUTSTRING(" RDC: ");
00219   PUTSTRING(NETSTACK_RDC.name);
00220   PUTCHAR('\n');
00221 
00222   PUTSTRING("##########################################\n");
00223 #endif
00224 
00225   watchdog_init();
00226 
00227   /* Initialise the H/W RNG engine. */
00228   random_init(0);
00229 
00230   /* start services */
00231   process_start(&etimer_process, NULL);
00232   ctimer_init();
00233 
00234   /* initialize the netstack */
00235   netstack_init();
00236   set_rime_addr();
00237 
00238 #if BUTTON_SENSOR_ON || ADC_SENSOR_ON
00239   process_start(&sensors_process, NULL);
00240   BUTTON_SENSOR_ACTIVATE();
00241   ADC_SENSOR_ACTIVATE();
00242 #endif
00243 
00244 #if UIP_CONF_IPV6
00245   memcpy(&uip_lladdr.addr, &rimeaddr_node_addr, sizeof(uip_lladdr.addr));
00246   queuebuf_init();
00247   process_start(&tcpip_process, NULL);
00248 #endif /* UIP_CONF_IPV6 */
00249 
00250 #if VIZTOOL_CONF_ON
00251   process_start(&viztool_process, NULL);
00252 #endif
00253 
00254   energest_init();
00255   ENERGEST_ON(ENERGEST_TYPE_CPU);
00256 
00257   autostart_start(autostart_processes);
00258 
00259   watchdog_start();
00260 
00261   fade(LEDS_YELLOW);
00262 
00263   while(1) {
00264     do {
00265       /* Reset watchdog and handle polls and events */
00266       watchdog_periodic();
00267 
00268 #if CLOCK_CONF_STACK_FRIENDLY
00269       if(sleep_flag) {
00270         if(etimer_pending() &&
00271             (etimer_next_expiration_time() - clock_time() - 1) > MAX_TICKS) {
00272           etimer_request_poll();
00273         }
00274         sleep_flag = 0;
00275       }
00276 #endif
00277       r = process_run();
00278     } while(r > 0);
00279     len = NETSTACK_RADIO.pending_packet();
00280     if(len) {
00281       packetbuf_clear();
00282       len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE);
00283       if(len > 0) {
00284         packetbuf_set_datalen(len);
00285         NETSTACK_RDC.input();
00286       }
00287     }
00288 
00289 #if LPM_MODE
00290 #if (LPM_MODE==LPM_MODE_PM2)
00291     SLEEP &= ~OSC_PD;            /* Make sure both HS OSCs are on */
00292     while(!(SLEEP & HFRC_STB));  /* Wait for RCOSC to be stable */
00293     CLKCON |= OSC;               /* Switch to the RCOSC */
00294     while(!(CLKCON & OSC));      /* Wait till it's happened */
00295     SLEEP |= OSC_PD;             /* Turn the other one off */
00296 #endif /* LPM_MODE==LPM_MODE_PM2 */
00297 
00298     /*
00299      * Set MCU IDLE or Drop to PM1. Any interrupt will take us out of LPM
00300      * Sleep Timer will wake us up in no more than 7.8ms (max idle interval)
00301      */
00302     SLEEPCMD = (SLEEPCMD & 0xFC) | (LPM_MODE - 1);
00303 
00304 #if (LPM_MODE==LPM_MODE_PM2)
00305     /*
00306      * Wait 3 NOPs. Either an interrupt occurred and SLEEP.MODE was cleared or
00307      * no interrupt occurred and we can safely power down
00308      */
00309     __asm
00310       nop
00311       nop
00312       nop
00313     __endasm;
00314 
00315     if(SLEEPCMD & SLEEP_MODE0) {
00316 #endif /* LPM_MODE==LPM_MODE_PM2 */
00317 
00318       ENERGEST_OFF(ENERGEST_TYPE_CPU);
00319       ENERGEST_ON(ENERGEST_TYPE_LPM);
00320 
00321       /* We are only interested in IRQ energest while idle or in LPM */
00322       ENERGEST_IRQ_RESTORE(irq_energest);
00323 
00324       /* Go IDLE or Enter PM1 */
00325       PCON |= PCON_IDLE;
00326 
00327       /* First instruction upon exiting PM1 must be a NOP */
00328       __asm
00329         nop
00330       __endasm;
00331 
00332       /* Remember energest IRQ for next pass */
00333       ENERGEST_IRQ_SAVE(irq_energest);
00334 
00335       ENERGEST_ON(ENERGEST_TYPE_CPU);
00336       ENERGEST_OFF(ENERGEST_TYPE_LPM);
00337 
00338 #if (LPM_MODE==LPM_MODE_PM2)
00339       SLEEPCMD &= ~SLEEP_OSC_PD;            /* Make sure both HS OSCs are on */
00340       while(!(SLEEPCMD & SLEEP_XOSC_STB));  /* Wait for XOSC to be stable */
00341       CLKCONCMD &= ~CLKCONCMD_OSC;              /* Switch to the XOSC */
00342       /*
00343        * On occasion the XOSC is reported stable when in reality it's not.
00344        * We need to wait for a safeguard of 64us or more before selecting it
00345        */
00346       clock_delay_usec(65);
00347       while(CLKCONCMD & CLKCONCMD_OSC);         /* Wait till it's happened */
00348     }
00349 #endif /* LPM_MODE==LPM_MODE_PM2 */
00350 #endif /* LPM_MODE */
00351   }
00352 }
00353 /*---------------------------------------------------------------------------*/