void tmr0_isr(void) { if(bit_is_set(*TMR(0,CSCTRL),TCF1)) { current_clock++; if((current_clock % CLOCK_CONF_SECOND) == 0) { seconds++; /* ADC can be serviced every tick or every second */ #if CLOCK_CONF_SAMPLEADC > 1 adc_service(); #endif } #if CLOCK_CONF_SAMPLEADC == 1 adc_service(); #endif if(etimer_pending() && (etimer_next_expiration_time() - current_clock - 1) > MAX_TICKS) { etimer_request_poll(); } /* clear the compare flags */ clear_bit(*TMR(0,SCTRL),TCF); clear_bit(*TMR(0,CSCTRL),TCF1); clear_bit(*TMR(0,CSCTRL),TCF2); return; } else { /* this timer didn't create an interrupt condition */ return; } }
Java_se_sics_cooja_corecomm_[CLASS_NAME]_tick(JNIEnv *env, jobject obj) { /* Let all simulation interfaces act first */ simNoYield = 1; doActionsBeforeTick(); simNoYield = 0; /* Poll etimer process */ if (etimer_pending()) { etimer_request_poll(); } /* Let Contiki handle a few events. This call stores the process_run() return value */ cooja_mt_exec(&process_run_thread); /* Let all simulation interfaces act before returning to java */ simNoYield = 1; doActionsAfterTick(); simNoYield = 0; /* Look for new e-timers */ simEtimerPending = etimer_pending(); /* Save nearest event timer expiration time */ if (simEtimerPending) { simNextExpirationTime = etimer_next_expiration_time() - simCurrentTime; } }
Java_se_sics_cooja_corecomm_[CLASS_NAME]_tick(JNIEnv *env, jobject obj) { /* Let all simulation interfaces act first */ simNoYield = 1; doActionsBeforeTick(); simNoYield = 0; /* Check if any e-timers are pending (save result for state decisions) */ if (etimer_pending()) { /* Poll etimers */ etimer_request_poll(); simEtimerPending = 1; } else { simEtimerPending = 0; } /* Let Contiki execute one or a part of the process_run()-function via the thread. This call stores the process_run() return value */ cooja_mt_exec(&process_run_thread); /* Let all simulation interfaces act before returning to java */ simNoYield = 1; doActionsAfterTick(); simNoYield = 0; /* Look for new e-timers */ if (!simEtimerPending && etimer_pending()) { /* Poll etimers */ etimer_request_poll(); simEtimerPending = 1; } /* Save nearest event timer expiration time (0 if no timers) */ simNextExpirationTime = etimer_next_expiration_time(); }
void tmr3_isr(void) { if(bit_is_set(*TMR(3,CSCTRL),TCF1)) { current_clock++; if((current_clock % CLOCK_CONF_SECOND) == 0) { seconds++; #if BLINK_SECONDS leds_toggle(LEDS_GREEN); #endif } if(etimer_pending() && (etimer_next_expiration_time() - current_clock - 1) > MAX_TICKS) { etimer_request_poll(); } /* clear the compare flags */ clear_bit(*TMR(3,SCTRL),TCF); clear_bit(*TMR(3,CSCTRL),TCF1); clear_bit(*TMR(3,CSCTRL),TCF2); return; } else { /* this timer didn't create an interrupt condition */ return; } }
/*---------------------------------------------------------------------------*/ int main(void) { printf("Starting Contiki\n"); process_init(); ctimer_init(); netstack_init(); procinit_init(); serial_line_init(); autostart_start(autostart_processes); /* Make standard output unbuffered. */ setvbuf(stdout, (char *)NULL, _IONBF, 0); while(1) { fd_set fds; int n; struct timeval tv; clock_time_t next_event; n = process_run(); next_event = etimer_next_expiration_time()-clock_time(); #if DEBUG_SLEEP if(n > 0) { printf("%d events pending\n",n); } else { printf("next event: T-%.03f\n",(double)next_event/(double)CLOCK_SECOND); } #endif if(next_event>CLOCK_SECOND*2) next_event = CLOCK_SECOND*2; tv.tv_sec = n?0:next_event/CLOCK_SECOND; tv.tv_usec = n?0:next_event%1000*1000; FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); select(1, &fds, NULL, NULL, &tv); if(FD_ISSET(STDIN_FILENO, &fds)) { char c; if(read(STDIN_FILENO, &c, 1) > 0) { serial_line_input_byte(c); } } etimer_request_poll(); } return 0; }
// alarm timer interrupt handler ALARM_TIMER_INTERRUPT() { // read & unset the highest bit volatile uint16_t x = TIMER_INTERRUPT_VECTOR; (void) x; if (isInSleepMode) { // wakeup and return EXIT_SLEEP_MODE(); return; } uint16_t tar = ALARM_TIMER_READ(); // Advance jiffies (MansOS time counter) while counter register <= counter // Spurios interrupts may happen when the alarm timer is restarted after stopping! while (!timeAfter16(ALARM_TIMER_REGISTER, tar)) { jiffies += JIFFY_TIMER_MS; ALARM_TIMER_REGISTER += PLATFORM_ALARM_TIMER_PERIOD; } #if PLATFORM_HAS_CORRECTION_TIMER // // On MSP430 platforms binary ACLK oscillator usually is used. // It has constant rate 32768 Hz (the ACLK_SPEED define) // When ACLK ticks are converted to milliseconds, rounding error is introduced. // When TIMER_INTERRUPT_HZ = 1000, there are 32 ACLK ticks per millisecond; // The clock error is (32768 / 32) - 1000 = 1024 - 1000 = 24 milliseconds. // We improve the precision by applying a fix 24/3 = 8 times per second. // while (!timeAfter16(CORRECTION_TIMER_REGISTER, tar)) { CORRECTION_TIMER_REGISTER += PLATFORM_TIME_CORRECTION_PERIOD; jiffies -= 3; } #endif #ifdef USE_ALARMS if (hasAnyReadyAlarms(jiffies)) { alarmsProcess(); } #endif #ifdef USE_PROTOTHREADS if (etimer_pending() && !etimer_polled() && !timeAfter32(jiffies, etimer_next_expiration_time())) { etimer_request_poll(); EXIT_SLEEP_MODE(); } #endif // If TAR still > TACCR0 at this point, we are in trouble: // the interrupt will not be generated until the next wraparound (2 seconds). // So avoid it at all costs. while (!timeAfter16(ALARM_TIMER_REGISTER, ALARM_TIMER_READ() + 2)) { jiffies += JIFFY_TIMER_MS; ALARM_TIMER_REGISTER += PLATFORM_ALARM_TIMER_PERIOD; } }
void SysTick_handler(void) { (void)SysTick->CTRL; SCB->ICSR = SCB_ICSR_PENDSTCLR; current_clock++; if(etimer_pending() && etimer_next_expiration_time() <= current_clock) { etimer_request_poll(); } if (--second_countdown == 0) { current_seconds++; second_countdown = CLOCK_SECOND; } }
/*---------------------------------------------------------------------------*/ interrupt(TIMERA1_VECTOR) timera1 (void) { ENERGEST_ON(ENERGEST_TYPE_IRQ); if(TAIV == 2) { etimer_interrupt(); if(etimer_pending() && (etimer_next_expiration_time() - count - 1) > MAX_TICKS) { etimer_request_poll(); LPM4_EXIT; } } ENERGEST_OFF(ENERGEST_TYPE_IRQ); }
/*---------------------------------------------------------------------------*/ ISR(TIMERA1, timera1) { ENERGEST_ON(ENERGEST_TYPE_IRQ); watchdog_start(); if(TAIV == 2) { /* HW timer bug fix: Interrupt handler called before TR==CCR. * Occurs when timer state is toggled between STOP and CONT. */ while(TACTL & MC1 && TACCR1 - TAR == 1); /* Make sure interrupt time is future */ do { TACCR1 += INTERVAL; ++count; /* Make sure the CLOCK_CONF_SECOND is a power of two, to ensure that the modulo operation below becomes a logical and and not an expensive divide. Algorithm from Wikipedia: http://en.wikipedia.org/wiki/Power_of_two */ #if (CLOCK_CONF_SECOND & (CLOCK_CONF_SECOND - 1)) != 0 #error CLOCK_CONF_SECOND must be a power of two (i.e., 1, 2, 4, 8, 16, 32, 64, ...). #error Change CLOCK_CONF_SECOND in contiki-conf.h. #endif if(count % CLOCK_CONF_SECOND == 0) { ++seconds; energest_flush(); } } while((TACCR1 - TAR) > INTERVAL); last_tar = TAR; if(etimer_pending() && (etimer_next_expiration_time() - count - 1) > MAX_TICKS) { etimer_request_poll(); LPM4_EXIT; } } /* if(process_nevents() >= 0) { LPM4_EXIT; }*/ watchdog_stop(); ENERGEST_OFF(ENERGEST_TYPE_IRQ); }
static void clock_alarm(handler_arg_t arg) { (void)arg; clock_cnt ++; clock_sec_cnt ++; if (etimer_pending() && etimer_next_expiration_time() <= clock_cnt) { etimer_request_poll(); } if (clock_sec_cnt == CLOCK_SECOND) { clock_sec ++; clock_sec_cnt = 0; } }
void SysTick_Handler(void) { INT_Disable( ); current_clock++; if(etimer_pending() && etimer_next_expiration_time() <= current_clock) { etimer_request_poll(); } if (--second_countdown == 0) { current_seconds++; second_countdown = CLOCK_SECOND; } INT_Enable( ); }
/** * \brief Let mote execute one "block" of code (tick mote). * * Let mote defined by the active contiki processes and current * process memory execute some program code. This code must not block * or else this function will never return. A typical contiki * process will return when it executes PROCESS_WAIT..() statements. * * Before the control is left to contiki processes, any messages * from the Java part are handled. These may for example be * incoming network data. After the contiki processes return control, * messages to the Java part are also handled (those which may need * special attention). * * This is a JNI function and should only be called via the * responsible Java part (MoteType.java). */ JNIEXPORT void JNICALL Java_org_contikios_cooja_corecomm_CLASSNAME_tick(JNIEnv *env, jobject obj) { clock_time_t nextEtimer; rtimer_clock_t nextRtimer; simProcessRunValue = 0; /* Let all simulation interfaces act first */ doActionsBeforeTick(); /* Poll etimer process */ if (etimer_pending()) { etimer_request_poll(); } /* Let rtimers run. * Sets simProcessRunValue */ cooja_mt_exec(&rtimer_thread); if(simProcessRunValue == 0) { /* Rtimers done: Let Contiki handle a few events. * Sets simProcessRunValue */ cooja_mt_exec(&process_run_thread); } /* Let all simulation interfaces act before returning to java */ doActionsAfterTick(); /* Do we have any pending timers */ simEtimerPending = etimer_pending() || rtimer_arch_pending(); if(!simEtimerPending) { return; } /* Save nearest expiration time */ nextEtimer = etimer_next_expiration_time() - (clock_time_t) simCurrentTime; nextRtimer = rtimer_arch_next() - (rtimer_clock_t) simCurrentTime; if(etimer_pending() && rtimer_arch_pending()) { simNextExpirationTime = MIN(nextEtimer, nextRtimer); } else if (etimer_pending()) { simNextExpirationTime = nextEtimer; } else if (rtimer_arch_pending()) { simNextExpirationTime = nextRtimer; } }
/*---------------------------------------------------------------------------*/ interrupt(TIMERA1_VECTOR) timera1 (void) { ENERGEST_ON(ENERGEST_TYPE_IRQ); int taiv = TAIV; if(taiv == 2) { etimer_interrupt(); if(etimer_pending() && (etimer_next_expiration_time() - count - 1) > MAX_TICKS) { etimer_request_poll(); LPM4_EXIT; } } else { if (taiv == TAIV_TACCR2) { radio_abort_rx(); LPM4_EXIT; } } ENERGEST_OFF(ENERGEST_TYPE_IRQ); }
void SimluateRun(CuTest* tc) { /* * Initialize Contiki and our processes. */ process_init(); process_start(&etimer_process, NULL); ctimer_init(); energest_init(); ENERGEST_ON(ENERGEST_TYPE_CPU); window_init(0xff); autostart_start(autostart_processes); process_start(&event_process, NULL); while(run) { int r; do { /* Reset watchdog. */ r = process_run(); } while(r > 0); #if 0 int n = etimer_next_expiration_time(); if (n > 0) { int p = n - clock_time(); if (p > 0) nanosleep(p); } else { nanosleep(1000); } #endif etimer_request_poll(); } }
/*---------------------------------------------------------------------------*/ int main(void) { /* Hardware initialization */ bus_init();//ʱÖÓ³õʼ»¯ rtimer_init();//¼ÆʱÆ÷³õʼ»¯ /* model-specific h/w init. */ io_port_init(); /* Init LEDs here */ leds_init();//LED³õʼ»¯ /*LEDS_GREEN indicate LEDs Init finished*/ fade(LEDS_GREEN); /* initialize process manager. */ process_init();//½ø³Ì¹ÜÀí³õʼ»¯ /* Init UART0 * Based on the EJOY MCU CC2430 Circuit Design * */ uart0_init();//UART0´®¿Ú³õʼ»¯ #if DMA_ON dma_init();//DMA³õʼ»¯ #endif #if SLIP_ARCH_CONF_ENABLE /* On cc2430, the argument is not used */ slip_arch_init(0);//SLIP³õʼ»¯ #else uart1_set_input(serial_line_input_byte); serial_line_init(); #endif PUTSTRING("##########################################\n"); putstring(CONTIKI_VERSION_STRING "\n"); // putstring(SENSINODE_MODEL " (CC24"); puthex(((CHIPID >> 3) | 0x20)); putstring("-" FLASH_SIZE ")\n"); #if STARTUP_VERBOSE #ifdef HAVE_SDCC_BANKING PUTSTRING(" With Banking.\n"); #endif /* HAVE_SDCC_BANKING */ #ifdef SDCC_MODEL_LARGE PUTSTRING(" --model-large\n"); #endif /* SDCC_MODEL_LARGE */ #ifdef SDCC_MODEL_HUGE PUTSTRING(" --model-huge\n"); #endif /* SDCC_MODEL_HUGE */ #ifdef SDCC_STACK_AUTO PUTSTRING(" --stack-auto\n"); #endif /* SDCC_STACK_AUTO */ PUTCHAR('\n'); PUTSTRING(" Net: "); PUTSTRING(NETSTACK_NETWORK.name); PUTCHAR('\n'); PUTSTRING(" MAC: "); PUTSTRING(NETSTACK_MAC.name); PUTCHAR('\n'); PUTSTRING(" RDC: "); PUTSTRING(NETSTACK_RDC.name); PUTCHAR('\n'); PUTSTRING("##########################################\n"); #endif watchdog_init();//¿´ÃŹ·³õʼ»¯ /* Initialise the cc2430 RNG engine. */ random_init(0);//Ëæ»úÊýÉú³ÉÆ÷³õʼ»¯ /* start services */ process_start(&etimer_process, NULL);// ctimer_init();//ctimer³õʼ»¯ /* initialize the netstack */ netstack_init();//ÍøÂçµ×²ãÕ»³õʼ»¯ set_rime_addr();//rimeµØÖ·ÉèÖà //there is no sensor for us maintenance #if BUTTON_SENSOR_ON || ADC_SENSOR_ON process_start(&sensors_process, NULL); sensinode_sensors_activate(); #endif //IPV6,YES! #if UIP_CONF_IPV6 memcpy(&uip_lladdr.addr, &rimeaddr_node_addr, sizeof(uip_lladdr.addr)); queuebuf_init(); process_start(&tcpip_process, NULL); //DISCO #if DISCO_ENABLED process_start(&disco_process, NULL); #endif /* DISCO_ENABLED */ //VIZTOOL #if VIZTOOL_CONF_ON process_start(&viztool_process, NULL); #endif #if (!UIP_CONF_IPV6_RPL) { uip_ipaddr_t ipaddr; uip_ip6addr(&ipaddr, 0x2001, 0x630, 0x301, 0x6453, 0, 0, 0, 0); uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); } #endif /* UIP_CONF_IPV6_RPL */ #endif /* UIP_CONF_IPV6 */ /* * Acknowledge the UART1 RX interrupt * now that we're sure we are ready to process it * * We don't need it. by MW */ // model_uart_intr_en(); energest_init(); ENERGEST_ON(ENERGEST_TYPE_CPU); fade(LEDS_RED); #if BATMON_CONF_ON process_start(&batmon_process, NULL); #endif autostart_start(autostart_processes); watchdog_start(); while(1) { do { /* Reset watchdog and handle polls and events */ watchdog_periodic(); /**/ #if !CLOCK_CONF_ACCURATE if(sleep_flag) { if(etimer_pending() && (etimer_next_expiration_time() - count - 1) > MAX_TICKS) { /*core/sys/etimer.c*/ etimer_request_poll(); } sleep_flag = 0; } #endif r = process_run(); } while(r > 0); #if SHORTCUTS_CONF_NETSTACK len = NETSTACK_RADIO.pending_packet(); if(len) { packetbuf_clear(); len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE); if(len > 0) { packetbuf_set_datalen(len); NETSTACK_RDC.input(); } } #endif #if LPM_MODE #if (LPM_MODE==LPM_MODE_PM2) SLEEP &= ~OSC_PD; /* Make sure both HS OSCs are on */ while(!(SLEEP & HFRC_STB)); /* Wait for RCOSC to be stable */ CLKCON |= OSC; /* Switch to the RCOSC */ while(!(CLKCON & OSC)); /* Wait till it's happened */ SLEEP |= OSC_PD; /* Turn the other one off */ #endif /* LPM_MODE==LPM_MODE_PM2 */ /* * Set MCU IDLE or Drop to PM1. Any interrupt will take us out of LPM * Sleep Timer will wake us up in no more than 7.8ms (max idle interval) */ SLEEP = (SLEEP & 0xFC) | (LPM_MODE - 1); #if (LPM_MODE==LPM_MODE_PM2) /* * Wait 3 NOPs. Either an interrupt occurred and SLEEP.MODE was cleared or * no interrupt occurred and we can safely power down */ __asm nop nop nop __endasm; if (SLEEP & SLEEP_MODE0) { #endif /* LPM_MODE==LPM_MODE_PM2 */ ENERGEST_OFF(ENERGEST_TYPE_CPU); ENERGEST_ON(ENERGEST_TYPE_LPM); /* We are only interested in IRQ energest while idle or in LPM */ ENERGEST_IRQ_RESTORE(irq_energest); /* Go IDLE or Enter PM1 */ PCON |= IDLE; /* First instruction upon exiting PM1 must be a NOP */ __asm nop __endasm; /* Remember energest IRQ for next pass */ ENERGEST_IRQ_SAVE(irq_energest); ENERGEST_ON(ENERGEST_TYPE_CPU); ENERGEST_OFF(ENERGEST_TYPE_LPM); #if (LPM_MODE==LPM_MODE_PM2) SLEEP &= ~OSC_PD; /* Make sure both HS OSCs are on */ while(!(SLEEP & XOSC_STB)); /* Wait for XOSC to be stable */ CLKCON &= ~OSC; /* Switch to the XOSC */ /* * On occasion the XOSC is reported stable when in reality it's not. * We need to wait for a safeguard of 64us or more before selecting it */ clock_delay(10); while(CLKCON & OSC); /* Wait till it's happened */ } #endif /* LPM_MODE==LPM_MODE_PM2 */ #endif /* LPM_MODE */ } }
/*---------------------------------------------------------------------------*/ int main(void) { clock_init(); #if UIP_CONF_IPV6 /* A hard coded address overrides the stack default MAC address to allow multiple instances. uip6.c defines it as {0x00,0x06,0x98,0x00,0x02,0x32} giving an ipv6 address of [fe80::206:98ff:fe00:232] We make it simpler, {0x02,0x00,0x00 + the last three bytes of the hard coded address (if any are nonzero). HARD_CODED_ADDRESS can be defined in the contiki-conf.h file, or here to allow quick builds using different addresses. If HARD_CODED_ADDRESS has a prefix it also applied, unless built as a RPL end node. E.g. bbbb::12:3456 becomes fe80::ff:fe12:3456 and prefix bbbb::/64 if non-RPL ::10 becomes fe80::ff:fe00:10 and prefix awaits RA or RPL formation bbbb:: gives an address of bbbb::206:98ff:fe00:232 if non-RPL */ #ifdef HARD_CODED_ADDRESS { uip_ipaddr_t ipaddr; uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr); if((ipaddr.u8[13] != 0) || (ipaddr.u8[14] != 0) || (ipaddr.u8[15] != 0)) { if(sizeof(uip_lladdr) == 6) { /* Minimal-net uses ethernet MAC */ uip_lladdr.addr[0] = 0x02; uip_lladdr.addr[1] = 0; uip_lladdr.addr[2] = 0; uip_lladdr.addr[3] = ipaddr.u8[13]; uip_lladdr.addr[4] = ipaddr.u8[14]; uip_lladdr.addr[5] = ipaddr.u8[15]; } } } #endif /* HARD_CODED_ADDRESS */ #endif /* UIP_CONF_IPV6 */ process_init(); /* procinit_init initializes RPL which sets a ctimer for the first DIS */ /* We must start etimers and ctimers,before calling it */ process_start(&etimer_process, NULL); ctimer_init(); #if RPL_BORDER_ROUTER process_start(&border_router_process, NULL); printf("Border Router Process started\n"); #elif UIP_CONF_IPV6_RPL printf("RPL enabled\n"); #endif procinit_init(); autostart_start(autostart_processes); /* Set default IP addresses if not specified */ #if !UIP_CONF_IPV6 { uip_ipaddr_t addr; uip_gethostaddr(&addr); if(addr.u8[0] == 0) { uip_ipaddr(&addr, 172,18,0,2); } printf("IP Address: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr)); uip_sethostaddr(&addr); uip_getnetmask(&addr); if(addr.u8[0] == 0) { uip_ipaddr(&addr, 255,255,0,0); uip_setnetmask(&addr); } printf("Subnet Mask: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr)); uip_getdraddr(&addr); if(addr.u8[0] == 0) { uip_ipaddr(&addr, 172,18,0,1); uip_setdraddr(&addr); } printf("Def. Router: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr)); } #else /* UIP_CONF_IPV6 */ #if !UIP_CONF_IPV6_RPL { uip_ipaddr_t ipaddr; #ifdef HARD_CODED_ADDRESS uiplib_ipaddrconv(HARD_CODED_ADDRESS, &ipaddr); #else uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); #endif if((ipaddr.u16[0] != 0) || (ipaddr.u16[1] != 0) || (ipaddr.u16[2] != 0) || (ipaddr.u16[3] != 0)) { #if UIP_CONF_ROUTER if(!uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0)) { fprintf(stderr,"uip_ds6_prefix_add() failed.\n"); exit(EXIT_FAILURE); } #else /* UIP_CONF_ROUTER */ if(!uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0)) { fprintf(stderr,"uip_ds6_prefix_add() failed.\n"); exit(EXIT_FAILURE); } #endif /* UIP_CONF_ROUTER */ uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); } } #endif /* !UIP_CONF_IPV6_RPL */ #endif /* !UIP_CONF_IPV6 */ // procinit_init(); // autostart_start(autostart_processes); /* Make standard output unbuffered. */ setvbuf(stdout, (char *)NULL, _IONBF, 0); printf("\n*******%s online*******\n",CONTIKI_VERSION_STRING); #if UIP_CONF_IPV6 && !RPL_BORDER_ROUTER /* Border router process prints addresses later */ { int i = 0; int interface_count = 0; for(i = 0; i < UIP_DS6_ADDR_NB; i++) { if(uip_ds6_if.addr_list[i].isused) { printf("IPV6 Addresss: "); sprint_ip6(uip_ds6_if.addr_list[i].ipaddr); printf("\n"); interface_count++; } } assert(0 < interface_count); } #endif while(1) { fd_set fds; int n; struct timeval tv; clock_time_t next_event; n = process_run(); next_event = etimer_next_expiration_time() - clock_time(); #if DEBUG_SLEEP if(n > 0) printf("sleep: %d events pending\n",n); else printf("sleep: next event @ T-%.03f\n",(double)next_event / (double)CLOCK_SECOND); #endif #ifdef __CYGWIN__ /* wpcap doesn't appear to support select, so * we can't idle the process on windows. */ next_event = 0; #endif if(next_event > (CLOCK_SECOND * 2)) next_event = CLOCK_SECOND * 2; tv.tv_sec = n ? 0 : (next_event / CLOCK_SECOND); tv.tv_usec = n ? 0 : ((next_event % 1000) * 1000); FD_ZERO(&fds); FD_SET(STDIN_FILENO, &fds); #ifdef __CYGWIN__ select(1, &fds, NULL, NULL, &tv); #else FD_SET(tapdev_fd(), &fds); if(0 > select(tapdev_fd() + 1, &fds, NULL, NULL, &tv)) { perror("Call to select() failed."); exit(EXIT_FAILURE); } #endif if(FD_ISSET(STDIN_FILENO, &fds)) { char c; if(read(STDIN_FILENO, &c, 1) > 0) { serial_line_input_byte(c); } } #ifdef __CYGWIN__ process_poll(&wpcap_process); #else process_poll(&tapdev_process); #endif etimer_request_poll(); } return 0; }
/*---------------------------------------------------------------------------*/ int main(void) { /* Hardware initialization */ clock_init(); soc_init(); rtimer_init(); /* Init LEDs here */ leds_init(); leds_off(LEDS_ALL); fade(LEDS_GREEN); /* initialize process manager. */ process_init(); /* Init UART */ uart0_init(); #if DMA_ON dma_init(); #endif #if SLIP_ARCH_CONF_ENABLE slip_arch_init(0); #else uart0_set_input(serial_line_input_byte); serial_line_init(); #endif fade(LEDS_RED); PUTSTRING("##########################################\n"); putstring(CONTIKI_VERSION_STRING "\n"); putstring("TI SmartRF05 EB\n"); switch(CHIPID) { case 0xA5: putstring("cc2530"); break; case 0xB5: putstring("cc2531"); break; case 0x95: putstring("cc2533"); break; case 0x8D: putstring("cc2540"); break; } putstring("-F"); switch(CHIPINFO0 & 0x70) { case 0x40: putstring("256, "); break; case 0x30: putstring("128, "); break; case 0x20: putstring("64, "); break; case 0x10: putstring("32, "); break; } puthex(CHIPINFO1 + 1); putstring("KB SRAM\n"); PUTSTRING("\nSDCC Build:\n"); #if STARTUP_VERBOSE #ifdef HAVE_SDCC_BANKING PUTSTRING(" With Banking.\n"); #endif /* HAVE_SDCC_BANKING */ #ifdef SDCC_MODEL_LARGE PUTSTRING(" --model-large\n"); #endif /* SDCC_MODEL_LARGE */ #ifdef SDCC_MODEL_HUGE PUTSTRING(" --model-huge\n"); #endif /* SDCC_MODEL_HUGE */ #ifdef SDCC_STACK_AUTO PUTSTRING(" --stack-auto\n"); #endif /* SDCC_STACK_AUTO */ PUTCHAR('\n'); PUTSTRING(" Net: "); PUTSTRING(NETSTACK_NETWORK.name); PUTCHAR('\n'); PUTSTRING(" MAC: "); PUTSTRING(NETSTACK_MAC.name); PUTCHAR('\n'); PUTSTRING(" RDC: "); PUTSTRING(NETSTACK_RDC.name); PUTCHAR('\n'); PUTSTRING("##########################################\n"); #endif watchdog_init(); /* Initialise the H/W RNG engine. */ random_init(0); /* start services */ process_start(&etimer_process, NULL); ctimer_init(); /* initialize the netstack */ netstack_init(); set_rime_addr(); #if BUTTON_SENSOR_ON || ADC_SENSOR_ON process_start(&sensors_process, NULL); BUTTON_SENSOR_ACTIVATE(); ADC_SENSOR_ACTIVATE(); #endif #if UIP_CONF_IPV6 memcpy(&uip_lladdr.addr, &rimeaddr_node_addr, sizeof(uip_lladdr.addr)); queuebuf_init(); process_start(&tcpip_process, NULL); #endif /* UIP_CONF_IPV6 */ #if VIZTOOL_CONF_ON process_start(&viztool_process, NULL); #endif energest_init(); ENERGEST_ON(ENERGEST_TYPE_CPU); autostart_start(autostart_processes); watchdog_start(); fade(LEDS_YELLOW); while(1) { do { /* Reset watchdog and handle polls and events */ watchdog_periodic(); #if CLOCK_CONF_STACK_FRIENDLY if(sleep_flag) { if(etimer_pending() && (etimer_next_expiration_time() - clock_time() - 1) > MAX_TICKS) { etimer_request_poll(); } sleep_flag = 0; } #endif r = process_run(); } while(r > 0); len = NETSTACK_RADIO.pending_packet(); if(len) { packetbuf_clear(); len = NETSTACK_RADIO.read(packetbuf_dataptr(), PACKETBUF_SIZE); if(len > 0) { packetbuf_set_datalen(len); NETSTACK_RDC.input(); } } #if LPM_MODE #if (LPM_MODE==LPM_MODE_PM2) SLEEP &= ~OSC_PD; /* Make sure both HS OSCs are on */ while(!(SLEEP & HFRC_STB)); /* Wait for RCOSC to be stable */ CLKCON |= OSC; /* Switch to the RCOSC */ while(!(CLKCON & OSC)); /* Wait till it's happened */ SLEEP |= OSC_PD; /* Turn the other one off */ #endif /* LPM_MODE==LPM_MODE_PM2 */ /* * Set MCU IDLE or Drop to PM1. Any interrupt will take us out of LPM * Sleep Timer will wake us up in no more than 7.8ms (max idle interval) */ SLEEPCMD = (SLEEPCMD & 0xFC) | (LPM_MODE - 1); #if (LPM_MODE==LPM_MODE_PM2) /* * Wait 3 NOPs. Either an interrupt occurred and SLEEP.MODE was cleared or * no interrupt occurred and we can safely power down */ __asm nop nop nop __endasm; if(SLEEPCMD & SLEEP_MODE0) { #endif /* LPM_MODE==LPM_MODE_PM2 */ ENERGEST_OFF(ENERGEST_TYPE_CPU); ENERGEST_ON(ENERGEST_TYPE_LPM); /* We are only interested in IRQ energest while idle or in LPM */ ENERGEST_IRQ_RESTORE(irq_energest); /* Go IDLE or Enter PM1 */ PCON |= PCON_IDLE; /* First instruction upon exiting PM1 must be a NOP */ __asm nop __endasm; /* Remember energest IRQ for next pass */ ENERGEST_IRQ_SAVE(irq_energest); ENERGEST_ON(ENERGEST_TYPE_CPU); ENERGEST_OFF(ENERGEST_TYPE_LPM); #if (LPM_MODE==LPM_MODE_PM2) SLEEPCMD &= ~SLEEP_OSC_PD; /* Make sure both HS OSCs are on */ while(!(SLEEPCMD & SLEEP_XOSC_STB)); /* Wait for XOSC to be stable */ CLKCONCMD &= ~CLKCONCMD_OSC; /* Switch to the XOSC */ /* * On occasion the XOSC is reported stable when in reality it's not. * We need to wait for a safeguard of 64us or more before selecting it */ clock_delay(10); while(CLKCONCMD & CLKCONCMD_OSC); /* Wait till it's happened */ } #endif /* LPM_MODE==LPM_MODE_PM2 */ #endif /* LPM_MODE */ } }
int main(int argc, char **argv) { clock_init(); #if NETSTACK_CONF_WITH_IPV6 #if UIP_CONF_IPV6_RPL printf(CONTIKI_VERSION_STRING " started with IPV6, RPL\n"); #else printf(CONTIKI_VERSION_STRING " started with IPV6\n"); #endif #else printf(CONTIKI_VERSION_STRING " started\n"); #endif /* crappy way of remembering and accessing argc/v */ contiki_argc = argc; contiki_argv = argv; /* native under windows is hardcoded to use the first one or two args */ /* for wpcap configuration so this needs to be "removed" from */ /* contiki_args (used by the native-border-router) */ #ifdef __CYGWIN__ contiki_argc--; contiki_argv++; #ifdef UIP_FALLBACK_INTERFACE contiki_argc--; contiki_argv++; #endif #endif process_init(); process_start(&etimer_process, NULL); ctimer_init(); rtimer_init(); prepare_network(); serial_line_init(); /* Make standard output unbuffered. */ setvbuf(stdout, (char *)NULL, _IONBF, 0); select_set_callback(STDIN_FILENO, &stdin_fd); while(1) { fd_set fdr; fd_set fdw; int maxfd; int i; int retval; struct timeval tv; retval = process_run(); tv.tv_sec = 0; tv.tv_usec = 0; if(!retval) { if(etimer_pending()) { clock_time_t t = etimer_next_expiration_time() - clock_time() - 1; if(t < MAX_TICKS) { tv.tv_sec = t / CLOCK_SECOND; tv.tv_usec = (t % CLOCK_SECOND) * 1000; if(tv.tv_usec == 0 && tv.tv_sec == 0) { /* Clock time resolution is milliseconds. Avoid millisecond busy loops. */ tv.tv_usec = 250; } } } else { tv.tv_sec = 60; } /* TODO Replace the busy polling used to read data from the slip pthread */ if(tv.tv_sec) { tv.tv_sec = 0; tv.tv_usec = 10000; } else if(tv.tv_usec > 10000) { tv.tv_usec = 10000; } } FD_ZERO(&fdr); FD_ZERO(&fdw); maxfd = 0; for(i = 0; i <= select_max; i++) { if(select_callback[i] != NULL && select_callback[i]->set_fd(&fdr, &fdw)) { maxfd = i; } } retval = select(maxfd + 1, &fdr, &fdw, NULL, &tv); if(retval < 0) { if(errno != EINTR) { perror("select"); } } else if(retval > 0) { /* timeout => retval == 0 */ for(i = 0; i <= maxfd; i++) { if(select_callback[i] != NULL) { select_callback[i]->handle_fd(&fdr, &fdw); } } } if(etimer_pending() && (etimer_next_expiration_time() - clock_time() - 1) > MAX_TICKS) { etimer_request_poll(); } } return 0; }
/*---------------------------------------------------------------------------*/ int main(int argc, char **argv) { PRINTF(">> %s:main()\n", __FILE__); start: /* Yield once during bootup */ kleenet_schedule_state(MILLISECOND); kleenet_yield_state(); simCurrentTime = NODE_TIME(); PRINTF("> Executing Contiki at simulation time %lu\n", clock_time()); /* Code from contiki-cooja-main.c:process_run_thread_loop (before loop) */ doActionsBeforeTick(); contiki_init(); doActionsAfterTick(); while (1) { /* reboot */ if ((clock_seconds() >= failure_delay()) && reboot_once) { /* symbolic node reboot every 10 seconds */ if (clock_seconds() % 10 == 0) { if (failure_reboot_node()) { PRINTF("main(): rebooting node once @ %lu, %lu seconds\n", clock_time(), clock_seconds()); reboot_once = 0; exit_all_processes(); goto start; } } } /* halt */ if ((clock_seconds() >= failure_delay()) && halt_once) { /* symbolic node outage every 10 seconds */ if (clock_seconds() % 10 == 0) { if (failure_halt_node()) { PRINTF("main(): halting node once @ %lu, %lu seconds\n", clock_time(), clock_seconds()); halt_once = 0; exit_all_processes(); /* loop forerver */ while(1) { kleenet_schedule_state(MILLISECOND); kleenet_yield_state(); } } } } /* Update time */ simCurrentTime = NODE_TIME(); simProcessRunValue = 0; /* Do actions before tick */ doActionsBeforeTick(); /* Poll etimer process */ if (etimer_pending()) { etimer_request_poll(); } /* Code from contiki-cooja-main.c:process_run_thread_loop */ simProcessRunValue = process_run(); while(simProcessRunValue-- > 0) { process_run(); } simProcessRunValue = process_nevents(); /* Do actions after tick */ doActionsAfterTick(); /* Request next tick for remaining events / timers */ if (simProcessRunValue != 0) { kleenet_schedule_state(MILLISECOND); kleenet_yield_state(); continue; } /* Request tick next wakeup time */ if (etimer_pending()) { simNextExpirationTime = etimer_next_expiration_time() - simCurrentTime; } else { simNextExpirationTime = 0; PRINTF("WARNING: No more timers pending\n"); kleenet_schedule_state(MILLISECOND); kleenet_yield_state(); continue; } /* check next expiration time */ if (simNextExpirationTime <= 0) { PRINTF("WARNING: Event timer already expired, but has been delayed: %lu\n", simNextExpirationTime); kleenet_schedule_state(MILLISECOND); } else { kleenet_schedule_state(simNextExpirationTime*MILLISECOND); } /* yield active state */ kleenet_yield_state(); } return 0; }
/*---------------------------------------------------------------------------*/ void lpm_drop() { lpm_registered_module_t *module; uint8_t max_pm = LPM_MODE_MAX_SUPPORTED; uint8_t module_pm; clock_time_t next_event; uint32_t domains = LOCKABLE_DOMAINS; if(RTIMER_CLOCK_LT(soc_rtc_get_next_trigger(), RTIMER_NOW() + STANDBY_MIN_DURATION)) { lpm_sleep(); return; } /* Collect max allowed PM permission from interested modules */ for(module = list_head(modules_list); module != NULL; module = module->next) { if(module->request_max_pm) { module_pm = module->request_max_pm(); if(module_pm < max_pm) { max_pm = module_pm; } } } /* Check if any events fired during this process. Last chance to abort */ if(process_nevents()) { return; } /* Drop */ if(max_pm == LPM_MODE_SLEEP) { lpm_sleep(); } else { /* Critical. Don't get interrupted! */ ti_lib_int_master_disable(); /* * Reschedule AON RTC CH1 to fire an event N ticks before the next etimer * event */ next_event = etimer_next_expiration_time(); if(next_event) { next_event = next_event - clock_time(); soc_rtc_schedule_one_shot(AON_RTC_CH1, RTIMER_NOW() + (next_event * (RTIMER_SECOND / CLOCK_SECOND))); } /* * Notify all registered modules that we are dropping to mode X. We do not * need to do this for simple sleep. * * This is a chance for modules to delay us a little bit until an ongoing * operation has finished (e.g. uart TX) or to configure themselves for * deep sleep. * * At this stage, we also collect power domain locks, if any. * The argument to PRCMPowerDomainOff() is a bitwise OR, so every time * we encounter a lock we just clear the respective bits in the 'domains' * variable as required by the lock. In the end the domains variable will * just hold whatever has not been cleared */ for(module = list_head(modules_list); module != NULL; module = module->next) { if(module->shutdown) { module->shutdown(max_pm); } /* Clear the bits specified in the lock */ domains &= ~module->domain_lock; } /* Pat the dog: We don't want it to shout right after we wake up */ watchdog_periodic(); /* Clear unacceptable bits, just in case a lock provided a bad value */ domains &= LOCKABLE_DOMAINS; /* * Freeze the IOs on the boundary between MCU and AON. We only do this if * PERIPH is not needed */ if(domains & PRCM_DOMAIN_PERIPH) { ti_lib_aon_ioc_freeze_enable(); } /* * Among LOCKABLE_DOMAINS, turn off those that are not locked * * If domains is != 0, pass it as-is */ if(domains) { ti_lib_prcm_power_domain_off(domains); } /* * Before entering Deep Sleep, we must switch off the HF XOSC. The HF XOSC * is predominantly controlled by the RF driver. In a build with radio * cycling (e.g. ContikiMAC), the RF driver will request the XOSC before * using the Freq. Synth, and switch back to the RC when it is about to * turn back off. * * If the radio is on, we won't even reach here, and if it's off the HF * clock source should already be the HF RC. * * Nevertheless, request the switch to the HF RC explicitly here. */ oscillators_switch_to_hf_rc(); /* Configure clock sources for MCU and AUX: No clock */ ti_lib_aon_wuc_mcu_power_down_config(AONWUC_NO_CLOCK); ti_lib_aon_wuc_aux_power_down_config(AONWUC_NO_CLOCK); /* Full RAM retention. */ ti_lib_aon_wuc_mcu_sram_config(MCU_RAM0_RETENTION | MCU_RAM1_RETENTION | MCU_RAM2_RETENTION | MCU_RAM3_RETENTION); /* Disable retention of AUX RAM */ ti_lib_aon_wuc_aux_sram_config(false); /* * Always turn off RFCORE, CPU, SYSBUS and VIMS. RFCORE should be off * already */ ti_lib_prcm_power_domain_off(PRCM_DOMAIN_RFCORE | PRCM_DOMAIN_CPU | PRCM_DOMAIN_VIMS | PRCM_DOMAIN_SYSBUS); /* Request JTAG domain power off */ ti_lib_aon_wuc_jtag_power_off(); /* Turn off AUX */ ti_lib_aux_wuc_power_ctrl(AUX_WUC_POWER_OFF); ti_lib_aon_wuc_domain_power_down_enable(); while(ti_lib_aon_wuc_power_status_get() & AONWUC_AUX_POWER_ON); /* Configure the recharge controller */ ti_lib_sys_ctrl_set_recharge_before_power_down(XOSC_IN_HIGH_POWER_MODE); /* * If both PERIPH and SERIAL PDs are off, request the uLDO as the power * source while in deep sleep. */ if(domains == LOCKABLE_DOMAINS) { ti_lib_pwr_ctrl_source_set(PWRCTRL_PWRSRC_ULDO); } /* We are only interested in IRQ energest while idle or in LPM */ ENERGEST_IRQ_RESTORE(irq_energest); ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM); /* Sync the AON interface to ensure all writes have gone through. */ ti_lib_sys_ctrl_aon_sync(); /* * Explicitly turn off VIMS cache, CRAM and TRAM. Needed because of * retention mismatch between VIMS logic and cache. We wait to do this * until right before deep sleep to be able to use the cache for as long * as possible. */ ti_lib_prcm_cache_retention_disable(); ti_lib_vims_mode_set(VIMS_BASE, VIMS_MODE_OFF); /* Deep Sleep */ ti_lib_prcm_deep_sleep(); /* * When we reach here, some interrupt woke us up. The global interrupt * flag is off, hence we have a chance to run things here. We will wake up * the chip properly, and then we will enable the global interrupt without * unpending events so the handlers can fire */ wake_up(); ti_lib_int_master_enable(); } }