Beispiel #1
0
int
k_mut_ceil_enter (struct k_t *sem, int timeout)
{
    int retval;
    DI ();
    // if ceiling_prio < 0 then its a normal wait call
    if (sem->ceiling_prio < 0) {
	retval = ki_wait (sem, timeout);	// could call k_wait but just extra fct call
	EI ();
	return retval;
    }

    if (pRun->prio < sem->ceiling_prio) {	// I have higher priority than ceiling :-(
	EI ();
	return CEILINGFAIL;
    }
    // now we play imm ceiling protocol
    sem->saved_prio = pRun->prio;	// do im ceiling
    pRun->prio = sem->ceiling_prio;	// dont need to reinsert in AQ bq ceil prio is higher or equal to mine and Im already in front of AQ
    prio_enQ (pAQ, deQ (pRun));	// resinsert me in AQ acc to nwe(old) priority
    retval = ki_wait (sem, timeout);
    // coming back interrupt is still disabled !


    // chk if we did get semaphore
    if (retval < 0) {		// NOPE we did not
	pRun->prio = sem->saved_prio;	// reset to my old priority
	prio_enQ (pAQ, deQ (pRun));	// reinsert me in AQ acc to nwe(old) priority
	ki_task_shift ();	// bq maybe started task has higher prio than me

    }
    EI ();
    return retval;		// 0(has waited),1(straight through) : ok, -1: timeout
}
Beispiel #2
0
ISR (TIMER2_OVF_vect, ISR_NAKED)
{
	// no local vars ! I think
  PUSHREGS ();

  TCNT2 = tcnt2;		// Reload the timer

  if (!k_running)  // obvious
    goto exitt;

  fakecnt--;
  if (0 < fakecnt)		// how often shall we run KeRNeL timer code ?
    goto exitt;

  fakecnt = fakecnt_preset;	// now it's time for doing RT stuff

  // It looks maybe crazy to go through all semaphores and tasks
  // but 
  // you may have 3-4 tasks and 3-6 semaphores in your code
  // so...
  // and - it's a good idea not to init krnl with more items (tasks/Sem/msg descriptors than needed)
  

  pE = sem_pool;		// Semaphore timer - check timers on semaphores - they may be cyclic
  
  for (tmr_indx = 0; tmr_indx < nr_sem; tmr_indx++) {
    if (0 < pE->cnt2) {                         // timer on semaphore ?
      pE->cnt2--;                               // yep  decrement it
      if (pE->cnt2 <= 0) {                      // timeout  ?
        pE->cnt2 = pE->cnt3;	                  // preset again - if cnt3 == 0 and >= 0 the rep timer  
        ki_signal (pE);	                        //issue a signal to the semaphore
      }
    }
    pE++;
  }

  pE = task_pool;                               // Chk timers on tasks - they may be one shoot waiting

  for (tmr_indx = 0; tmr_indx < nr_task; tmr_indx++) {
    if (0 < pE->cnt2) {                        // timer active on task ? 
      pE->cnt2--;                              // yep so let us do one down count
      if (pE->cnt2 <= 0) {                     // timeout ? ( == 0 ) 
        pE->cnt2 = -1;	                       // indicate timeout inis semQ
        prio_enQ (pAQ, deQ (pE));	             // to AQ
      }
    }
    pE++;
  }

  prio_enQ (pAQ, deQ (pRun));	// round robbin

  K_CHG_STAK ();

 exitt:
  POPREGS ();
  RETI ();
}
Beispiel #3
0
int
ki_signal (struct k_t *sem)
{
    DI ();			// just in case
    if (sem->cnt1 < sem->maxv) {
	sem->cnt1++;		// Salute to Dijkstra

	if (sem->cnt1 <= 0) {
	    sem->next->cnt2 = 0;	// return code == ok
	    prio_enQ (pAQ, deQ (sem->next));
	    return (0);		// task was waiting
	}
	return (1);		// just delivered a signal - no task was waiting
    }

    if (SEM_MAX_VALUE > sem->clip) {
	sem->clip++;
    }
    // here we are on bad clip failure no signal takes place
    // signal is lost !!!
#ifdef KRNLBUG
    k_sem_clip (sem->nr, sem->clip);
#endif
    return (-1);
}
Beispiel #4
0
int
k_set_prio (char prio)
{
    int i;

    if (!k_running) {
	return (-2);
    }

    DI ();

    if ((prio <= 0) || (DMY_PRIO <= prio))	// not legal value my friend
    {
	EI ();
	return (-1);
    }
    i = pRun->prio;

    pRun->prio = prio;

    prio_enQ (pAQ, deQ (pRun));
    ki_task_shift ();

    EI ();

    return (i);
}
Beispiel #5
0
void
k_round_robbin (void)
{

    // reinsert running task in activeQ if round robbin is selected
    DI ();

    prio_enQ (pAQ, deQ (pRun));
    ki_task_shift ();

    EI ();
}
Beispiel #6
0
void
chg_Q_pos (struct k_t *el)
{
// not mature 
#ifdef PRIOINHERITANCE
  struct k_t *q;

  q = el->next;
  while (q->prio < QHD_PRIO)	// lets find Q head
    q = q->next;
  prio_enQ (q, el);  // resinsert
  #endif
}
Beispiel #7
0
char
k_mutex_leave (struct k_t *sem)
{
   volatile char res;

  DI ();

  pRun->prio = (char) (pRun->maxv);	// back to org prio
  prio_enQ (pAQ, deQ (pRun));	// chg pos in AQ acc to prio

  res = ki_signal (sem);

  if (res == 0)
    ki_task_shift ();

  EI ();

  return (res);
 }
