Exemple #1
0
int8_t nrk_wait_until_next_n_periods (uint16_t p)
{
  uint8_t timer;

  nrk_stack_check ();

  if (p == 0)
    p = 1;
// Next Period Wakeup Time is Set inside scheduler when a task becomes Runnable 
  nrk_int_disable ();
  nrk_cur_task_TCB->suspend_flag = 1;
  nrk_cur_task_TCB->num_periods = p;
  timer = _nrk_os_timer_get ();

//nrk_cur_task_TCB->cpu_remaining=_nrk_prev_timer_val+1;

// +2 allows for potential time conflict resolution
  if (timer < (MAX_SCHED_WAKEUP_TIME - TIME_PAD))       // 254 8bit overflow point - 2
    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;
}
Exemple #2
0
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;
}
Exemple #3
0
int8_t nrk_wait_until_next_period ()
{
    uint8_t timer;
	 //Abhijeet disabled this...	Haww
		//NVIC_EnableIRQ(TIMER0_IRQn);
		//NVIC_EnableIRQ(TIMER1_IRQn);
    //nrk_stack_check ();
// Next Period Wakeup Time is Set inside scheduler when a task becomes Runnable
    nrk_int_disable ();
    nrk_cur_task_TCB->num_periods = 1;
    nrk_cur_task_TCB->suspend_flag = 1;
    timer = _nrk_os_timer_get ();

//nrk_cur_task_TCB->cpu_remaining=_nrk_prev_timer_val+1;

    if (timer < (MAX_SCHED_WAKEUP_TIME - TIME_PAD)) // if(timer<(250-10))
        if ((timer + TIME_PAD) <= _nrk_get_next_wakeup ())
        {
            timer += TIME_PAD;
            _nrk_prev_timer_val = timer;                  // pdiener: why is this only set in this special case?
            _nrk_set_next_wakeup (timer);                 // pdiener: Set next wakeup to NOW...Ask Madhur and Abhijeet
        }

    nrk_int_enable ();
    _nrk_wait_for_scheduler ();
		//pc6.printf("should not come here");
    return NRK_OK;
}
Exemple #4
0
int8_t nrk_wait_until_next_period() {
	uint8_t timer;

	nrk_stack_check();
	// Next Period Wakeup Time is Set inside scheduler when a task becomes Runnable
	nrk_int_disable();
	nrk_cur_task_TCB->num_periods = 1;
	nrk_cur_task_TCB->suspend_flag = 1;
	timer = _nrk_os_timer_get();

	//nrk_cur_task_TCB->cpu_remaining=_nrk_prev_timer_val+1;

	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);
		}

	printf("Task %u finished in %u. \r\n",nrk_cur_task_TCB->task_ID,timer);

	nrk_int_enable();
	_nrk_wait_for_scheduler();
	return NRK_OK;
}
Exemple #5
0
int8_t nrk_wait_until_next_period ()
{
  uint16_t timer;

  nrk_stack_check ();
// Next Period Wakeup Time is Set inside scheduler when a task becomes Runnable // EXCEPT THIS CAUSES A FIRST-TIME-THROUGH BUG
  nrk_int_disable ();
  nrk_cur_task_TCB->num_periods = 1;
  nrk_cur_task_TCB->suspend_flag = 1;
  nrk_cur_task_TCB->next_wakeup = nrk_cur_task_TCB->next_period;
  timer = _nrk_os_timer_get ();

//nrk_cur_task_TCB->cpu_remaining=_nrk_prev_timer_val+1;

  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;
}
Exemple #6
0
int8_t nrk_wait_until_next_period ()
{
    uint8_t timer;

    nrk_stack_check ();
// Next Period Wakeup Time is Set inside scheduler when a task becomes Runnable
    nrk_int_disable ();
    nrk_cur_task_TCB->num_periods = 1;
    nrk_cur_task_TCB->suspend_flag = 1;
    timer = _nrk_os_timer_get ();

//nrk_cur_task_TCB->cpu_remaining=_nrk_prev_timer_val+1;

    if (timer < (MAX_SCHED_WAKEUP_TIME - TIME_PAD))
        if ((timer + TIME_PAD) <= _nrk_get_next_wakeup ())
        {
            timer += TIME_PAD;
            _nrk_prev_timer_val = timer;                  // pdiener: why is this only set in this special case?
            _nrk_set_next_wakeup (timer);                 // pdiener: Set next wakeup to NOW
        }

    nrk_int_enable ();
    _nrk_wait_for_scheduler ();
    return NRK_OK;
}
Exemple #7
0
void nrk_time_get(nrk_time_t *t)
{
 t->secs=nrk_system_time.secs;
 t->nano_secs=nrk_system_time.nano_secs;

   t->nano_secs+=((uint32_t)_nrk_os_timer_get()*(uint32_t)NANOS_PER_TICK);
    while(t->nano_secs>=(uint32_t)NANOS_PER_SEC)
    {
    t->nano_secs-=(uint32_t)NANOS_PER_SEC;
    t->secs++;
    }
}
Exemple #8
0
int8_t nrk_wait_until_nw() {
	uint8_t timer;
	nrk_int_disable();
	nrk_cur_task_TCB->suspend_flag = 1;
	nrk_cur_task_TCB->nw_flag = 1;
	timer = _nrk_os_timer_get();

	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);
		}
	//else nrk_cur_task_TCB->next_wakeup=ticks+1;
	nrk_int_enable();
	//while(nrk_cur_task_TCB->suspend_flag==1);
	_nrk_wait_for_scheduler();
	return NRK_OK;
}
Exemple #9
0
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;
}
Exemple #10
0
void nrk_time_get(nrk_time_t *t)
{
 //t->nano_secs=(((uint32_t)_nrk_precision_os_timer_get()%PRECISION_TICKS_PER_TICK)*(uint32_t)NANOS_PER_PRECISION_TICK);
#ifdef NRK_SUB_TICK_TIMING
       	t->nano_secs=(((uint32_t)_nrk_precision_os_timer_get())*(uint32_t)NANOS_PER_PRECISION_TICK);
#else
       	t->nano_secs=0;

#endif

 t->secs=nrk_system_time.secs;
 t->nano_secs+=nrk_system_time.nano_secs;
   
   t->nano_secs+=((uint32_t)_nrk_os_timer_get()*(uint32_t)NANOS_PER_TICK);
  

    while(t->nano_secs>=(uint32_t)NANOS_PER_SEC)
    {
    t->nano_secs-=(uint32_t)NANOS_PER_SEC;
    t->secs++;
    }

}
Exemple #11
0
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();

}
Exemple #12
0
void _isa_rx (uint8_t slot)
{
    uint8_t n;
    uint32_t node_mask;
    volatile uint8_t timeout;

    #ifdef LED_DEBUG
	nrk_led_set(1);
    #endif
    rf_set_rx (&isa_rfRxInfo, isa_param.channel);       // sets rx buffer and channel 
    rf_polling_rx_on ();
    
    // Timing for waiting for sfd
    timeout = _nrk_os_timer_get();
    timeout+=4;  // 4ms
    n = 0;
    //nrk_gpio_set(NRK_DEBUG_3);
    while ((n = rf_rx_check_sfd()) == 0) {
        if (_nrk_os_timer_get() > timeout) {
	    //spend too much time on waiting for a pkt's arrival
	    rf_rx_off ();
	    #ifdef LED_DEBUG
		nrk_led_clr(1);
	    #endif
	    #ifdef RX_DEBUG
		printf("sfd times out.\n\r");
	    #endif
	    return;
        }
    }
//printf("%d\n\r",_nrk_high_speed_timer_get());
    // sfd received, start receiving packet and record start time
    rx_start_time = _nrk_high_speed_timer_get();

    // Timing for waiting for finishing packet receiving
    timeout = _nrk_os_timer_get(); 
    timeout += 5;               // 5ms
    if (n != 0) {
        n = 0;
        //printf("Packet on its way\n\r");
        while ((n = rf_polling_rx_packet (false,128)) == 0) {
	    //printf("%d\n\r",_nrk_os_timer_get());
            if (_nrk_os_timer_get () > timeout) {
		#ifdef RX_DEBUG
		    printf("packet is too long, times out.\n\r");
		#endif
		// spend too much time on receiving pkt.
                return;          // huge timeout as fail safe
            }
        }
    }
    rf_rx_off ();
    if (n == 1) {// successfully received packet
	isa_rx_data_ready = 1;
	//potential problem: if repeater or recipient receives noise, the DHDR would be changed. And it is highly possible that the highest bit of DHDR would be set to 0
	/*if(isa_node_mode != ISA_GATEWAY)
	    DHDR = isa_rfRxInfo.pPayload[DHDR_INDEX];*/
	#ifdef RX_DEBUG
	    printf("Repeater slot = %d, local slot is %d.\n\r", isa_rfRxInfo.pPayload[SLOT_INDEX],global_slot);
	#endif RX_DEBUG	
	nrk_event_signal(isa_rx_pkt_signal);	

	//_nrk_high_speed_timer_reset();
	//nrk_high_speed_timer_wait(0,CPU_PROCESS_TIME);
	//nrk_gpio_set(NRK_DEBUG_3);

	node_mask = ((uint32_t) 1) << isa_rfRxInfo.pPayload[SRC_INDEX];
	
	if( !(node_mask & child_list))
	   return;  //FIXME change

	// ACK required
	if(DHDR & (1<<7)){
	    // Transmit ACK packet
	    DHR = configDHR();
	    isa_ack_buf[DHR_INDEX]= DHR;
	    #ifdef ACK_DEBUG
		//printf("DHR is %d.\n\r",DHR);
	    #endif
	    isa_ack_tx.pPayload = isa_ack_buf;
	    if (DHDR & (1<<2)){ // recipient , only reply explicit ACK
	        //isa_ack_tx.length = PKT_DATA_START-1;
		isa_ack_tx.length = 2;
            }
	    else { //reply ACK with time offsetX
		offsetX = rx_start_time - slot_start_time;
		//printf("slot_start_time is %d,rx_start_time is %d.\n\r",slot_start_time,rx_start_time);
		uint8_t temp1,temp2;
		temp1 = (offsetX & 0xFF00)>>8;
		isa_ack_buf[OFFSET_HIGH]=temp1;
		temp2 = (offsetX & 0x00FF);
 		isa_ack_buf[OFFSET_LOW]=temp2;
		#ifdef ACK_DEBUG
		    printf("offsetX is %d\n\r", offsetX);
		#endif		
		//isa_ack_tx.length = PKT_DATA_START + 1;	
		isa_ack_tx.length = 4;
	    }
	    rf_tx_tdma_packet (&isa_ack_tx,slot_start_time,isa_param.tx_guard_time,&tx_start_time);	
	}	
Exemple #13
0
/**************************************************************************
This function is the same as normal TX, only it waits until the last
second to send the duty out with the high speed timer.  And by duty, I mean
the packet BIATCH...
**************************************************************************/
uint8_t rf_tx_tdma_packet(RF_TX_INFO *pRTI, uint16_t slot_start_time, uint16_t tx_guard_time)
{
    uint16_t frameControlField;
    uint8_t packetLength;
    uint8_t success;
    uint8_t spiStatusByte;
    uint8_t checksum,i;
    uint8_t timestamp;

#ifdef RADIO_PRIORITY_CEILING
    nrk_sem_pend (radio_sem);
#endif
    timestamp=_nrk_os_timer_get();
    // XXX 2 below are hacks...
#ifdef CC2420_OSC_OPT
    FASTSPI_STROBE(CC2420_SXOSCON);
    nrk_spin_wait_us(OSC_STARTUP_DELAY);
#endif
    FASTSPI_STROBE(CC2420_SFLUSHRX);
    FASTSPI_STROBE(CC2420_SFLUSHRX);
    // Wait until the transceiver is idle
    while (FIFOP_IS_1 || SFD_IS_1);
    // Turn off global interrupts to avoid interference on the SPI interface
    DISABLE_GLOBAL_INT();
    // Flush the TX FIFO just in case...
    FASTSPI_STROBE(CC2420_SFLUSHTX);
    FASTSPI_STROBE(CC2420_SFLUSHTX);

    checksum=0;
    for(i=0; i<pRTI->length; i++ )
    {
        // lets do our own payload checksum because we don't trust the CRC
        checksum+=pRTI->pPayload[i];
    }
    packetLength = pRTI->length + RF_PACKET_OVERHEAD_SIZE + CHECKSUM_OVERHEAD;
    //nrk_set_led(3);
    //do { } while(_nrk_get_high_speed_timer()<(tx_guard_time));

    // Write the packet to the TX FIFO (the FCS is appended automatically when AUTOCRC is enabled)
    // These are only the MAC AGNOSTIC parameters...
    // Slots for example are at a higher layer since they assume TDMA

    FASTSPI_WRITE_FIFO((uint8_t*)&packetLength, 1);               // Packet length
    frameControlField = pRTI->ackRequest ? RF_FCF_ACK : RF_FCF_NOACK;
    FASTSPI_WRITE_FIFO((uint8_t*) &frameControlField, 2);         // Frame control field
    FASTSPI_WRITE_FIFO((uint8_t*) &rfSettings.txSeqNumber, 1);    // Sequence number
    FASTSPI_WRITE_FIFO((uint8_t*) &rfSettings.panId, 2);          // Dest. PAN ID
    FASTSPI_WRITE_FIFO((uint8_t*) &pRTI->destAddr, 2);            // Dest. address
    FASTSPI_WRITE_FIFO((uint8_t*) &rfSettings.myAddr, 2);         // Source address

    nrk_high_speed_timer_wait(slot_start_time,tx_guard_time);
    //nrk_clr_led(3);
    /*
    DISABLE_GLOBAL_INT();
     nrk_set_led(3);
    last=0;
    do {
    if(last==_nrk_get_high_speed_timer())
    	{
    	//while(1)
    	//printf( "TX ERROR %d vs %d\r\n",_nrk_get_high_speed_timer(),tx_guard_time );
    	break;
    	}
    last=_nrk_get_high_speed_timer();
    }
    while((volatile)last<(tx_guard_time));

    ENABLE_GLOBAL_INT();
    nrk_clr_led(3);
    */
    /*
        // Turn on RX if necessary
        if (!rfSettings.receiveOn) {
    		FASTSPI_STROBE(CC2420_SRXON);
    		}

        // Wait for the RSSI value to become valid
        do {
            FASTSPI_UPD_STATUS(spiStatusByte);
        } while (!(spiStatusByte & BM(CC2420_RSSI_VALID)));

    	// TX begins after the CCA check has passed
        do {
    		FASTSPI_STROBE(CC2420_STXONCCA);
    		FASTSPI_UPD_STATUS(spiStatusByte);
    		halWait(100);
        } while (!(spiStatusByte & BM(CC2420_TX_ACTIVE)));
    */
    if (pRTI->cca == TRUE)
    {
        uint8_t cnt;
        if (!rfSettings.receiveOn)
        {
            FASTSPI_STROBE (CC2420_SRXON);
        }

        // Wait for the RSSI value to become valid
        do
        {
            FASTSPI_UPD_STATUS (spiStatusByte);
        }
        while (!(spiStatusByte & BM (CC2420_RSSI_VALID)));

        // TX begins after the CCA check has passed
        cnt = 0;
        do
        {
            FASTSPI_STROBE (CC2420_STXONCCA);
            FASTSPI_UPD_STATUS (spiStatusByte);
            cnt++;
            if (cnt > 100)
            {
                ENABLE_GLOBAL_INT ();
                nrk_sem_post(radio_sem);
                return FALSE;
            }
            halWait (100);
        }
        while (!(spiStatusByte & BM (CC2420_TX_ACTIVE)));
    }
    else
        FASTSPI_STROBE (CC2420_STXON);
    //nrk_gpio_set(DEBUG_0);


    // Fill in the rest of the packet now
    FASTSPI_WRITE_FIFO((uint8_t*) pRTI->pPayload, pRTI->length);  // Payload
    FASTSPI_WRITE_FIFO((uint8_t*) &checksum, 1);         // Checksum



    //nrk_spin_wait_us(200);
//  FASTSPI_STROBE(CC2420_STXON);
    // Wait for the transmission to begin before exiting (makes sure that this function cannot be called
    // a second time, and thereby cancelling the first transmission (observe the FIFOP + SFD test above).
    while (!SFD_IS_1);
    success = TRUE;

    // Turn interrupts back on
//	ENABLE_GLOBAL_INT();

    // Wait for the acknowledge to be received, if any
    /*if (pRTI->ackRequest) {
    	rfSettings.ackReceived = FALSE;

    	// Wait for the SFD to go low again
    	while (SFD_IS_1);
        // We'll enter RX automatically, so just wait until we can be sure that the ack reception should have finished
        // The timeout consists of a 12-symbol turnaround time, the ack packet duration, and a small margin
        halWait((12 * RF_SYMBOL_DURATION) + (RF_ACK_DURATION) + (2 * RF_SYMBOL_DURATION) + 100);

    	// If an acknowledgment has been received (by the FIFOP interrupt), the ackReceived flag should be set
    	success = rfSettings.ackReceived;
    }*/


    // Turn off the receiver if it should not continue to be enabled
    DISABLE_GLOBAL_INT();
    // XXX hack, temp out
    //if (!rfSettings.receiveOn) { while (SFD_IS_1); /*FASTSPI_STROBE(CC2420_SRFOFF);*/ }
    // while (SFD_IS_1);
    while (SFD_IS_1); // wait for packet to finish

    FASTSPI_STROBE(CC2420_SFLUSHRX);
    FASTSPI_STROBE(CC2420_SFLUSHRX);
    FASTSPI_STROBE(CC2420_SFLUSHTX);
    FASTSPI_STROBE(CC2420_SFLUSHTX);

#ifdef CC2420_OSC_OPT
    FASTSPI_STROBE(CC2420_SXOSCOFF);
#endif
    FASTSPI_STROBE(CC2420_SRFOFF);  // shut off radio
    ENABLE_GLOBAL_INT();


    // Increment the sequence number, and return the result
    rfSettings.txSeqNumber++;
//	while (SFD_IS_1);
#ifdef RADIO_PRIORITY_CEILING
    nrk_sem_post(radio_sem);
#endif

    return success;

}
Exemple #14
0
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

//printf( "last run: %d\n",nrk_cur_task_TCB->task_ID );
//for (task_ID=0; task_ID < NRK_MAX_TASKS; task_ID++)
//{
//printf( "%d nw:%lu\n",task_ID,nrk_task_TCB[task_ID].next_wakeup );
//}


#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;
	    // agr added to fix initial startup scheduling problem
            if(nrk_cur_task_TCB->next_wakeup==0) {
		nrk_cur_task_TCB->next_wakeup=nrk_cur_task_TCB->next_period;
		}
        }
        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 && nrk_cur_task_TCB->task_state!=FINISHED )
    {
        if(nrk_cur_task_TCB->cpu_remaining<_nrk_prev_timer_val)
        {
#ifdef NRK_STATS_TRACKER
            _nrk_stats_add_violation(nrk_cur_task_TCB->task_ID);
#endif
            nrk_kernel_error_add(NRK_RESERVE_ERROR,nrk_cur_task_TCB->task_ID);
            nrk_cur_task_TCB->cpu_remaining=0;
        }
        else
            nrk_cur_task_TCB->cpu_remaining-=_nrk_prev_timer_val;

        task_ID= nrk_cur_task_TCB->task_ID;

        if (nrk_cur_task_TCB->cpu_remaining ==0 )
        {
#ifdef NRK_STATS_TRACKER
            _nrk_stats_add_violation(nrk_cur_task_TCB->task_ID);
#endif
            nrk_kernel_error_add(NRK_RESERVE_VIOLATED,task_ID);
            nrk_cur_task_TCB->task_state = SUSPENDED;
            nrk_rem_from_readyQ(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;

    // Maybe the signals are triggering this problem?
    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();

}
Exemple #15
0
void inline _nrk_scheduler() {
	int8_t task_ID;
	uint16_t next_wake;
	uint16_t start_time_stamp;

	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_KERNEL_TEST
	if(_nrk_cpu_state && _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==2) _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

	printf("==============================\r\n");
	printf("ENTERING SCHEDULER @ %u \r\n",
			nrk_system_time.nano_secs);
	printf("!! Interrupted TID %u after %u.\r\n ", nrk_cur_task_TCB->task_ID,
			_nrk_prev_timer_val);

	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 && nrk_cur_task_TCB->task_state != FINISHED) {
		if (nrk_cur_task_TCB->cpu_remaining < _nrk_prev_timer_val) {
#ifdef NRK_STATS_TRACKER
			_nrk_stats_add_violation(nrk_cur_task_TCB->task_ID);
#endif
			printf("< MISS > Deadline Missed for Task %u\r\n",task_ID);
			nrk_kernel_error_add(NRK_RESERVE_ERROR, nrk_cur_task_TCB->task_ID);
			nrk_cur_task_TCB->cpu_remaining = 0;
		} else
			nrk_cur_task_TCB->cpu_remaining -= _nrk_prev_timer_val;

		task_ID = nrk_cur_task_TCB->task_ID;

		if (nrk_cur_task_TCB->cpu_remaining == 0) {
#ifdef NRK_STATS_TRACKER
			_nrk_stats_add_violation(nrk_cur_task_TCB->task_ID);
#endif
			printf("xxxxxx >>  Deadline Violated for Task %u\r\n",task_ID);
			nrk_kernel_error_add(NRK_RESERVE_VIOLATED, task_ID);
			nrk_cur_task_TCB->task_state = SUSPENDED;
			nrk_rem_from_readyQ(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;
					nrk_task_TCB[task_ID].abs_deadline
							+= nrk_task_TCB[task_ID].period;
					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].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));
					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;
			}

			printf("SQueue Contents :\r\n");
			printf(
					"%u. TID %u, CPU Rem %u, CPU Res %u, Period %u, State %u, NW %u, NP %u, AD %u \r\n",
					task_ID, nrk_task_TCB[task_ID].task_ID,
					nrk_task_TCB[task_ID].cpu_remaining,
					nrk_task_TCB[task_ID].cpu_reserve,
					nrk_task_TCB[task_ID].period,
					nrk_task_TCB[task_ID].task_state,
					nrk_task_TCB[task_ID].next_wakeup,
					nrk_task_TCB[task_ID].next_period,
					nrk_task_TCB[task_ID].abs_deadline);
		}
	}
	printf(">>> next_wake is @ %u after loop .\r\n", next_wake);

