/*---------------------------------Main Routine----------------------------*/ int main(void) { /* GCC depends on register r1 set to 0 (?) */ asm volatile ("clr r1"); /* Initialize in a subroutine to maximize stack space */ initialize(); #if DEBUG {struct process *p; for(p = PROCESS_LIST();p != NULL; p = ((struct process *)p->next)) { PRINTA("Process=%p Thread=%p Name=\"%s\" \n",p,p->thread,PROCESS_NAME_STRING(p)); } } #endif while(1) { process_run(); watchdog_periodic(); /* Print rssi of all received packets, useful for range testing */ #ifdef RF230_MIN_RX_POWER uint8_t lastprint; if (rf230_last_rssi != lastprint) { //can be set in halbb.c interrupt routine PRINTA("%u ",rf230_last_rssi); lastprint=rf230_last_rssi; } #endif #if 0 /* Clock.c can trigger a periodic PLL calibration in the RF230BB driver. * This can show when that happens. */ extern uint8_t rf230_calibrated; if (rf230_calibrated) { PRINTA("\nRF230 calibrated!\n"); rf230_calibrated=0; } #endif #if TESTRTIMER /* Timeout can be increased up to 8 seconds maximum. * A one second cycle is convenient for triggering the various debug printouts. * The triggers are staggered to avoid printing everything at once. * My Jackdaw is 4% slow. */ if (rtimerflag) { rtimer_set(&rt, RTIMER_NOW()+ RTIMER_ARCH_SECOND*1UL, 1,(void *) rtimercycle, NULL); rtimerflag=0; #if STAMPS if ((rtime%STAMPS)==0) { PRINTA("%us ",rtime); if (rtime%STAMPS*10) PRINTA("\n"); } #endif rtime+=1; #if PINGS && UIP_CONF_IPV6_RPL extern void raven_ping6(void); if ((rtime%PINGS)==1) { PRINTA("**Ping\n"); raven_ping6(); } #endif #if ROUTES && UIP_CONF_IPV6_RPL if ((rtime%ROUTES)==2) { extern uip_ds6_nbr_t uip_ds6_nbr_cache[]; extern uip_ds6_route_t uip_ds6_routing_table[]; extern uip_ds6_netif_t uip_ds6_if; uint8_t i,j; PRINTA("\nAddresses [%u max]\n",UIP_DS6_ADDR_NB); for (i=0;i<UIP_DS6_ADDR_NB;i++) { if (uip_ds6_if.addr_list[i].isused) { uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr); PRINTA("\n"); } } PRINTA("\nNeighbors [%u max]\n",UIP_DS6_NBR_NB); for(i = 0,j=1; i < UIP_DS6_NBR_NB; i++) { if(uip_ds6_nbr_cache[i].isused) { uip_debug_ipaddr_print(&uip_ds6_nbr_cache[i].ipaddr); PRINTA("\n"); j=0; } } if (j) PRINTA(" <none>"); PRINTA("\nRoutes [%u max]\n",UIP_DS6_ROUTE_NB); for(i = 0,j=1; i < UIP_DS6_ROUTE_NB; i++) { if(uip_ds6_routing_table[i].isused) { uip_debug_ipaddr_print(&uip_ds6_routing_table[i].ipaddr); PRINTA("/%u (via ", uip_ds6_routing_table[i].length); uip_debug_ipaddr_print(&uip_ds6_routing_table[i].nexthop); // if(uip_ds6_routing_table[i].state.lifetime < 600) { PRINTA(") %lus\n", uip_ds6_routing_table[i].state.lifetime); // } else { // PRINTA(")\n"); // } j=0; } } if (j) PRINTA(" <none>"); PRINTA("\n---------\n"); } #endif #if STACKMONITOR && CONFIG_STACK_MONITOR if ((rtime%STACKMONITOR)==3) { extern uint16_t __bss_end; uint16_t p=(uint16_t)&__bss_end; do { if (*(uint16_t *)p != 0x4242) { PRINTA("Never-used stack > %d bytes\n",p-(uint16_t)&__bss_end); break; } p+=100; } while (p<RAMEND-10); } #endif } #endif /* TESTRTIMER */ //Use with RF230BB DEBUGFLOW to show path through driver #if RF230BB&&0 extern uint8_t debugflowsize,debugflow[]; //in rf230bb.c if (debugflowsize) { debugflow[debugflowsize]=0; PRINTA("%s",debugflow); debugflowsize=0; } #endif } return 0; }
/*---------------------------------------------------------------------------*/ static void exit_process(struct process *p, struct process *fromprocess) { register struct process *q; register struct process *r; struct process * tmp_ptr; //PT_THREAD((* tmp_func_ptr)(struct pt *, process_event_t, process_data_t)); struct process *old_current = process_current; int ret; bool any_marked; uint8_t tmp; PRINTF("process: exit_process '%s'\n", PROCESS_NAME_STRING(p)); /* Make sure the process is in the process list before we try to exit it. */ for (q = process_list; q != p && q != NULL; q = q->next); if (q == NULL) { return; } if (process_is_running(p)) { /* Process was running */ p->state = PROCESS_STATE_NONE; p->xc8_aux = XC8_AUX_STATE_MARKED_FOR_EXIT; } do { any_marked = false; /* * Post a synchronous event to all processes to inform them that * this process is about to exit. This will allow services to * deallocate state associated with this process. */ for (r = process_list; r != NULL; r = r->next) { if (r->xc8_aux & XC8_AUX_STATE_MARKED_FOR_EXIT) { for (q = process_list; q != NULL; q = q->next) { if ((q->xc8_aux & XC8_AUX_STATE_MARKED_FOR_EXIT) == 0) { //call_process(q, PROCESS_EVENT_EXITED, (process_data_t)p); /****************************** * * removing recursion * ***************************************************/ if ((q->state & PROCESS_STATE_RUNNING) && q->thread != NULL) { PRINTF("process: calling process '%s' with event PROCESS_EVENT_EXITED \n", PROCESS_NAME_STRING(q)); process_current = q; q->state = PROCESS_STATE_CALLED; ret = q->thread(&q->pt, PROCESS_EVENT_EXITED, (process_data_t) r); if (ret == PT_EXITED || ret == PT_ENDED /*|| PROCESS_EVENT_EXITED == PROCESS_EVENT_EXIT*/) { //exit_process(p,p); tmp = q->xc8_aux | XC8_AUX_STATE_MARKED_FOR_EXIT; q->xc8_aux = tmp; any_marked = true; if (process_is_running(q)) { q->state = PROCESS_STATE_NONE; } } else { q->state = PROCESS_STATE_RUNNING; } } } } } } } while (any_marked); //We are repeating until no process need exit if (p->thread != NULL && p != fromprocess) { /* Post the exit event to the process that is about to exit. */ process_current = p; p->thread(&p->pt, PROCESS_EVENT_EXIT, NULL); } // We are removing all processed marked for exit for (r = process_list; r != NULL; r = r->next) { if (r->xc8_aux & XC8_AUX_STATE_MARKED_FOR_EXIT) { r->xc8_aux = XC8_AUX_STATE_NONE; r->state = PROCESS_STATE_NONE; if (r == process_list) { process_list = process_list->next; } else { for (q = process_list; q != NULL; q = q->next) { if (q->next == r) { tmp_ptr = r->next; q->next = tmp_ptr; break; } } } } } process_current = old_current; }