Beispiel #8
0
int
ki_signal (struct k_t *sem)
{

  if (sem->maxv <= sem->cnt1){
		if (32000 > sem->clip)
			  sem->clip++;
    return (-1);
	}

  sem->cnt1++;		// Salute to Dijkstra

  if (sem->cnt1 <= 0) {
    sem->next->cnt2 = 0;	// return code == ok
    prio_enQ (pAQ, deQ (sem->next));
  }

  return (0);
}
Beispiel #9
0
int
k_prio_signal (struct k_t *sem, char prio)
{
    int res;

    DI ();

    res = ki_signal (sem);

    // set prio
    pRun->prio = prio;
    prio_enQ (pAQ, deQ (pRun));

    ki_task_shift ();

    EI ();

    return (res);
}
Beispiel #10
0
int
k_init (int nrTask, int nrSem, int nrMsg)
{
    if (k_running)		// are you a fool ???
    {
	return (-666);
    }

    k_task = nrTask + 1;	// +1 due to dummy
    k_sem = nrSem + nrMsg + 1;	// due to that every msgQ has a builtin semaphore
    k_msg = nrMsg + 1;		// to align so first user msgQ has index 1
    nr_send++;			// to align so we waste one but ... better equal access
    task_pool = (struct k_t *) malloc (k_task * sizeof (struct k_t));
    sem_pool = (struct k_t *) malloc (k_sem * sizeof (struct k_t));
    send_pool = (struct k_msg_t *) malloc (k_msg * sizeof (struct k_msg_t));

    // we dont accept any errors
    if ((task_pool == NULL) || (sem_pool == NULL) || (send_pool == NULL)) {
	k_err_cnt++;
	goto leave;
    }
    // init AQ as empty double chained list
    pAQ = &AQ;
    pAQ->next = pAQ->pred = pAQ;
    pAQ->prio = QHD_PRIO;

    // crt dummy
    //pDmy = k_crt_task (dummy_task, DMY_PRIO, dmy_stk, DMY_STK_SZ);

    pmain_el = task_pool;
    pmain_el->nr = 0;
    pmain_el->cnt2 = pmain_el->cnt3 = 0;
    nr_task++;
    pmain_el->prio = DMY_PRIO;	// main is dummy
    prio_enQ (pAQ, pmain_el);

    pSleepSem = k_crt_sem (0, 2000);

  leave:
    return k_err_cnt;
}
Beispiel #11
0
int
k_mut_ceil_leave (struct k_t *sem)
{
    int res;

    DI ();
    if (sem->ceiling_prio < 0) {	// just std signal
	return k_signal (sem);
    }

    res = ki_signal (sem);	// 1: ok no task to AQ, 0: ok task to AQ

    // coming back interrupt is still disabled !
    pRun->prio = sem->saved_prio;	// reset to my old priority

    prio_enQ (pAQ, deQ (pRun));	// resinsert me in AQ acc to nwe(old) priority

    ki_task_shift ();		// bq maybe started task has higher prio than me

    EI ();

    return (res);
}
Beispiel #12
0
int
k_set_prio (char prio)
{

  if (!k_running)
    return (-1);

  DI ();

  if ((prio <= 0) || (DMY_PRIO <= prio)) {
    // not legal value my friend
    EI ();
    return (-2);
  }

  pRun->prio = prio;
  prio_enQ (pAQ, deQ (pRun));
  ki_task_shift ();

  EI ();

  return (0);
}
Beispiel #13
0
struct k_t *
k_crt_task (void (*pTask) (void), char prio, char *pStk, int stkSize)
{
    struct k_t *pT;
    int i;
    char *s;

    if ((k_running) || ((prio <= 0) || (DMY_PRIO < prio))
	|| (k_task <= nr_task)) {
	goto badexit;
    }

    pT = task_pool + nr_task;	// lets take a task descriptor
    pT->nr = nr_task;
    nr_task++;

    pT->cnt2 = 0;		// no time out running on you for the time being
    pT->cnt3 = 0;		// no time out semaphore

    pT->cnt1 = (int) (pStk);	// ref to my stack

    // stack paint :-)
    for (i = 0; i < stkSize; i++)	// put hash code on stak to be used by k_unused_stak()
    {
	pStk[i] = STAK_HASH;
    }

    s = pStk + stkSize - 1;	// now we point on top of stak
    *(s--) = 0x00;		// 1 byte safety distance :-)

    // an interrupt do only push PC on stack by HW - can be 2 or 3 bytes
    // depending of 368/.../1280/2560
#ifdef BACKSTOPPER
    pT->pt = pTask;
    *(s--) = lo8 (jumper);	//  so top now holds address of function
    *(s--) = hi8 (jumper);	// which is code body for task
#else
    *(s--) = lo8 (pTask);	//  so top now holds address of function
    *(s--) = hi8 (pTask);	// which is code body for task
#endif
    // NB  NB 2560 use 3 byte for call/ret addresses the rest only 2
#if defined (__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
    *(s--) = EIND;		// best guess : 3 byte addresses !!! or just 0
#endif

    // r1 is the socalled zero value register
    // see https://gcc.gnu.org/wiki/avr-gcc
    // can tmp be non zero (multiplication etc)
    *(s--) = 0x00;		// r1
    *(s--) = 0x00;		// r0
    *(s--) = 0x00;		// sreg

    //1280 and 2560 need to save rampz reg just in case
#if defined (__AVR_ATmega2560__) || defined (__AVR_ATmega1280__) || defined (__AVR_ATmega1284P__) || defined(__AVR_ATmega2561__)
    *(s--) = RAMPZ;		// best guess  0x3b
    // obsolete JDN    *(s--) = EIND;             // best guess
#endif

#if defined (__AVR_ATmega2560__) || defined (__AVR_ATmega1280__) || defined(__AVR_ATmega2561__)
    *(s--) = EIND;		// best guess 0x3c
#endif

    for (i = 0; i < 30; i++)	//r2-r31 = 30 regs
    {
	*(s--) = 0x00;
    }

    pT->sp_lo = lo8 (s);	// now we just need to save stakptr
    pT->sp_hi = hi8 (s);	// in thread descriptor

    // HW DEPENDENT PART - ENDE

    pT->prio = prio;		// maxv for holding org prio for inheritance
    pT->maxv = (int) prio;
    prio_enQ (pAQ, pT);		// and put task in active Q

    return (pT);

  badexit:
    k_err_cnt++;
    return (NULL);
}
Beispiel #14
0
ISR (KRNLTMRVECTOR, ISR_NAKED)	// naked so we have to supply with prolog and epilog (push pop stack of regs)
{
    PUSHREGS ();		// no local vars ! I think

    // JDN NASTY FOR TIMING ANALYSIS ONLY
    //  PORTB |=0x10;

    wdt_reset ();

#if (KRNLTMR == 0)
    // we have overtaken the millis timer so we do it by hand
    timer0_millis += MILLIS_INC;
    timer0_fractt += FRACT_INC;
    if (timer0_fractt >= FRACT_MAX) {
	timer0_fractt -= FRACT_MAX;
	timer0_millis += 1;
    }
    timer0_overflow_count++;
#else
    TCNTx = tcntValue;		// Reload the timer
#endif

    if (!k_running) {
	goto exitt;
    }

    if (1 < k_tick_size) {
	fakecnt--;
	if (fakecnt <= 0) {
	    fakecnt = k_tick_size;
	} else {
	    goto exitt;		// no service
	}
    }

    k_millis_counter += k_tick_size;	// my own millis counter

    // the following may look crazy: to go through all semaphores and tasks
    // but you may have 3-4 tasks and 3-6 semaphores in your code
    // so - seems to be efficient :-)
    // so - it's a good idea not to init krnl with more items
    // (tasks/Sem/msg descriptors than needed)


    pE = sem_pool;		// Semaphore timer - check timers on semaphores

    for (tmr_indx = 0; tmr_indx < nr_sem; tmr_indx++) {
	if (0 < pE->cnt2)	// timer on semaphore ?
	{
	    pE->cnt2--;		// yep  decrement it
	    if (pE->cnt2 <= 0)	// timeout  ?
	    {
		pE->cnt2 = pE->cnt3;	// preset again - if cnt3 == 0 and >= 0 the rep timer
		ki_signal (pE);	//issue a signal to the semaphore
	    }
	}
	pE++;
    }

    pE = task_pool;		// Chk timers on tasks - they may be one shoot waiting

    for (tmr_indx = 0; tmr_indx < nr_task; tmr_indx++) {
	if (0 < pE->cnt2)	// timer active on task ?
	{
	    pE->cnt2--;		// yep so let us do one down count
	    if (pE->cnt2 <= 0)	// timeout ? ( == 0 )
	    {
		((struct k_t *) (pE->cnt3))->cnt1++;	// leaving sem so adjust semcount on sem
		prio_enQ (pAQ, deQ (pE));	// and rip task of semQ and insert in activeQ
		pE->cnt2 = -1;	// indicate timeout in this semQ
	    }
	}
	pE++;
    }

    prio_enQ (pAQ, deQ (pRun));

    K_CHG_STAK ();

  exitt:

    //JDN NASTY FOR MEA ONLY onn UNO pin8
    //PORTB &=0xef;

    POPREGS ();
    RETI ();
}
Beispiel #15
0
struct k_t *
k_crt_task (void (*pTask) (void), char prio, char *pStk, int stkSize)
{

  struct k_t *pT;
  int i;
  char *s;

  if (k_running)
    return (NULL);

  if ((prio <= 0 ) || (DMY_PRIO < prio)) {
    pT = NULL;
    goto badexit;
  }

  if (k_task <= nr_task) {
    goto badexit;
  }

  pT = task_pool + nr_task;	// lets take a task descriptor
  nr_task++;

  pT->cnt2 = 0;		// no time out running on you for the time being

  // HW_DEP_START
  // inspiration from http://dev.bertos.org/doxygen/frame_8h_source.html
  // and http://www.control.aau.dk/~jdn/kernels/krnl/
  // now we are going to precook stak
  
  pT->cnt1 = (int) (pStk);

  for (i = 0; i < stkSize; i++)	// put hash code on stak to be used by k_unused_stak()
    pStk[i] = STAK_HASH;

  s = pStk + stkSize - 1;	// now we point on top of stak
  *(s--) = 0x00;		// 1 byte safety distance
  *(s--) = lo8 (pTask);	//  so top now holds address of function
  *(s--) = hi8 (pTask);	// which is code body for task

  // NB  NB 2560 use 3 byte for call/ret addresses the rest only 2
#if defined (__AVR_ATmega2560__)
  *(s--) = EIND;		// best guess : 3 byte addresses !!!
#endif

  *(s--) = 0x00;		// r1
  *(s--) = 0x00;		// r0
  *(s--) = 0x00;		// sreg

  //1280 and 2560 need to save rampz reg just in case
#if defined (__AVR_ATmega2560__) || defined (__AVR_ATmega1280__)
  *(s--) = RAMPZ;		// best guess
  *(s--) = EIND;		// best guess
#endif

  for (i = 0; i < 30; i++)	//r2-r31 = 30 regs
    *(s--) = 0x00;

  pT->sp_lo = lo8 (s);	// now we just need to save stakptr
  pT->sp_hi = hi8 (s);	// in thread descriptor
  //HW_DE_ENDE

  pT->prio = prio;		// maxv for holding org prio for inheritance
  pT->maxv = (int) prio;
  prio_enQ (pAQ, pT);		// and put task in active Q

  return (pT);		// shall be index to task descriptor

 badexit:
  k_err_cnt++;
  return (NULL);
}
Beispiel #16
0
ISR (KRNLTMRVECTOR, ISR_NAKED)
{
    // no local vars ! I think
    PUSHREGS ();

    TCNTx = tcntValue;		// Reload the timer

    if (!k_running) {	// obvious
        goto exitt;
    }

    fakecnt--;			// for very slow k_start values 
                        //bq timer cant run so slow (8 bit timers at least)
    if (0 < fakecnt) {	// how often shall we run KeRNeL timer code ?
        goto exitt;
    }

    fakecnt = fakecnt_preset;	// now it's time for doing RT stuff

    k_millis_counter += k_tick_size;	// my own millis counter

    // the following may look crazy: to go through all semaphores and tasks
    // but you may have 3-4 tasks and 3-6 semaphores in your code
    // so - seesm to be efficient :-)
    // so - it's a good idea not to init krnl with more items 
    // (tasks/Sem/msg descriptors than needed)


    pE = sem_pool;		// Semaphore timer - check timers on semaphores - they may be cyclic

    for (tmr_indx = 0; tmr_indx < nr_sem; tmr_indx++) {
        if (0 < pE->cnt2) {	// timer on semaphore ?
            pE->cnt2--;		// yep  decrement it
            if (pE->cnt2 <= 0) {	// timeout  ?
                pE->cnt2 = pE->cnt3;	// preset again - if cnt3 == 0 and >= 0 the rep timer
                ki_signal (pE);	//issue a signal to the semaphore
            }
        }
        pE++;
    }

    pE = task_pool;		// Chk timers on tasks - they may be one shoot waiting

    for (tmr_indx = 0; tmr_indx < nr_task; tmr_indx++) {
        if (0 < pE->cnt2) {	// timer active on task ?
            pE->cnt2--;		// yep so let us do one down count
            if (pE->cnt2 <= 0) {	// timeout ? ( == 0 )
                ki_signal ((struct k_t *) (pE->cnt3));
                pE->cnt2 = -1;	// indicate timeout in this semQ
            }
        }
        pE++;
    }

    if (krnl_preempt_flag) {
        prio_enQ (pAQ, deQ (pRun));	// round robbin

        K_CHG_STAK ();
    }

exitt:
    POPREGS ();
    RETI ();
}