#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.

		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;
			}
		}
	}
	printf(">>> next_wake CHANGED TO REM_TIME,i.e. %u  .\r\n", next_wake);

	/*
	 // 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);
	 }
	 }*/

	//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
	_nrk_prev_timer_val = next_wake;

	if (_nrk_os_timer_get() >= 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==2))
		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 = 0;

	nrk_queue * printer = _head_node;
	int j = 0;
	printf("RQueue Contents :\r\n");
	while (printer) {
		printf(
				"%u. TID %u, CPU Rem %u, CPU Res %u, Period %u, State %u, NW %u, NP %u, AD %u . \r\n",
				j, printer->task_ID,
				nrk_task_TCB[printer->task_ID].cpu_remaining,
				nrk_task_TCB[printer->task_ID].cpu_reserve,
				nrk_task_TCB[printer->task_ID].period,
				nrk_task_TCB[printer->task_ID].task_state,
				nrk_task_TCB[printer->task_ID].next_wakeup,
				nrk_task_TCB[printer->task_ID].next_period,
				nrk_task_TCB[printer->task_ID].abs_deadline);
		printer = printer->Next;
		j++;
	}
	_nrk_set_next_wakeup(next_wake);
	printf("Setting TACCR0 to (nw-1) -> %u \r\n", (next_wake - 1));
	printf("Starting TID %u \r\n", task_ID);
	printf("EXITING SCHEDULER\r\n");
	printf("==============================\r\n");
	_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();

}