void Task1() { uint16_t i,j; uint32_t it; nrk_time_t time, time2, time3; while(1) { nrk_led_set(RED_LED); nrk_gpio_toggle(NRK_DEBUG_0); nrk_kprintf("Task 1\r\n"); //for (i = 0; i < 10; i++) { // nrk_time_get(&time); // nrk_time_get(&time2); // nrk_time_sub(&time3, time2, time); // printf("%lu.%09lu\r\n", time3.secs, time3.nano_secs); nrk_time_get(&time); printf("%lu.%09lu\r\n", time.secs, time.nano_secs); for(it=0;it<115200;it++); nrk_time_get(&time); printf("%lu.%09lu\r\n", time.secs, time.nano_secs); // nrk_time_get(&time2); // nrk_time_sub(&time3, time2, time); // printf("%lu.%09lu\r\n", time3.secs, time3.nano_secs); //} // nrk_time_get(&time); // for(i=0;i<256;i++) for(j=0;j<65000;j++); // wait 1 second // nrk_time_get(&time2); // nrk_time_sub(&time3, time2, time); // printf("%lu.%lu\r\n", time3.secs, time3.nano_secs); nrk_kprintf("Task 1 done\r\n"); nrk_wait_until_next_period(); } }
int8_t nrk_wait_until (nrk_time_t t) { nrk_time_t ct; int8_t v; // uint8_t c; //c = _nrk_os_timer_get (); //do{ //}while(_nrk_os_timer_get()==c); //ttt=c+1; nrk_time_get (&ct); v = nrk_time_sub (&t, t, ct); //nrk_time_compact_nanos(&t); if (v == NRK_ERROR) { return NRK_ERROR; } //if(t.secs<ct.secs) return 0; //if(t.secs==ct.secs && t.nano_secs<ct.nano_secs) return 0; //t.secs-=ct.secs; //t.nano_secs-=ct.nano_secs; // nrk_wait (t); return NRK_OK; }
void handle_discover_response(pkt_t *pkt) { node_id_t origin = pkt->payload[PKT_RESPONSE_ORIGIN_OFFSET]; uint8_t seq = pkt->payload[PKT_RESPONSE_SEQ_OFFSET]; nrk_time_t delay; uint8_t attempt; if (!IS_VALID_NODE_ID(origin)) { LOG("WARN: invalid origin in response: "); LOGP("%d\r\n", origin); return; } LOG("response: orig "); LOGP("%u", origin); LOGA(" seq "); LOGP("%u", seq); LOGA(" src "); LOGP("%u", pkt->src); LOGA(": "); nrk_time_get(&last_activity); if (origin == this_node_id) { LOGA("reached origin\r\n"); add_path_to_graph(pkt); print_graph(&network); } else { /* we're not the destination: forward to gateway */ attempt = 0; do { forward_response(pkt, attempt); choose_delay(&delay, &discover_req_delay); nrk_wait(delay); } while (++attempt < discover_send_attempts); } }
int main () { nrk_setup_ports(); nrk_setup_uart(UART_BAUDRATE_115K2); nrk_init(); nrk_time_set(0,0); nrk_time_get(seed); srand(seed->nano_secs); //Initialize tasks //Higher value higher priority` // INITIALIZE_TASK(1, BASIC_TASK); // INITIALIZE_TASK(2, CBS_TASK); // INITIALIZE_TASK(3, BASIC_TASK); INITIALIZE_TASK(1, CBS_TASK); INITIALIZE_TASK(2, BASIC_TASK); INITIALIZE_TASK(3, CBS_TASK); nrk_start(); return 0; }
void tdma_stats_ts_packet(uint8_t * tx_buf) { nrk_time_t old, cur, lat; nrk_time_get(&cur); nrk_time_compact_nanos(&cur); //memcpy(&lat, &tx_buf[TDMA_DATA_START+8], sizeof(lat)); memcpy(&lat, &tx_buf[TDMA_DATA_START+8], sizeof(lat)); //memcpy(&old, &tx_buf[TDMA_DATA_START+16], sizeof(old)); memcpy(&old, &tx_buf[TDMA_DATA_START+16], sizeof(old)); //printf("MTTS %lu %lu %lu %lu\r\n", lat.secs, lat.nano_secs, old.secs, old.nano_secs); // subtract current time from arrival time (old) if (nrk_time_sub(&cur, cur, old) == NRK_ERROR) { cur.secs = 0; cur.nano_secs = 0; } // add that difference to the total latency nrk_time_add(&lat, lat, cur); // finally, add the cumulative latency back in memcpy(&tx_buf[TDMA_DATA_START+8], &lat, sizeof(lat)); }
// This is an interrupts routine that handles the button press. // It has a 300ms debounce void button_handler() { int8_t v; // Make sure button is depressed for at least 50 us nrk_spin_wait_us(50); v=nrk_gpio_get(NRK_PORTD_0); if(v!=0) return; nrk_time_get(&button_cur_press); nrk_time_sub(&button_tmp_press, button_cur_press, button_last_press ); if(button_tmp_press.secs>=1 || button_tmp_press.nano_secs>=(300*NANOS_PER_MS)) { // Reboot the node... socket_0_disable(); power_socket_disable(0); nrk_int_disable(); while(1); if(socket_0_active==1) { plug_led_green_clr(); power_socket_disable(0); } else { plug_led_green_set(); power_socket_enable(0); } button_last_press.secs=button_cur_press.secs; button_last_press.nano_secs=button_cur_press.nano_secs; } }
void handle_discover_request(pkt_t *pkt) { node_id_t origin; uint8_t seq, depth; nrk_time_t delay; uint8_t attempt; int8_t rc; origin = pkt->payload[PKT_REQUEST_ORIGIN_OFFSET]; seq = pkt->payload[PKT_REQUEST_SEQ_OFFSET]; depth = pkt->payload[PKT_REQUEST_DEPTH_OFFSET]; if (!IS_VALID_NODE_ID(origin)) { LOG("WARN: invalid origin node id in response: "); LOGP("%d\r\n", origin); return; } LOG("request:"); LOGA(" src "); LOGP("%u", pkt->src); LOGA(" orig "); LOGP("%u", origin); LOGA(" seq "); LOGP("%d (%d)", seq, discovered_seq); LOGA(" depth "); LOGP("%d\r\n", depth); nrk_time_get(&last_activity); choose_delay(&delay, &discover_req_delay); nrk_wait(delay); /* Discover this node: mark and broadcast to neighbors */ if (discovered_seq != seq) { discovered_seq = seq; route_to_origin = pkt->src; LOG("discovered: orig "); LOGP("%d", origin); LOGA(" seq "); LOGP("%d", discovered_seq); LOGA(" hop "); LOGP("%d\r\n", route_to_origin); if (depth == 0 || pkt->hops < depth) { attempt = 0; do { rc = broadcast_request(origin, seq, depth, attempt); if (rc != NRK_OK) LOG("WARN: failed to broadcast req\r\n"); nrk_wait(delay); } while (++attempt < discover_send_attempts); } else { LOG("max depth reached: "); LOGP("%d\r\n", depth); } } else { LOG("already discovered: seq "); LOGP("%u\r\n", discovered_seq); } attempt = 0; do { send_response(origin, pkt->src, seq, attempt); nrk_wait(delay); } while (++attempt < discover_send_attempts); }
void tdma_stats_dump() { nrk_time_t ct; nrk_time_get(&ct); // PRINTS OUT... // // My MAC address // time tdma task has spent awake (secs) // time tdma task has spent awake (nanosecs) // time tdma task used radio // number of slot steals // number of backoffs // number of rx syncs // number of sync slots #ifdef NRK_STATS_TRACKER nrk_stats_get(tdma_pid, &tdma_stat_struct); tdma_cpu_time = _nrk_ticks_to_time(tdma_stat_struct.total_ticks); //printf("TCT %lu %lu %lu %lu\r\n", tdma_cpu_time.secs, tdma_cpu_time.nano_secs, // tree_creation_time.secs, tree_creation_time.nano_secs); nrk_time_sub(&tdma_cpu_time, tdma_cpu_time, tree_creation_time); #endif printf("SD %d %lu %lu %lu %lu %lu %u %u\r\n", tdma_mac_get(), tdma_cpu_time.secs, tdma_cpu_time.nano_secs, ticks_rdo, steal_cnt, backoff_cnt, sync_rx_cnt, sync_slot_cnt); printf("OSA %lu %lu %lu %lu\r\n", osa_time.secs, osa_time.nano_secs, ct.secs, ct.nano_secs); #ifdef SYNC_HIST printf("SH %d %d %d %d %d %d %d %d %d %d %d\r\n", tdma_mac_get(), sync_hist[0], sync_hist[1], sync_hist[2], sync_hist[3], sync_hist[4], sync_hist[5], sync_hist[6], sync_hist[7], sync_hist[8], sync_hist[9]); #endif }
void Task3() { uint16_t i,j; uint32_t it; nrk_time_t time; while(1) { nrk_led_set(BLUE_LED); nrk_gpio_toggle(NRK_DEBUG_2); nrk_kprintf("Task 3\r\n"); nrk_time_get(&time); printf("%lu.%09lu\r\n", time.secs, time.nano_secs); for(it=0;it<345600;it++);//345600 nrk_time_get(&time); printf("%lu.%09lu\r\n", time.secs, time.nano_secs); nrk_kprintf("Task 3 done\r\n"); nrk_wait_until_next_period(); } }
void Task1() { nrk_kprintf( PSTR("Nano-RK Version ") ); printf( "%d\r\n",NRK_VERSION ); start_time.secs=0; start_time.nano_secs=0; end_time.secs=0; end_time.nano_secs=0; start_time_1.secs=0; start_time_1.nano_secs=0; end_time_1.secs=0; end_time_1.nano_secs=0; while (1) { // Measure time with code inbetween nrk_time_get(&start_time); nrk_time_get(&end_time); printf("####### NO WAIT BETWEEN READINGS #########\r\n"); printf("start: %lu %lu\r\n",start_time.secs,start_time.nano_secs); printf(" end: %lu %lu\r\n",end_time.secs,end_time.nano_secs); printf("end.nano - start.nano: %lu\r\n",end_time.nano_secs-start_time.nano_secs); //printf("start.nano - end.nano: %lu\r\n",start_time.nano_secs-end_time.nano_secs); // Measure time with code inbetween nrk_time_get(&start_time_1); nrk_spin_wait_us(200); nrk_time_get(&end_time_1); printf("####### 200us BETWEEN READINGS #########\r\n"); printf("start: %lu %lu\r\n",start_time_1.secs,start_time_1.nano_secs); printf(" end: %lu %lu\r\n",end_time_1.secs,end_time_1.nano_secs); printf("end.nano - start.nano: %lu\r\n",end_time_1.nano_secs-start_time_1.nano_secs); nrk_wait_until_next_period(); } }
void Task2() { uint16_t i,j; uint32_t it; nrk_time_t time, time2, time3; while(1) { nrk_led_set(GREEN_LED); nrk_gpio_toggle(NRK_DEBUG_1); nrk_kprintf("Task 2\r\n"); nrk_time_get(&time); printf("%lu.%09lu\r\n", time.secs, time.nano_secs); for(it=0;it<400800;it++);//for(it=0;it<460800;it++);//460800 nrk_time_get(&time); printf("%lu.%09lu\r\n", time.secs, time.nano_secs); nrk_kprintf("Task 2 done\r\n"); nrk_wait_until_next_period(); } }
int8_t probe(uint8_t depth) { outstanding_seq++; nrk_time_get(&last_activity); LOG("starting: orig "); LOGP("%d", this_node_id); LOGA(" seq "); LOGP("%d", outstanding_seq); LOGA(" depth "); LOGP("%d\r\n", depth); init_graph(&network); print_graph(&network); discovered_seq = outstanding_seq; // origin starts discovered return broadcast_request(this_node_id, outstanding_seq, depth, 0 /* attempt */); }
void sync_miss_log() { if (sync_consec_miss < 10) { sync_consec_miss++; if (sync_consec_miss > 5) { nrk_time_t cur_time; nrk_time_get(&cur_time); nrk_time_compact_nanos(&cur_time); printf("SM %d %d %lu %lu\r\n", tdma_mac_get(), sync_consec_miss, cur_time.secs, cur_time.nano_secs); } } }
void debug_update() { nrk_time_get(&t); debug_stats.uptime.secs=t.secs; debug_stats.uptime.nano_secs=t.nano_secs; nrk_stats_get_deep_sleep(&t); debug_stats.deep_sleep.secs=t.secs; debug_stats.deep_sleep.nano_secs=t.nano_secs; nrk_stats_get(0, &t_stat); t=_nrk_ticks_to_time(t_stat.total_ticks); debug_stats.idle_time.secs=t.secs; debug_stats.idle_time.nano_secs=t.nano_secs; }
static void periodic_heading_process(bool enabled, nrk_time_t *next_event, nrk_sig_mask_t *wait_mask) { int16_t heading; int8_t rc; nrk_time_t now; if (!enabled) return; rc = get_heading(&heading); OUT("heading: "); show_heading(rc == NRK_OK ? &heading : NULL); nrk_time_get(&now); nrk_time_add(next_event, now, heading_period); }
int8_t nrk_wait_until(nrk_time_t t) { nrk_time_t ct; uint8_t v; nrk_time_get(&ct); v = nrk_time_sub(&t, t, ct); if (v == 0) return NRK_ERROR; //if(t.secs<ct.secs) return 0; //if(t.secs==ct.secs && t.nano_secs<ct.nano_secs) return 0; //t.secs-=ct.secs; //t.nano_secs-=ct.nano_secs; nrk_wait(t); return NRK_OK; }
void Task4() { uint16_t cnt; nrk_time_t my_time; printf( "Task4 PID=%d\r\n",nrk_get_pid()); cnt=0; while(1) { nrk_led_set(RED_LED); nrk_time_get(&my_time); printf( "Task4 cnt=%d\r\n",cnt ); nrk_wait_until_next_period(); nrk_led_clr(RED_LED); cnt++; nrk_wait_until_next_period(); } }
void _nrk_reserve_update (uint8_t reserve_id) { nrk_time_t t; nrk_int_disable (); nrk_time_get (&t); _nrk_reserve[reserve_id].cur_time = (int32_t) _nrk_time_to_ticks_long (t); if (_nrk_reserve[reserve_id].cur_time >= _nrk_reserve[reserve_id].set_time) { // If the reserve is passed its period then replenish it _nrk_reserve[reserve_id].set_time = _nrk_reserve[reserve_id].cur_time + _nrk_reserve[reserve_id].period_ticks; _nrk_reserve[reserve_id].cur_access = 0; } nrk_int_enable (); }
void heart_rate_int() { uint8_t bpm; nrk_led_set(BLUE_LED); nrk_time_get(&c); nrk_time_sub(&t,c,l); bpm=(uint16_t)60000 / (uint16_t)(t.nano_secs/1000000); if(bpm>20 && bpm<220 ) { bpm_list[bpm_index]=bpm; bpm_index++; if(bpm_index==BPM_LIST_SIZE)bpm_index=0; } l.secs=c.secs; l.nano_secs=c.nano_secs; nrk_led_clr(BLUE_LED); }
uint8_t hrm_get_value() { uint16_t acc; uint8_t i,j,tmp; nrk_time_get(&c); nrk_time_sub(&t,c,l); if(t.secs>5) { for(i=0; i<BPM_LIST_SIZE; i++ ) bpm_list[i]=0; return 0; } for(i=0; i<BPM_LIST_SIZE; i++ ) { bpm_sort[i]=bpm_list[i]; if(bpm_list[i]==0) return 0; } for(i=0; i<BPM_LIST_SIZE; i++ ) { for(j=0; j<BPM_LIST_SIZE-1; j++ ) { if(bpm_sort[j]>bpm_sort[j+1] ) { tmp=bpm_sort[j]; bpm_sort[j]=bpm_sort[j+1]; bpm_sort[j+1]=tmp; } } } /* for(i=0; i<BPM_LIST_SIZE; i++ ) { if(bpm_index==i) printf( ">" ); printf( "%u %d %d\r\n",i,bpm_sort[i],bpm_list[i]); } */ acc=0; for(i=(BPM_LIST_SIZE/2)-2; i<(BPM_LIST_SIZE/2)+2; i++ ) acc+=bpm_sort[BPM_LIST_SIZE/2]; //return bpm_sort[BPM_LIST_SIZE/2]; return (acc/4); }
int8_t nrk_reserve_set (uint8_t id, nrk_time_t * period, int16_t access_count, void *errhandler) { nrk_time_t tmp_time; if (id >= NRK_MAX_RESERVES) return NRK_ERROR; if (_nrk_reserve[id].active == -1) return NRK_ERROR; tmp_time.secs = period->secs; tmp_time.nano_secs = period->nano_secs; _nrk_reserve[id].period_ticks = _nrk_time_to_ticks_long (tmp_time); _nrk_reserve[id].set_access = access_count; _nrk_reserve[id].cur_access = 0; nrk_time_get (&tmp_time); _nrk_reserve[id].cur_time = (uint32_t) _nrk_time_to_ticks_long (tmp_time); _nrk_reserve[id].set_time = _nrk_reserve[id].cur_time + _nrk_reserve[id].period_ticks; _nrk_reserve[id].error = (void *) errhandler; return NRK_OK; }
void nl_rx_task() { uint8_t len; // to hold the size of the received packet, always = sizeof(NW_Packet) int8_t rssi; // to hold rssi of received packet uint8_t *local_rx_buf; // pointer to receive buffer of link layer int8_t val; // status variable to hold the return type of function calls int8_t flag; nrk_time_t start, end, elapsed; // needed by nl_rx_task() // to decide when to send own NGB_LIST if(DEBUG_NL >= 1) { nrk_kprintf(PSTR("NL_RX_TASK PID = ")); printf("%d\r\n",nrk_get_pid()); } // initialise the timer nrk_time_get(&start); end.secs = start.secs; end.nano_secs = start.nano_secs; // initialise the link layer val = bmac_init(25); if(val == NRK_ERROR) { nrk_int_disable(); nrk_led_set(RED_LED); while(1) nrk_kprintf(PSTR("NL: Error returned by bmac_init()\r\n")); } // give the link layer a rx buffer val = bmac_rx_pkt_set_buffer(rx_buf, RF_BUFFER_SIZE); if(val == NRK_ERROR) { nrk_int_disable(); nrk_led_set(RED_LED); while(1) nrk_kprintf(PSTR("NL: Error returned by bmac_rx_pkt_set_buffer()\r\n")); } // start processing forever while(1) { // decide whether it is time to send your own Ngb_List message if(CONNECTED_TO_GATEWAY == TRUE) { nrk_time_get(&end); val = nrk_time_sub(&elapsed, end, start); nrk_time_compact_nanos(&elapsed); if(elapsed.secs >= NGB_LIST_PERIOD) { ntg_pkt.type = SERIAL_NGB_LIST; ntg_pkt.length = SIZE_MSG_NGB_LIST; enter_cr(nl_sem, 34); pack_Msg_NgbList(ntg_pkt.data, &nl); leave_cr(nl_sem, 34); pack_NodeToGatewaySerial_Packet_header(to_gw_buf, &ntg_pkt); memcpy(to_gw_buf + SIZE_NODETOGATEWAYSERIAL_PACKET_HEADER, ntg_pkt.data, MAX_SERIAL_PAYLOAD); if(DEBUG_NL == 2) { nrk_kprintf(PSTR("Sending own NGB_LIST message to gateway\r\n")); } sendToSerial(to_gw_buf, SIZE_NODETOGATEWAYSERIAL_PACKET); // reset the timer start.secs = end.secs; start.nano_secs = end.nano_secs; } // end if } // end if if(DEBUG_NL >= 1) { nrk_kprintf(PSTR("Waiting for next pkt from link layer\r\n")); } flag = 0; // wait for the next packet while(bmac_rx_pkt_ready() == 0) { val = bmac_wait_until_rx_pkt(); if(DEBUG_NL == 2) { nrk_kprintf(PSTR("NL: bmac_wait_until_rx_packet() returned ")); printf("%d\n", val); } } // Get the packet do { local_rx_buf = bmac_rx_pkt_get(&len,&rssi); if(local_rx_buf == NULL) { nrk_kprintf(PSTR("NL: NULL returned by bmac_rx_pkt_get()\r\n")); } } while(local_rx_buf == NULL); // sanity check for debugging if(len != SIZE_NW_PACKET) // this should not happen { /* nrk_int_disable(); nrk_led_set(RED_LED); while(1) { nrk_kprintf(PSTR("NL: Wrong length of packet received: ")); printf("%d\r\n", len); } */ if(DEBUG_NL >= 1) { nrk_kprintf(PSTR("NL: nl_rx_task(): Wrong length of packet received: ")); printf("%d\r\n", len); } flag = 1; } nrk_led_set(GREEN_LED); if(DEBUG_NL == 2)// || flag == 1) { int8_t i; nrk_kprintf(PSTR("NL: Contents of received packet are\r\n")); printf("["); for(i = 0; i < len; i++) printf("%d ", local_rx_buf[i]); printf("]\r\n"); } if(flag == 1) { bmac_rx_pkt_release(); // drop the packet and go receive another nrk_led_clr(GREEN_LED); continue; } // unpack the packet header from the received buffer unpack_NW_Packet_header(&pkt_rx, local_rx_buf); // copy the packet payload to the data field of the local packet memcpy(pkt_rx.data, local_rx_buf + SIZE_NW_PACKET_HEADER, MAX_NETWORK_PAYLOAD); // Release the RX buffer quickly so future packets can arrive bmac_rx_pkt_release(); // begin processing this packet if(pkt_type(&pkt_rx) == APPLICATION) // its an application layer packet { // case 1: Destination is NODE_ADDR or BCAST_ADDR if(pkt_rx.dest == NODE_ADDR || pkt_rx.dest == BCAST_ADDR) process_app_pkt(&pkt_rx, rssi); // case 2: I am enroute to the destination else if(pkt_rx.nextHop == NODE_ADDR) { if(pkt_rx.src == NODE_ADDR) // routing table corrupted { nrk_int_disable(); nrk_led_set(RED_LED); while(1) { nrk_kprintf(PSTR("Routing table corrupted at ")); printf("%d\r\n", NODE_ADDR); } // end while } // end if else route_packet(&pkt_rx); } // end if // case 3: Routing tables still not made else if(pkt_rx.nextHop == BCAST_ADDR) route_packet(&pkt_rx); else ; // drop all other packets } // end if(type == APPLICATION) else { if(pkt_type(&pkt_rx) == NW_CONTROL) // its a network control packet { // case 1: Destination is NODE_ADDR or BCAST_ADDR if(pkt_rx.dest == NODE_ADDR || pkt_rx.dest == BCAST_ADDR) process_nw_ctrl_pkt(&pkt_rx, rssi); // case 2: I am enroute to a destination else if(pkt_rx.nextHop == NODE_ADDR) { if(pkt_rx.src == NODE_ADDR) // routing table corrupted { nrk_int_disable(); nrk_led_set(RED_LED); while(1) { nrk_kprintf(PSTR("Routing table corrupted at ")); printf("%d\r\n", NODE_ADDR); } // end while } // end if else route_packet(&pkt_rx); } // end if // case 3: Routing tables still not made else if(pkt_rx.nextHop == BCAST_ADDR) route_packet(&pkt_rx); else ; // drop all other packets } // end if(type == NW_CONTROL) else // unknown packet type { nrk_kprintf(PSTR("NL: Unknown pkt type received = ")); printf("%d\r\n", pkt_type(&pkt_rx)); } } nrk_led_clr(GREEN_LED); } // end while(1) return; } // end nl_rx_task
void inline _nrk_scheduler() { int8_t task_ID; uint16_t next_wake; //uint16_t start_time_stamp; /* _nrk_precision_os_timer_reset(); */ /* nrk_int_disable(); */ // this should be removed... Not needed #ifndef NRK_NO_BOUNDED_CONTEXT_SWAP _nrk_high_speed_timer_reset(); start_time_stamp=_nrk_high_speed_timer_get(); #endif _nrk_set_next_wakeup(MAX_SCHED_WAKEUP_TIME); // Set to huge number which will later get set to min next_wake=60000; // Safety zone starts here.... #ifdef NRK_WATCHDOG nrk_watchdog_reset(); #endif #ifdef NRK_SW_WDT _nrk_sw_wdt_check(); #endif #ifdef NRK_KERNEL_TEST //nrk_kprintf( PSTR("*")); //Check if OS tick was delayed... // if(_nrk_cpu_state!=CPU_SLEEP && _nrk_os_timer_get()!=0) { // nrk_kprintf( PSTR("X" )); //printf( "%u ",_nrk_os_timer_get()); // } //printf( "%u\r\n",_nrk_prev_timer_val); if((_nrk_cpu_state!=CPU_ACTIVE) && (_nrk_os_timer_get()>nrk_max_sleep_wakeup_time)) nrk_max_sleep_wakeup_time=_nrk_os_timer_get(); #endif //while(_nrk_time_trigger>0) //{ nrk_system_time.nano_secs+=((uint32_t)_nrk_prev_timer_val*NANOS_PER_TICK); nrk_system_time.nano_secs-=(nrk_system_time.nano_secs%(uint32_t)NANOS_PER_TICK); #ifdef NRK_STATS_TRACKER if(nrk_cur_task_TCB->task_ID==NRK_IDLE_TASK_ID) { if(_nrk_cpu_state==CPU_SLEEP) _nrk_stats_sleep(_nrk_prev_timer_val); _nrk_stats_task_preempted(nrk_cur_task_TCB->task_ID, _nrk_prev_timer_val); // Add 0 time since the preempted call before set the correct value _nrk_stats_task_suspend(nrk_cur_task_TCB->task_ID, 0); } else { if(nrk_cur_task_TCB->suspend_flag==1) _nrk_stats_task_suspend(nrk_cur_task_TCB->task_ID, _nrk_prev_timer_val); else _nrk_stats_task_preempted(nrk_cur_task_TCB->task_ID, _nrk_prev_timer_val); } #endif while(nrk_system_time.nano_secs>=NANOS_PER_SEC) { nrk_system_time.nano_secs-=NANOS_PER_SEC; nrk_system_time.secs++; nrk_system_time.nano_secs-=(nrk_system_time.nano_secs%(uint32_t)NANOS_PER_TICK); } // _nrk_time_trigger--; //} if(nrk_cur_task_TCB->suspend_flag==1 && nrk_cur_task_TCB->task_state!=FINISHED) { // nrk_cur_task_TCB->task_state = EVENT_SUSPENDED; if(nrk_cur_task_TCB->event_suspend==RSRC_EVENT_SUSPENDED) nrk_cur_task_TCB->task_state = EVENT_SUSPENDED; else if( nrk_cur_task_TCB->event_suspend>0 && nrk_cur_task_TCB->nw_flag==0) nrk_cur_task_TCB->task_state = EVENT_SUSPENDED; else if( nrk_cur_task_TCB->event_suspend>0 && nrk_cur_task_TCB->nw_flag==1) nrk_cur_task_TCB->task_state = SUSPENDED; else { nrk_cur_task_TCB->task_state = SUSPENDED; nrk_cur_task_TCB->event_suspend=0; nrk_cur_task_TCB->nw_flag=0; } nrk_rem_from_readyQ(nrk_cur_task_TCB->task_ID); } // nrk_print_readyQ(); // Update cpu used value for ended task // If the task has used its reserve, suspend task // Don't disable IdleTask which is 0 // Don't decrease cpu_remaining if reserve is 0 and hence disabled if(nrk_cur_task_TCB->cpu_reserve!=0 && nrk_cur_task_TCB->task_ID!=NRK_IDLE_TASK_ID) { // Update CASH and cpu_remaining // First use up any available CASH budget uint8_t ticksToAccountFor = _nrk_prev_timer_val; nrk_budget_t *budgetFromCASH = nrk_peek_budget(); while (ticksToAccountFor > 0 && budgetFromCASH) { // We've found some cash budget uint8_t availableCASH = budgetFromCASH->amount_left; nrk_time_t system_time; nrk_time_get(&system_time); // We need to look at the deadline for the cash budget // If it has passed, we can only use the portion that came before the deadline if (nrk_time_compare(&system_time, &budgetFromCASH->expire_time) == 1) { nrk_time_t difference; nrk_time_sub(&difference, system_time, budgetFromCASH->expire_time); uint8_t differenceInTicks = _nrk_time_to_ticks(&difference); // Check if it expired before we got a chance to use it if (differenceInTicks > ticksToAccountFor) { availableCASH = 0; } else { uint8_t usableBudget = ticksToAccountFor - _nrk_time_to_ticks(&difference); // Take the minimum of available vs usable availableCASH = usableBudget < availableCASH ? usableBudget : availableCASH; } // pop it off the queue. Expired now. nrk_get_budget(); } if (availableCASH > ticksToAccountFor) { budgetFromCASH->amount_left -= ticksToAccountFor; ticksToAccountFor = 0; } else { ticksToAccountFor -= availableCASH; // Pop the now empty cash budget off the queue nrk_get_budget(); } budgetFromCASH = budgetFromCASH->Next; } // If we still have ticks to account for, take them off cpu_remaining if (ticksToAccountFor > 0) { nrk_cur_task_TCB->cpu_remaining -= ticksToAccountFor; } // For finished tasks that still have cpu remaining, give it to the CASH queue if (nrk_cur_task_TCB->task_state==FINISHED && nrk_cur_task_TCB->cpu_remaining > 0) { // Add to CASH queue nrk_add_nrk_budget(nrk_cur_task_TCB->absolute_deadline, nrk_cur_task_TCB->cpu_remaining); } else if (nrk_cur_task_TCB->cpu_remaining ==0 ) { // Support for Constant Bandwith Servers if(nrk_cur_task_TCB->task_type == CBS_TASK) { // Recharge budget nrk_cur_task_TCB->cpu_remaining = nrk_cur_task_TCB->cpu_reserve; // Increase the absolute deadline nrk_time_t increase = _nrk_ticks_to_time(nrk_cur_task_TCB->period); nrk_time_add(&nrk_cur_task_TCB->absolute_deadline, nrk_cur_task_TCB->absolute_deadline, increase); // Remove/re-add from ready queue to re-sort based on new absolute deadline nrk_rem_from_readyQ(nrk_cur_task_TCB->task_ID); nrk_add_to_readyQ(nrk_cur_task_TCB->task_ID); } else { #ifdef NRK_STATS_TRACKER _nrk_stats_add_violation(nrk_cur_task_TCB->task_ID); #endif nrk_kernel_error_add(NRK_RESERVE_VIOLATED,nrk_cur_task_TCB->task_ID); nrk_cur_task_TCB->task_state = SUSPENDED; nrk_rem_from_readyQ(nrk_cur_task_TCB->task_ID); } } } // Check I/O nrk_queues to add tasks with remaining cpu back... // Add eligable tasks back to the ready Queue // At the same time find the next earliest wakeup for (task_ID=0; task_ID < NRK_MAX_TASKS; task_ID++) { if(nrk_task_TCB[task_ID].task_ID==-1) continue; nrk_task_TCB[task_ID].suspend_flag=0; if( nrk_task_TCB[task_ID].task_ID!=NRK_IDLE_TASK_ID && nrk_task_TCB[task_ID].task_state!=FINISHED ) { if( nrk_task_TCB[task_ID].next_wakeup >= _nrk_prev_timer_val ) nrk_task_TCB[task_ID].next_wakeup-=_nrk_prev_timer_val; else { nrk_task_TCB[task_ID].next_wakeup=0; } // Do next period book keeping. // next_period needs to be set such that the period is kept consistent even if other // wait until functions are called. if( nrk_task_TCB[task_ID].next_period >= _nrk_prev_timer_val ) nrk_task_TCB[task_ID].next_period-=_nrk_prev_timer_val; else { if(nrk_task_TCB[task_ID].period>_nrk_prev_timer_val) nrk_task_TCB[task_ID].next_period= nrk_task_TCB[task_ID].period-_nrk_prev_timer_val; else nrk_task_TCB[task_ID].next_period= _nrk_prev_timer_val % nrk_task_TCB[task_ID].period; } if(nrk_task_TCB[task_ID].next_period==0) nrk_task_TCB[task_ID].next_period=nrk_task_TCB[task_ID].period; } // Look for Next Task that Might Wakeup to interrupt current task if (nrk_task_TCB[task_ID].task_state == SUSPENDED ) { // printf( "Task: %d nw: %d\n",task_ID,nrk_task_TCB[task_ID].next_wakeup); // If a task needs to become READY, make it ready if (nrk_task_TCB[task_ID].next_wakeup == 0) { // printf( "Adding back %d\n",task_ID ); if(nrk_task_TCB[task_ID].event_suspend>0 && nrk_task_TCB[task_ID].nw_flag==1) nrk_task_TCB[task_ID].active_signal_mask=SIG(nrk_wakeup_signal); //if(nrk_task_TCB[task_ID].event_suspend==0) nrk_task_TCB[task_ID].active_signal_mask=0; nrk_task_TCB[task_ID].event_suspend=0; nrk_task_TCB[task_ID].nw_flag=0; nrk_task_TCB[task_ID].suspend_flag=0; if(nrk_task_TCB[task_ID].num_periods==1) { nrk_task_TCB[task_ID].cpu_remaining = nrk_task_TCB[task_ID].cpu_reserve; nrk_task_TCB[task_ID].task_state = READY; nrk_task_TCB[task_ID].next_wakeup = nrk_task_TCB[task_ID].next_period; // If there is no period set, don't wakeup periodically if(nrk_task_TCB[task_ID].period==0) nrk_task_TCB[task_ID].next_wakeup = MAX_SCHED_WAKEUP_TIME; nrk_add_to_readyQ(task_ID); } else { nrk_task_TCB[task_ID].cpu_remaining = nrk_task_TCB[task_ID].cpu_reserve; //nrk_task_TCB[task_ID].next_wakeup = nrk_task_TCB[task_ID].next_period; //nrk_task_TCB[task_ID].num_periods--; nrk_task_TCB[task_ID].next_wakeup = (nrk_task_TCB[task_ID].period*(nrk_task_TCB[task_ID].num_periods-1)); nrk_task_TCB[task_ID].next_period = (nrk_task_TCB[task_ID].period*(nrk_task_TCB[task_ID].num_periods-1)); if(nrk_task_TCB[task_ID].period==0) nrk_task_TCB[task_ID].next_wakeup = MAX_SCHED_WAKEUP_TIME; nrk_task_TCB[task_ID].num_periods=1; // printf( "np = %d\r\n",nrk_task_TCB[task_ID].next_wakeup); // nrk_task_TCB[task_ID].num_periods=1; } } if(nrk_task_TCB[task_ID].next_wakeup!=0 && nrk_task_TCB[task_ID].next_wakeup<next_wake ) { // Find closest next_wake task next_wake=nrk_task_TCB[task_ID].next_wakeup; } } } #ifdef NRK_STATS_TRACKER _nrk_stats_task_start(nrk_cur_task_TCB->task_ID); #endif task_ID = nrk_get_high_ready_task_ID(); nrk_high_ready_prio = nrk_task_TCB[task_ID].task_prio; nrk_high_ready_TCB = &nrk_task_TCB[task_ID]; // next_wake should hold next time when a suspended task might get run // task_ID holds the highest priority READY task ID // So nrk_task_TCB[task_ID].cpu_remaining holds the READY task's end time // Now we pick the next wakeup (either the end of the current task, or the possible resume // of a suspended task) if(task_ID!=NRK_IDLE_TASK_ID) { // You are a non-Idle Task if(nrk_task_TCB[task_ID].cpu_reserve!=0 && nrk_task_TCB[task_ID].cpu_remaining<MAX_SCHED_WAKEUP_TIME) { if(next_wake>nrk_task_TCB[task_ID].cpu_remaining) next_wake=nrk_task_TCB[task_ID].cpu_remaining; } else { if(next_wake>MAX_SCHED_WAKEUP_TIME) next_wake=MAX_SCHED_WAKEUP_TIME; } } else { // This is the idle task // Make sure you wake up from the idle task a little earlier // if you would go into deep sleep... // After waking from deep sleep, the next context swap must be at least // NRK_SLEEP_WAKEUP_TIME-1 away to make sure the CPU wakes up in time. #ifndef NRK_NO_POWER_DOWN if(next_wake>NRK_SLEEP_WAKEUP_TIME) { if(next_wake-NRK_SLEEP_WAKEUP_TIME<MAX_SCHED_WAKEUP_TIME) { if(next_wake-NRK_SLEEP_WAKEUP_TIME<NRK_SLEEP_WAKEUP_TIME) { next_wake=NRK_SLEEP_WAKEUP_TIME-1; } else { next_wake=next_wake-NRK_SLEEP_WAKEUP_TIME; } } else if(next_wake>NRK_SLEEP_WAKEUP_TIME+MAX_SCHED_WAKEUP_TIME) { next_wake=MAX_SCHED_WAKEUP_TIME; } else { next_wake=MAX_SCHED_WAKEUP_TIME-NRK_SLEEP_WAKEUP_TIME; } } #endif } /* // Some code to catch the case when the scheduler wakes up // from deep sleep and has to execute again before NRK_SLEEP_WAKEUP_TIME-1 if(_nrk_cpu_state==2 && next_wake<NRK_SLEEP_WAKEUP_TIME-1) { nrk_int_disable(); while(1) { nrk_spin_wait_us(60000); nrk_led_toggle(RED_LED); nrk_spin_wait_us(60000); nrk_led_toggle(GREEN_LED); printf( "crash: %d %d %d\r\n",task_ID,next_wake,_nrk_cpu_state); } }*/ // If we disable power down, we still need to wakeup before the overflow #ifdef NRK_NO_POWER_DOWN if(next_wake>MAX_SCHED_WAKEUP_TIME) next_wake=MAX_SCHED_WAKEUP_TIME; #endif //printf( "nw = %d %d %d\r\n",task_ID,_nrk_cpu_state,next_wake); nrk_cur_task_prio = nrk_high_ready_prio; nrk_cur_task_TCB = nrk_high_ready_TCB; #ifdef NRK_KERNEL_TEST if(nrk_high_ready_TCB==NULL) { nrk_kprintf( PSTR( "KERNEL TEST: BAD TCB!\r\n" )); } #endif //printf( "n %u %u %u %u\r\n",task_ID, _nrk_prev_timer_val, next_wake,_nrk_os_timer_get()); _nrk_prev_timer_val=next_wake; if((_nrk_os_timer_get()+1)>=next_wake) // just bigger then, or equal? { // FIXME: Terrible Terrible... // Need to find out why this is happening... #ifdef NRK_KERNEL_TEST // Ignore if you are the idle task coming from deep sleep if(!(task_ID==NRK_IDLE_TASK_ID && _nrk_cpu_state==CPU_SLEEP)) nrk_kernel_error_add(NRK_WAKEUP_MISSED,task_ID); #endif // This is bad news, but keeps things running // +2 just in case we are on the edge of the last tick next_wake=_nrk_os_timer_get()+2; _nrk_prev_timer_val=next_wake; } if(task_ID!=NRK_IDLE_TASK_ID) _nrk_cpu_state=CPU_ACTIVE; _nrk_set_next_wakeup(next_wake); #ifndef NRK_NO_BOUNDED_CONTEXT_SWAP // Bound Context Swap to 100us nrk_high_speed_timer_wait(start_time_stamp,CONTEXT_SWAP_TIME_BOUND); #endif nrk_stack_pointer_restore(); //nrk_int_enable(); nrk_start_high_ready_task(); }
void gateway_task () { uint8_t i, len; int8_t rssi, val; uint8_t *local_rx_tx_buf; uint16_t batt; nrk_time_t check_period, wait_time; uint16_t buf; int8_t fd; uint8_t j, cnt, level; nrk_sig_t tx_done_signal; nrk_sig_mask_t ret; nrk_time_t next_transmit_time; nrk_time_t current_time; nrk_time_t prev_time; char tmp[4]; printf ("gateway_task PID=%d\r\n", nrk_get_pid ()); next_transmit_time.secs = 0; next_transmit_time.nano_secs = 0; // init bmac on channel 25 bmac_init (26); // By default the RX check rate is 100ms // below shows how to change that check_period.secs=0; check_period.nano_secs=100*NANOS_PER_MS; val=bmac_set_rx_check_rate(check_period); // The default Clear Channel Assement RSSI threshold is -32 // Setting this value higher means that you will only trigger // receive with a very strong signal. Setting this lower means // bmac will try to receive fainter packets. If the value is set // too high or too low performance will suffer greatly. // bmac_set_cca_thresh(-36); if(val==NRK_ERROR) nrk_kprintf( PSTR("ERROR setting bmac rate\r\n" )); // This sets the next RX buffer. // This can be called at anytime before releaseing the packet // if you wish to do a zero-copy buffer switch bmac_rx_pkt_set_buffer (rx_buf, RF_MAX_PAYLOAD_SIZE); // Get and register the tx_done_signal if you want to // do non-blocking transmits tx_done_signal = bmac_get_tx_done_signal (); nrk_signal_register (tx_done_signal); nrk_time_set(0, 0); cnt = 0; // Initially clear all the data buffers for(i=0; i<(MAX_NODES);i++) { for(j=0; j<(WORDS_PER_NODE); j++) { data_pkt.node_specific_data[i][j] = 0; } } while (1) { nrk_time_get(¤t_time); // If it is time to flood the network, send the control packets if(current_time.secs%FLOOD_RATE == 0 && prev_time.secs != current_time.secs || cnt == 0) { prev_time = current_time; cnt ++; SET_PACKET_COUNT(pkt_buf.pkt_type_cnt, cnt); #if MODE==DATA_MODE SET_PACKET_TYPE(pkt_buf.pkt_type_cnt, PKT_TYPE_CONTROL); #else SET_PACKET_TYPE(pkt_buf.pkt_type_cnt, PKT_TYPE_DIAG_CONTROL); #endif pkt_buf.hop_number = 0; pkt_buf.time_to_flood = TIME_TO_FLOOD_IN_SECS; pkt_buf.bmac_check_rate = BMAC_CHECK_RATE_IN_MS; pkt_buf.maximum_depth = MAXIMUM_DEPTH; pkt_buf.delay_at_each_level = DELAY_AT_EACH_LEVEL_IN_SECS; pkt_buf.next_control_time = NEXT_CONTROL_TIME; pkt_buf.data_push_rate = 0; for(i=0; i<(MAX_NODES);i++) { for(j=0; j<(WORDS_PER_NODE); j++) { #if MODE==DATA_MODE pkt_buf.node_specific_data[i][j] = SENSOR; #else pkt_buf.node_specific_data[i][j] = 0; #endif } } memcpy(tx_buf, &pkt_buf, sizeof(pkt_buf)); // Non-blocking send nrk_led_set (BLUE_LED); val = bmac_tx_pkt_nonblocking (tx_buf, sizeof(struct message_packet)); nrk_kprintf (PSTR ("Tx packet enqueued\r\n")); ret = nrk_event_wait (SIG(tx_done_signal)); if(ret & SIG(tx_done_signal) == 0 ) nrk_kprintf (PSTR ("TX done signal error\r\n")); nrk_led_clr (BLUE_LED); } // If a new packet has been received, then update the information if(bmac_rx_pkt_ready()) { // Wait until an RX packet is received nrk_led_set (ORANGE_LED); // Get the RX packet local_rx_tx_buf = bmac_rx_pkt_get (&len, &rssi); for (i = 0; i < len; i++) printf ("%d", rx_buf[i]); printf ("\r\n"); memcpy(&pkt_buf, rx_buf, sizeof(pkt_buf)); nrk_led_clr (ORANGE_LED); // Release the RX buffer so future packets can arrive bmac_rx_pkt_release (); // If the received packet is a data packet then update the information, gateway just ignores the control packets if(GET_PACKET_TYPE(pkt_buf.pkt_type_cnt) == PKT_TYPE_DIAG_DATA || GET_PACKET_TYPE(pkt_buf.pkt_type_cnt) == PKT_TYPE_DATA) { printf("Type = %d\n\r", GET_PACKET_TYPE(pkt_buf.pkt_type_cnt)); printf("Count = %d\n\r", GET_PACKET_COUNT(pkt_buf.pkt_type_cnt)); printf("Hop # = %d\n\r", pkt_buf.hop_number); printf("TTF = %d\n\r", pkt_buf.time_to_flood); printf("BCR = %d\n\r", pkt_buf.bmac_check_rate); printf("Nmax = %d\n\r", pkt_buf.maximum_depth); printf("Dlev = %d\n\r", pkt_buf.delay_at_each_level); printf("Nxt = %d\n\r", pkt_buf.next_control_time); printf("Prate = %d\n\r", pkt_buf.data_push_rate); for(i=0; i<(MAX_NODES);i++) { for(j=0; j<(WORDS_PER_NODE); j++) { if(pkt_buf.node_specific_data[i][j] != 0) data_pkt.node_specific_data[i][j] = pkt_buf.node_specific_data[i][j]; } } for(i=0; i<(MAX_NODES);i++) { printf("Value @ Node %d is %d (cnt is %d)", i, ((int16_t)data_pkt.node_specific_data[i][1]<<4), (data_pkt.node_specific_data[i][0]&0x3F)); printf("\n\r"); } } } } }
static void discover_task () { uint8_t periods_in_idle = discover_period_s / DISCOVER_TASK_PERIOD_S; nrk_time_t now, elapsed; int8_t rc; while (1) { switch (discover_state) { case DISCOVER_IDLE: if (auto_discover) { if (periods_in_idle < periods_in_idle) break; set_state(DISCOVER_SCHEDULED); } break; case DISCOVER_SCHEDULED: #if ENABLE_LED pulse_led(led_discover); #endif set_state(DISCOVER_PENDING); nrk_event_signal(discover_signal); break; case DISCOVER_IN_PROGRESS: nrk_time_get(&now); nrk_time_sub(&elapsed, now, last_activity); if (time_cmp(&elapsed, &discover_time_out) < 0) { LOG("silent for "); LOGP("%lu ms\r\n", TIME_TO_MS(elapsed)); break; } LOG("finished, distrib routes: seq "); LOGP("%d\r\n", outstanding_seq); print_graph(&network); rc = calc_routes(&network, &routes); if (rc == NRK_OK) { print_routes(&routes); rc = broadcast_routes(&routes, outstanding_seq); if (rc != NRK_OK) LOG("WARN: failed to bcast routes\r\n"); } else { LOG("WARN: failed to calc routes\r\n"); } set_state(DISCOVER_COMPLETED); nrk_event_signal(discover_signal); break; case DISCOVER_PENDING: case DISCOVER_COMPLETED: /* the router failed to do its part in one task period */ set_state(DISCOVER_IDLE); break; default: ABORT("unexpected state\r\n"); } periods_in_state++; nrk_wait_until_next_period(); } ABORT("discover task exited\r\n"); }
void nl_tx_task() { TransmitBuffer *ptr = NULL; // pointer to the buffer to be transmitted nrk_sig_t tx_done_signal; // to hold the tx_done signal from the link layer int8_t ret; // to hold the return value of various functions int8_t port_index; // to store the index of the corresponding port element int8_t sent; // to count the number of times the HELLO msg was sent int8_t isApplication; // flag to indicate whether the packet in the transmit // buffer is an APPLICATION / NW_CONTROL packet nrk_time_t timeout; nrk_time_t start; // used for sending network control messages nrk_time_t end; nrk_time_t elapsed; // wait for the nl_rx_task to start bmac while(!bmac_started()) nrk_wait_until_next_period(); // retrieve and register for the 'transmit done' signal from bmac tx_done_signal = bmac_get_tx_done_signal(); if( nrk_signal_register(tx_done_signal) == NRK_ERROR ) { nrk_int_disable(); nrk_led_set(RED_LED); while(1) nrk_kprintf(PSTR("NL: Error while registering for the bmax_tx_done_signal\r\n")); } // initialise the timer nrk_time_get(&start); end.secs = start.secs; end.nano_secs = start.nano_secs; sent = 0; // set the radio power if( bmac_set_rf_power(10) == NRK_ERROR) { nrk_led_set(RED_LED); nrk_int_disable(); while(1) nrk_kprintf(PSTR("Error setting the transmit power\r\n")); } while(1) { isApplication = FALSE; // assume at the beginning that a nw_ctrl pkt will be transmitted ret = nrk_time_sub(&elapsed, end, start); if(ret == 0) { nrk_int_disable(); nrk_led_set(RED_LED); while(1) nrk_kprintf(PSTR("NL: Error returned by nrk_time_sub\r\n")); } nrk_time_compact_nanos(&elapsed); if(elapsed.secs >= HELLO_PERIOD) { sent++; build_Msg_Hello(&mhe); // build the 'HELLO' message if(DEBUG_NL == 2) { nrk_kprintf(PSTR("After building Msg_Hello, packet = ")); print_pkt(&pkt_tx); } enter_cr(bm_sem, 34); ret = insert_tx_aq(&pkt_tx); // insert it into the transmit queue leave_cr(bm_sem, 34); if(DEBUG_NL == 2) { nrk_kprintf(PSTR("build_Msg_Hello() inserted packet.")); print_tx_buffer(); //print_pkt_header(&pkt_tx); } if(ret == NRK_ERROR && DEBUG_NL == 2) { nrk_kprintf(PSTR("HELLO msg was not inserted into the transmit queue\r\n")); } start.secs = end.secs; start.nano_secs = end.nano_secs; // reinitialise the timer } if(sent >= 3) //NGB_LIST_PERIOD / HELLO_PERIOD) // NGB_LIST period is always a multiple of HELLO_PERIOD { build_Msg_NgbList(&mn); // build the 'NGB_LIST' message enter_cr(bm_sem, 34); ret = insert_tx_aq(&pkt_tx); // insert it into the transmit queue leave_cr(bm_sem, 34); if(DEBUG_NL == 2) { nrk_kprintf(PSTR("build_Msg_NgbList() inserted packet.")); print_tx_buffer(); //print_pkt_header(&pkt_tx); } if(ret == NRK_ERROR && DEBUG_NL == 2) { nrk_kprintf(PSTR("NGB_LIST msg was not inserted into the transmit queue\r\n")); } sent = 0; // reset the value of 'sent' } if(rand() % 2 == 0) // random number generator collect_queue_statistics(); enter_cr(bm_sem, 34); ptr = remove_tx_aq(); leave_cr(bm_sem, 34); if(ptr == NULL) // transmit queue is empty { if(DEBUG_NL == 2) nrk_kprintf(PSTR("NL:Transmit queue is empty\r\n")); // update the end time nrk_time_get(&end); nrk_wait_until_next_period(); // FIX ME continue; } if(DEBUG_NL == 2) { nrk_kprintf(PSTR("NL: nl_tx_task(): Packet removed. Packet = ")); //print_pkt_header( &(ptr -> pkt) ); print_pkt( &(ptr -> pkt) ); //print_tx_buffer(); } // check to see the type of packet. It should be of type APPLICATION and be sent by this // node if( (pkt_type(&(ptr -> pkt)) == APPLICATION) && ((ptr -> pkt).src == NODE_ADDR) ) { // remove the encapsulated TL segment from the packet unpack_TL_UDP_header(&seg, (ptr -> pkt).data); memcpy(seg.data, (ptr -> pkt).data + SIZE_TRANSPORT_UDP_HEADER, MAX_APP_PAYLOAD); if(DEBUG_NL == 2) { nrk_kprintf(PSTR("NL: nl_tx_task(): Segment Removed = ")); print_seg(&seg); } isApplication = TRUE; } // pack the network packet header into the transmit buffer pack_NW_Packet_header(tx_buf, &(ptr -> pkt)); // append the network payload into the transmit buffer memcpy(tx_buf + SIZE_NW_PACKET_HEADER, (ptr -> pkt).data, MAX_NETWORK_PAYLOAD); enter_cr(bm_sem, 34); insert_tx_fq(ptr); // release the transmit buffer into the free queue leave_cr(bm_sem, 34); if(DEBUG_NL == 2) { nrk_kprintf(PSTR("NL: nl_tx_task(): Released transmit buffer back into queue\n")); print_tx_buffer(); } do { ret = bmac_tx_pkt_nonblocking(tx_buf, SIZE_NW_PACKET); // try to queue the buffer in link layer if(ret == NRK_ERROR) if(nrk_event_wait(SIG(tx_done_signal)) == 0) { nrk_int_disable(); nrk_led_set(RED_LED); while(1) nrk_kprintf(PSTR("NL: Error returned by nrk_event_wait(tx_done_signal)\r\n")); } }while(ret == NRK_ERROR); // packet is queued at link layer timeout.secs = 10; // set a wait period of maximum 10 seconds timeout.nano_secs = 0; if( nrk_signal_register(nrk_wakeup_signal) == NRK_ERROR ) { nrk_int_disable(); nrk_led_set(RED_LED); while(1) nrk_kprintf(PSTR("NL:nl_tx(): Error registering for nrk_wakeup_signal\r\n")); } if( nrk_set_next_wakeup(timeout) == NRK_ERROR) { nrk_int_disable(); nrk_led_set(RED_LED); while(1) nrk_kprintf(PSTR("NL: nl_tx(): Error returned by nrk_set_next_wakeup()\r\n")); } nrk_led_set(BLUE_LED); ret = nrk_event_wait (SIG(tx_done_signal) | SIG(nrk_wakeup_signal)); // wait for its transmission if(ret == 0) { nrk_int_disable(); nrk_led_set(RED_LED); while(1) nrk_kprintf(PSTR("NL: Error returned by nrk_event_wait(tx_done_signal)\r\n")); } if(ret & SIG(tx_done_signal)) // bmac has successfully sent the packet over the radio { if(isApplication == TRUE) // it was an application layer packet { enter_cr(tl_sem, 34); port_index = port_to_port_index(seg.srcPort); if(port_index == NRK_ERROR) // sanity check { nrk_int_disable(); nrk_led_set(RED_LED); while(1) nrk_kprintf(PSTR("NL: nl_tx_task: Bug detected in implementation of port element array\r\n")); } // signal 'send done' signal if(nrk_event_signal(ports[port_index].send_done_signal) == NRK_ERROR) { if(nrk_errno_get() == 1) // sanity check. This means signal was not created { nrk_int_disable(); nrk_led_set(RED_LED); while(1) nrk_kprintf(PSTR("NL: nl_tx_task: Bug detected in creating signals in port element array\r\n")); } } leave_cr(tl_sem, 34); }// end if(isApplication == TRUE) else // a network control message was transmitted. Nothing to signal ; // do nothing } // end if(signal received = tx_done_signal) else if(ret & SIG(nrk_wakeup_signal)) { //nrk_led_set(RED_LED); //nrk_int_disable(); //while(1) //{ nrk_kprintf(PSTR("BMAC did not transmit the packet within specified time\r\n")); //} } else // unknown signal caught { nrk_int_disable(); nrk_led_set(RED_LED); while(1) nrk_kprintf(PSTR("NL: nl_tx_task(): Unknown signal caught\r\n")); } nrk_led_clr(BLUE_LED); // update the end time nrk_time_get(&end); } // end while(1) return; }
void Task1() { int8_t rssi, slot,length; //all parameters recieved along with an rx printf( "Task1 PID=%d\r\n",nrk_get_pid()); printf( "Node ID=%d\r\n",NODE_ID); nrk_led_set(RED_LED); rtl_init (RTL_COORDINATOR); rtl_set_channel(MY_CHANNEL); rtl_set_schedule( RTL_RX, NODE_2_RX_SLOT, 1 ); rtl_set_schedule( RTL_RX, NODE_3_RX_SLOT, 1 ); rtl_set_schedule( RTL_TX, MY_TX_SLOT, 1 ); //rtl_set_tx_power(MAX_POWER); rtl_rx_pkt_set_buffer(rx_buf, RF_MAX_PAYLOAD_SIZE); //to limit payload size rtl_start(); while(!rtl_ready()) nrk_wait_until_next_period(); while(1) { if( rtl_tx_pkt_check(MY_TX_SLOT)!=0 ) { //printf("Pending TX"); } else { nrk_time_get(¤tTime); if(currentTime.secs-exchangeTime.secs>EXCHANGE_INTERVAL) { //TODO:Data to be transmitted int8_t length; //sprintf( &tx_buf[PKT_DATA_START],"",); length = sprintf(&tx_buf[PKT_DATA_START], "%-+5d%-+5d",myX,myY); //TODO: Data printf ("(%s) is the result of our sprintf, which is %d characters long",tx_buf,length); length=length+PKT_DATA_START+1; printf("Sending: "); /* for(int i=PKT_DATA_START; i<length; i++ )*/ /* {*/ /* printf("%c",tx_buf[i] );*/ /* }*/ /* printf("\n\r");*/ addToTXBuffer(tx_buf,length); nrk_time_get(&exchangeTime); } fetchTxBuffer(); //Actual Transmit nrk_led_toggle(BLUE_LED); } if( rtl_rx_pkt_check()!=0 ) { int8_t senderNode; nrk_led_set(ORANGE_LED); uint8_t *local_rx_buf; local_rx_buf=rtl_rx_pkt_get(&length, &rssi, &slot); printf( "Got Packet on slot %d %d: ",slot,length ); senderNode=slot/2; if(senderNode==0) { int li = atoi (&local_rx_buf[NODE_ID]); printf ("\nXrecd=%d",li); myX=li; li = atoi (&local_rx_buf[NODE_ID+5]); printf ("\nYrecd=%d",li); myY=li; } else { int li = atoi (&local_rx_buf[NODE_ID]); printf ("\nXrecd=%d",li); X[senderNode]=li; li = atoi (&local_rx_buf[NODE_ID+5]); printf ("\nYrecd=%d",li); Y[senderNode]=li; } } rtl_wait_until_rx_or_tx(); } }
void pingMode() { // Broadcast for ping val=bmac_addr_decode_set_my_mac(((uint16_t)my_subnet_mac<<8)|my_mac); val=bmac_addr_decode_dest_mac((uint16_t)0xffff); // broadcast by default bmac_addr_decode_enable(); uint8_t i; // Build a TX packet by hand... p2p_pkt.pkt_type = PING_PKT; // set as p2p packet (no US_MASK or DS_MASK) p2p_pkt.ctrl_flags = MOBILE_MASK ; // | DEBUG_FLAG ; p2p_pkt.ack_retry= 0x00; p2p_pkt.ttl = 1; p2p_pkt.src_subnet_mac[0] = 0; p2p_pkt.src_subnet_mac[1] = 0; p2p_pkt.src_subnet_mac[2] = 0; p2p_pkt.src_mac = my_mac; p2p_pkt.last_hop_mac = my_mac; p2p_pkt.dst_subnet_mac[0] = BROADCAST; p2p_pkt.dst_subnet_mac[1] = BROADCAST; p2p_pkt.dst_subnet_mac[2] = BROADCAST; p2p_pkt.dst_mac = BROADCAST; p2p_pkt.buf=tx_buf; p2p_pkt.buf_len = P2P_PAYLOAD_START; p2p_pkt.seq_num = cnt; p2p_pkt.priority = 0; cnt++; // p2p_pkt.payload[0]=my_mac; // p2p_pkt.payload_len=1; // ping_p2p_generate(&p2p_pkt); nrk_led_set (BLUE_LED); check_period.secs = 0; check_period.nano_secs = 100 * NANOS_PER_MS; val = bmac_set_rx_check_rate (check_period); // Pack data structure values in buffer before transmit pack_peer_2_peer_packet(&p2p_pkt); // For blocking transmits, use the following function call. val = bmac_tx_pkt (p2p_pkt.buf, p2p_pkt.buf_len); check_period.secs = 0; check_period.nano_secs = FAST_CHECK_RATE * NANOS_PER_MS; val = bmac_set_rx_check_rate (check_period); #ifdef TXT_DEBUG nrk_kprintf (PSTR ("\r\nPING Packet Sent. Waiting for Replies...\r\n\n")); #endif nrk_led_clr (BLUE_LED); nrk_led_clr(GREEN_LED); // Wait for packets or timeout nrk_time_get (&start); while (1) { timeout.secs = PING_WAIT_SECS; timeout.nano_secs = 0; // Wait until an RX packet is received //val = bmac_wait_until_rx_pkt (); nrk_set_next_wakeup (timeout); my_sigs = nrk_event_wait (SIG (rx_signal) | SIG (nrk_wakeup_signal)); if (my_sigs == 0) nrk_kprintf (PSTR ("Error calling nrk_event_wait()\r\n")); if (my_sigs & SIG (rx_signal)) { // Get the RX packet local_rx_buf = bmac_rx_pkt_get (&len, &rssi); // Check the packet type from raw buffer before unpacking if ((local_rx_buf[CTRL_FLAGS] & (DS_MASK | US_MASK)) == 0) { // Set the buffer p2p_pkt.buf=local_rx_buf; p2p_pkt.buf_len=len; p2p_pkt.rssi=rssi; unpack_peer_2_peer_packet(&p2p_pkt); if (p2p_pkt.dst_mac == my_mac || p2p_pkt.dst_mac == BROADCAST) { nrk_led_set(GREEN_LED); // Packet arrived and is good to go printf( "Mac: %x%x%x",p2p_pkt.src_subnet_mac[0], p2p_pkt.src_subnet_mac[1], p2p_pkt.src_subnet_mac[2]); printf( "%x ",p2p_pkt.src_mac); printf( "| RSSI: %d ",p2p_pkt.rssi); printf( "| Type: %d \r\n",p2p_pkt.pkt_type); } } // Release the RX buffer so future packets can arrive bmac_rx_pkt_release (); } nrk_time_get (¤t); if (start.secs + PING_WAIT_SECS < current.secs) break; } nrk_kprintf (PSTR ("\r\nDone Waiting for Response...\r\n")); nrk_led_clr(GREEN_LED); }
static void periodic_task() { nrk_sig_mask_t wait_mask, func_wait_mask; nrk_time_t next_event, func_next_event; periodic_func_t **funcp; periodic_func_t *func; nrk_time_t now, sleep_time; int8_t rc; funcp = &functions[0]; while (*funcp) { func = *funcp; LOG("init: "); LOGF(func->name); LOGNL(); if (func->init) func->init(); funcp++; } rc = nrk_signal_register(func_signal); if (rc == NRK_ERROR) ABORT("reg sig: func\r\n"); while (1) { LOG("awake\r\n"); TIME_CLEAR(next_event); wait_mask = SIG(func_signal); funcp = &functions[0]; while (*funcp) { func = *funcp; TIME_CLEAR(func_next_event); func_wait_mask = 0; if (func->enabled || func->enabled != func->last_enabled) { LOG("proc: "); LOGF(func->name); LOGNL(); ASSERT(func->proc); func->proc(func->enabled, &func_next_event, &func_wait_mask); } func->last_enabled = func->enabled; wait_mask |= func_wait_mask; if (IS_VALID_TIME(func_next_event) && (!IS_VALID_TIME(next_event) || time_cmp(&func_next_event, &next_event) < 0)) { next_event = func_next_event; } funcp++; } if (IS_VALID_TIME(next_event)) { nrk_time_get(&now); rc = nrk_time_sub(&sleep_time, next_event, now); if (rc != NRK_OK) { LOG("next event in the past\r\n"); continue; } LOG("sleeping for: "); LOGP("%lu ms\r\n", TIME_TO_MS(sleep_time)); nrk_set_next_wakeup(sleep_time); wait_mask |= SIG(nrk_wakeup_signal); } LOG("waiting\r\n"); nrk_event_wait( wait_mask ); } ABORT("periodic task exited\r\n"); }
void tdma_nw_task () { int8_t v, i; uint16_t slot, tmp,sync; nrk_sig_mask_t event; do { nrk_wait_until_next_period (); } while (!tdma_started ()); _tdma_slot_time.nano_secs = TDMA_DEFAULT_SLOT_MS * NANOS_PER_MS; _tdma_slot_time.secs = 0; //register the signal after bmac_init has been called v = nrk_signal_register (tdma_enable_signal); if (v == NRK_ERROR) nrk_kprintf (PSTR ("Failed to register signal\r\n")); slot = 0; //rf_set_rx (&tdma_rfRxInfo, tdma_chan); while (1) { if (tdma_mode == TDMA_HOST) { sync_status=1; // HOST is always synced // This is the downstream transmit slot if (slot == 0) { //rf_rx_off(); // If there is no pending packet, lets make an empty one if (tx_data_ready == 0) { tdma_rfTxInfo.pPayload = tdma_tx_buf; // Setup the header data tdma_rfTxInfo.pPayload[TDMA_DST_LOW] = 0xff; // dst tdma_rfTxInfo.pPayload[TDMA_DST_HIGH] = 0xff; tdma_rfTxInfo.pPayload[TDMA_SRC_LOW] = 0x00; // src tdma_rfTxInfo.pPayload[TDMA_SRC_HIGH] = 0x00; tdma_rfTxInfo.pPayload[TDMA_SEQ_NUM_LOW] = 0x00; // seq num tdma_rfTxInfo.pPayload[TDMA_SEQ_NUM_HIGH] = 0x00; tdma_rfTxInfo.length = TDMA_PCF_HEADER; } tdma_rfTxInfo.pPayload[TDMA_CYCLE_SIZE_LOW] = tdma_slots_per_cycle & 0xff; // cycle size tdma_rfTxInfo.pPayload[TDMA_CYCLE_SIZE_HIGH] = tdma_slots_per_cycle >> 8; tdma_rfTxInfo.pPayload[TDMA_SLOT_LOW] = 0; // slot tdma_rfTxInfo.pPayload[TDMA_SLOT_HIGH] = 0; tdma_rfTxInfo.pPayload[TDMA_SLOT_SIZE] = tdma_slot_len_ms; nrk_time_get (&_tdma_next_wakeup); tdma_rfTxInfo.destAddr = 0xffff; tdma_rfTxInfo.ackRequest = 0; tdma_rfTxInfo.cca = 0; _tdma_tx (); rf_rx_on (); } else { // Upstream data slot v = _tdma_rx (); if (v == 1) tdma_last_tx_slot = slot; } slot++; if (slot >= tdma_slots_per_cycle + 1) slot = 0; nrk_time_add (&_tdma_next_wakeup, _tdma_next_wakeup, _tdma_slot_time); nrk_time_compact_nanos (&_tdma_next_wakeup); nrk_wait_until (_tdma_next_wakeup); }