int8_t nrk_TCB_init (nrk_task_type *Task, NRK_STK *ptos, NRK_STK *pbos, uint16_t stk_size, void *pext, uint16_t opt) { // Already in critical section so no needenter critical section if(Task->Type!=IDLE_TASK) Task->task_ID=nrk_task_init_cnt; else Task->task_ID=NRK_IDLE_TASK_ID; if(nrk_task_init_cnt>=NRK_MAX_TASKS) nrk_kernel_error_add(NRK_EXTRA_TASK,0); if(Task->Type!=IDLE_TASK) nrk_task_init_cnt++; if(nrk_task_init_cnt==NRK_IDLE_TASK_ID) nrk_task_init_cnt++; //initialize member of TCB structure nrk_task_TCB[Task->task_ID].OSTaskStkPtr = ptos; nrk_task_TCB[Task->task_ID].task_prio = Task->prio; nrk_task_TCB[Task->task_ID].task_state = SUSPENDED; nrk_task_TCB[Task->task_ID].task_prelevel = Task->prelevel; nrk_task_TCB[Task->task_ID].task_ID = Task->task_ID; nrk_task_TCB[Task->task_ID].suspend_flag = 0; nrk_task_TCB[Task->task_ID].period= _nrk_time_to_ticks( &(Task->period) ); if(Task->period.secs > 61) nrk_kernel_error_add(NRK_PERIOD_OVERFLOW,Task->task_ID); nrk_task_TCB[Task->task_ID].next_wakeup= _nrk_time_to_ticks( &(Task->offset)); nrk_task_TCB[Task->task_ID].next_period= nrk_task_TCB[Task->task_ID].period+nrk_task_TCB[Task->task_ID].next_wakeup; nrk_task_TCB[Task->task_ID].cpu_reserve= _nrk_time_to_ticks(&(Task->cpu_reserve)); nrk_task_TCB[Task->task_ID].cpu_remaining = nrk_task_TCB[Task->task_ID].cpu_reserve; nrk_task_TCB[Task->task_ID].num_periods = 1; nrk_task_TCB[Task->task_ID].OSTCBStkBottom = pbos; nrk_task_TCB[Task->task_ID].errno= NRK_OK; return NRK_OK; }
int8_t nrk_TCB_init(nrk_task_type *Task, NRK_STK *ptos, NRK_STK *pbos, uint16_t stk_size, void *pext, uint16_t opt) //////////NRK_TCB *nrk_TCB_init(nrk_task_type *Task, NRK_STK *ptos, NRK_STK *pbos, uint16_t stk_size, void *pext, uint16_t opt) { NRK_TCB *newTCB;///////////// = malloc(sizeof(NRK_TCB)); // Already in critical section so no needenter critical section if(Task->Type!=IDLE_TASK){ //check for task id conflict..fix srinivas check_taskID_conflict(); Task->task_ID=nrk_task_init_cnt; } else Task->task_ID=NRK_IDLE_TASK_ID; ////////// if(nrk_task_init_cnt>=NRK_MAX_TASKS_TCB) nrk_kernel_error_add(NRK_EXTRA_TASK,0); // if(tasksNumber>=NRK_MAX_TASKS_ALLOWED) nrk_kernel_error_add(NRK_EXTRA_TASK,0); if(Task->Type!=IDLE_TASK) { nrk_task_init_cnt++; newTCB = &mallocTCBs[tasksNumber-1];//malloc(sizeof(NRK_TCB)); //newTCB = (NRK_TCB *)nrk_malloc(sizeof(NRK_TCB)); tasksNumber++; }//PAJA:Check, 2 loooks the same, put in the same if part !!!!! optimize else { newTCB = &nrk_task_TCB; } //initialize member of TCB structure //Paja: Check this in CS ////////// newTCB = &nrk_task_TCB[Task->task_ID]; Task->taskTCB = newTCB; if (Task->Type!=IDLE_TASK) { _tailTCB->Next = newTCB; newTCB->Prev = _tailTCB; newTCB->Next = NULL; _tailTCB = newTCB; } newTCB->OSTaskStkPtr = ptos; newTCB->task_prio = Task->prio; newTCB->task_state = SUSPENDED; newTCB->event_suspend=0;//fix srinivas newTCB->SchType=Task->SchType;//fix srinivas newTCB->task_ID = Task->task_ID; newTCB->suspend_flag = 0; newTCB->period= _nrk_time_to_ticks( Task->period ); newTCB->next_wakeup= _nrk_time_to_ticks( Task->offset); newTCB->next_period= newTCB->period+newTCB->next_wakeup; newTCB->cpu_reserve= _nrk_time_to_ticks(Task->cpu_reserve); newTCB->cpu_remaining = newTCB->cpu_reserve; newTCB->num_periods = 1; newTCB->OSTCBStkBottom = pbos; newTCB->errno= NRK_OK; return NRK_OK; ////// return newTCB; }
int8_t _bmac_tx() { uint8_t v,backoff, backoff_count; uint16_t b; #ifdef DEBUG nrk_kprintf( PSTR("_bmac_tx()\r\n")); #endif if(cca_active) { // Add random time here to stop nodes from synchronizing with eachother b=_nrk_time_to_ticks(&_bmac_check_period); b=b/((rand()%10)+1); //printf( "waiting %d\r\n",b ); nrk_wait_until_ticks(b); //nrk_wait_ticks(b); backoff_count=1; do{ v=_bmac_channel_check(); rf_rx_off(); if(v==1) break; // Channel is busy backoff=rand()%(_b_pow(backoff_count)); #ifdef DEBUG printf( "backoff %d\r\n",backoff ); #endif // printf( "backoff %d\r\n",backoff ); nrk_wait_until_next_n_periods(backoff); backoff_count++; if(backoff_count>6) backoff_count=6; // cap it at 64 b=_nrk_time_to_ticks(&_bmac_check_period); b=b/((rand()%10)+1); // printf( "waiting %d\r\n",b ); nrk_wait_until_ticks(b); // nrk_wait_ticks(b); } while(v==0); } rf_test_mode(); rf_carrier_on(); nrk_wait(_bmac_check_period); //nrk_wait_until_next_period(); rf_carrier_off(); rf_data_mode(); // send packet rf_rx_off(); pkt_got_ack=rf_tx_packet (&bmac_rfTxInfo); rf_rx_off(); tx_data_ready=0; nrk_event_signal (bmac_tx_pkt_done_signal); return NRK_OK; }
int8_t _bmac_tx() { uint8_t v,result, backoff, backoff_count; uint16_t b; if(cca_active) { // Add random time here to stop nodes from synchronizing with eachother b=_nrk_time_to_ticks(&_bmac_check_period); b=b/((rand()%10)+1); //printf( "waiting %d\r\n",b ); nrk_wait_until_ticks(b); //nrk_wait_ticks(b); backoff_count=1; do { v=_bmac_channel_check(); rf_rx_off(); if(v==1) break; // Channel is busy backoff=rand()%(_b_pow(backoff_count)); // printf( "backoff %d\r\n",backoff ); nrk_wait_until_next_n_periods(backoff); backoff_count++; if(backoff_count>6) backoff_count=6; // cap it at 64 b=_nrk_time_to_ticks(&_bmac_check_period); b=b/((rand()%10)+1); // printf( "waiting %d\r\n",b ); nrk_wait_until_ticks(b); // nrk_wait_ticks(b); } while(v==0); } // Give check_period worth of channel activity rf_test_mode(); rf_carrier_on(); nrk_wait(_bmac_check_period); rf_carrier_off(); rf_data_mode(); rf_rx_off(); pkt_got_ack = rf_tx_packet(&bmac_rfTxInfo); rf_rx_off(); tx_data_ready = 0; // Should signal user task here that Tx is done return NRK_OK; }
int8_t nrk_wait (nrk_time_t t) { uint8_t timer; uint16_t nw; nrk_stack_check (); nrk_int_disable (); nrk_cur_task_TCB->suspend_flag = 1; nrk_cur_task_TCB->num_periods = 1; timer = _nrk_os_timer_get (); //printf( "t1 %lu %lu\n",t.secs, t.nano_secs/NANOS_PER_MS); nw = _nrk_time_to_ticks (t); //printf( "t2 %u\n",nw ); nrk_cur_task_TCB->next_wakeup = nw + timer; //printf( "wu %u\n",nrk_cur_task_TCB->next_wakeup ); if (timer < (MAX_SCHED_WAKEUP_TIME - TIME_PAD)) if ((timer + TIME_PAD) <= _nrk_get_next_wakeup ()) { timer += TIME_PAD; _nrk_prev_timer_val = timer; _nrk_set_next_wakeup (timer); } nrk_int_enable (); _nrk_wait_for_scheduler (); return NRK_OK; }
int8_t nrk_set_next_wakeup(nrk_time_t t) { uint8_t timer; uint16_t nw; nrk_int_disable(); timer = _nrk_os_timer_get(); nw = _nrk_time_to_ticks(t); if (nw <= TIME_PAD) return NRK_ERROR; nrk_cur_task_TCB->next_wakeup = nw + timer; /* if(timer<(254-TIME_PAD)) if((timer+TIME_PAD)<=_nrk_get_next_wakeup()) { timer+=TIME_PAD; _nrk_prev_timer_val=timer; _nrk_set_next_wakeup(timer); } */ // nrk_cur_task_TCB->nw_flag=1; nrk_int_enable(); return NRK_OK; }
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(); }
int8_t _bmac_tx () { uint8_t v, backoff, backoff_count; uint16_t b; #ifdef DEBUG nrk_kprintf (PSTR ("_bmac_tx()\r\n")); #endif if (cca_active) { // Add random time here to stop nodes from synchronizing with eachother b = _nrk_time_to_ticks (&_bmac_check_period); b = b / ((rand () % 10) + 1); //printf( "waiting %d\r\n",b ); nrk_wait_until_ticks (b); //nrk_wait_ticks(b); backoff_count = 1; do { #ifdef BMAC_MOD_CCA v=_bmac_rx(); v=!v; if (v == 1) { break; } nrk_event_signal (bmac_rx_pkt_signal); #else v = _bmac_channel_check (); if (v == 1) break; #endif // Channel is busy backoff = rand () % (_b_pow (backoff_count)); #ifdef DEBUG printf ("backoff %d\r\n", backoff); #endif // printf( "backoff %d\r\n",backoff ); nrk_wait_until_next_n_periods (backoff); backoff_count++; if (backoff_count > 6) backoff_count = 6; // cap it at 64 b = _nrk_time_to_ticks (&_bmac_check_period); b = b / ((rand () % 10) + 1); // printf( "waiting %d\r\n",b ); nrk_wait_until_ticks (b); // nrk_wait_ticks(b); } while (v == 0); } // send extended preamble bmac_rfTxInfo.cca = 0; bmac_rfTxInfo.ackRequest = 0; uint16_t ms = _bmac_check_period.secs * 1000; ms += _bmac_check_period.nano_secs / 1000000; //printf( "CR ms: %u\n",ms ); //target_t.nano_secs+=20*NANOS_PER_MS; rf_rx_on (); pkt_got_ack = rf_tx_packet_repeat (&bmac_rfTxInfo, ms); // send packet // pkt_got_ack=rf_tx_packet (&bmac_rfTxInfo); rf_rx_off (); // Just in case auto-ack left radio on tx_data_ready = 0; nrk_event_signal (bmac_tx_pkt_done_signal); return NRK_OK; }