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