My Project - RET HER  versionsnr
krnl.c
Go to the documentation of this file.
1 /******************************************************
2 * *
3 * *
4  | |/ /___| _ \| \ | | ___| |
5  | ' // _ \ |_) | \| |/ _ \ |
6  | . \ __/ _ <| |\ | __/ |___
7  |_|\_\___|_| \_\_| \_|\___|_____|
8 * *
9 * *
10  you are watching krnl.c
11 * *
12  March 2015,2016,..,2018
13  Author: jdn
14  13 March 2018
15  1
16 *******************************************************
17 
18  this version adapted for Arduino
19 
20  (C) 2012,2013,2014
21  2017,2018,2019
22 
23 
24 
25 
26  Jens Dalsgaard Nielsen <jdn@es.aau.dk>
27  http://es.aau.dk/staff/jdn
28  Section of Automation & Control
29  Aalborg University,
30  Denmark
31 
32  "THE BEER-WARE LICENSE" (frit efter PHK)
33  <jdn@es.aau.dk> wrote this file. As long as you
34  retain this notice you can do whatever you want
35  with this stuff. If we meet some day, and you think
36  this stuff is worth it ...
37  you can buy me a beer in return :-)
38  or if you are real happy then ...
39  single malt will be well received :-)
40 
41  Use it at your own risk - no warranty
42 
43  nice info...
44  http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_cplusplus
45  at 20090611
46  - k_eat_time now eats time in quants of krnl tick speed but not one quant boundary
47  - added k_malloc and k_free
48  k_free dont free memory bq we do not want fragmentation
49  so DONT USE k_free
50  - k_malloc and k_free are weak functions so you can just add your own versions
51  - watchdog is enabled (2sec and reset in krnl timer) in weak function k_enable_wdt
52 
53 
54 */
55 
56 /*
57  ABOUT TIMERS
58  following is Arduinos impl found in ...
59  "arduino install"/hardware/arduino/avr/cores/arduino/wiring.c
60 
61  volatile unsigned long timer0_overflow_count = 0;
62  volatile unsigned long timer0_millis = 0;
63  static unsigned char timer0_fract = 0;
64 
65  #if defined(TIM0_OVF_vect)
66  ISR(TIM0_OVF_vect)
67  #else
68  ISR(TIMER0_OVF_vect)
69  #endif
70  {
71  // copy these to local variables so they can be stored in registers
72  // (volatile variables must be read from memory on every access)
73  unsigned long m = timer0_millis;
74  unsigned char f = timer0_fract;
75 
76  m += MILLIS_INC;
77  f += FRACT_INC;
78  if (f >= FRACT_MAX) {
79  f -= FRACT_MAX;
80  m += 1;
81  }
82 
83  timer0_fract = f;
84  timer0_millis = m;
85  timer0_overflow_count++;
86  }
87 
88  unsigned long millis()
89  {
90  unsigned long m;
91  uint8_t oldSREG = SREG;
92 
93  // disable interrupts while we read timer0_millis or we might get an
94  // inconsistent value (e.g. in the middle of a write to timer0_millis)
95  cli();
96  m = timer0_millis;
97  SREG = oldSREG;
98 
99  return m;
100  }
101 
102  unsigned long micros() {
103  unsigned long m;
104  uint8_t oldSREG = SREG, t;
105 
106  cli();
107  m = timer0_overflow_count;
108  #if defined(TCNT0)
109  t = TCNT0;
110  #elif defined(TCNT0L)
111  t = TCNT0L;
112  #else
113  #error TIMER 0 not defined
114  #endif
115 
116  #ifdef TIFR0
117  if ((TIFR0 & _BV(TOV0)) && (t < 255))
118  m++;
119  #else
120  if ((TIFR & _BV(TOV0)) && (t < 255))
121  m++;
122  #endif
123 
124  SREG = oldSREG;
125 
126  return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
127  }
128 
129  void delay(unsigned long ms)
130  {
131  uint32_t start = micros();
132 
133  while (ms > 0) {
134  yield();
135  while ( ms > 0 && (micros() - start) >= 1000) {
136  ms--;
137  start += 1000;
138  }
139  }
140  }
141 
142 *********/
143 
144 #include "krnl.h"
145 
146 #ifdef WDT_TIMER
147 #include <avr/wdt.h>
148 #endif
149 
150 #include <avr/interrupt.h>
151 #include <util/delay.h>
152 #include <stdlib.h>
153 
154 // CPU frequency - for adjusting delays
155 #if (F_CPU == 8000000)
156 #pragma message("krnl detected 8 MHz")
157 #endif
158 
159 #if (KRNL_VRS != 20191008)
160 #error "KRNL VERSION NOT UPDATED in krnl.c "
161 #endif
162 
163 /*
164  #ifdef __cplusplus
165  extern "C" {
166  #endif
167 */
168 
169 /* which timer to use for krnl heartbeat
170  timer 0 ( 8 bit) is normally used by millis - avoid !
171  timer 1 (16 bit) DEFAULT
172  timer 2 ( 8 bit)
173  timer 3 (16 bit) 1280/1284P/2560 only (MEGA)
174  timer 4 (16 bit) 1280/2560 only (MEGA)
175  timer 5 (16 bit) 1280/2560 only (MEGA)
176 */
177 
178 #if (KRNLTMR == 0)
179 
180 // normally not goood bq of arduino sys timer is on timer 0so you wil get a compile error
181 // 8 bit timer !!!
182 #define KRNLTMRVECTOR TIMER0_OVF_vect
183 /* we use setting from original timer0
184  #define TCNTx TCNT0
185  #define TCCRxA TCCR0A
186  #define TCCRxB TCCR0B
187  #define TCNTx TCNT0
188  #define OCRxA OCR0A
189  #define TIMSKx TIMSK0
190  #define TOIEx TOIE0
191  #define PRESCALE 0x07
192  #define COUNTMAX 255
193  #define DIVV 15.625
194  #define DIVV8 7.812
195 */
196 
197 #elif (KRNLTMR == 1)
198 #define KRNLTMRVECTOR TIMER1_OVF_vect
199 #define TCNTx TCNT1
200 #define TCCRxA TCCR1A
201 #define TCCRxB TCCR1B
202 #define TCNTx TCNT1
203 #define OCRxA OCR1A
204 #define TIMSKx TIMSK1
205 #define TOIEx TOIE1
206 #define PRESCALE 0x03
207 #define COUNTMAX 0xffff
208 #define DIVV 250
209 #define DIVV8 (DIVV / 2)
210 
211 #elif (KRNLTMR == 2)
212 
213 // 8 bit timer !!!
214 // standard for krnl CHECK which pwm, tone etc is on this timer
215 #define KRNLTMRVECTOR TIMER2_OVF_vect
216 #define TCNTx TCNT2
217 #define TCCRxA TCCR2A
218 #define TCCRxB TCCR2B
219 #define TCNTx TCNT2
220 #define OCRxA OCR2A
221 #define TIMSKx TIMSK2
222 #define TOIEx TOIE2
223 #define PRESCALE 0x05
224 #define COUNTMAX 255
225 #define DIVV 125
226 #define DIVV8 64
227 
228 #elif (KRNLTMR == 3)
229 
230 #define KRNLTMRVECTOR TIMER3_OVF_vect
231 #define TCNTx TCNT3
232 #define TCCRxA TCCR3A
233 #define TCCRxB TCCR3B
234 #define TCNTx TCNT3
235 #define OCRxA OCR3A
236 #define TIMSKx TIMSK3
237 #define TOIEx TOIE3
238 #define PRESCALE 0x03
239 #define COUNTMAX 0xffff
240 #define DIVV 250
241 #define DIVV8 (DIVV / 2)
242 
243 #elif (KRNLTMR == 4)
244 
245 #define KRNLTMRVECTOR TIMER4_OVF_vect
246 #define TCNTx TCNT4
247 #define TCCRxA TCCR4A
248 #define TCCRxB TCCR4B
249 #define TCNTx TCNT4
250 #define OCRxA OCR4A
251 #define TIMSKx TIMSK4
252 #define TOIEx TOIE4
253 #define PRESCALE 0x03
254 #define COUNTMAX 0xffff
255 #define DIVV 250
256 #define DIVV8 (DIVV / 2)
257 
258 #elif (KRNLTMR == 5)
259 
260 #define KRNLTMRVECTOR TIMER5_OVF_vect
261 #define TCNTx TCNT5
262 #define TCCRxA TCCR5A
263 #define TCCRxB TCCR5B
264 #define TCNTx TCNT5
265 #define OCRxA OCR5A
266 #define TIMSKx TIMSK5
267 #define TOIEx TOIE5
268 #define PRESCALE 0x03
269 #define COUNTMAX 0xffff
270 #define DIVV 250
271 #define DIVV8 (DIVV / 2)
272 
273 #else
274 
275 #pragma err "KRNL: no valid tmr selected"
276 
277 #endif
278 
279 int k_config = KRNLTMR | (DYNMEM << 4) | (KRNLBUG << 5) | (BACKSTOPPER << 6)
280 
281  //----------------------------------------------------------------------------
282 
283  struct k_t *
284  task_pool, // array of descriptors for tasks
285  *sem_pool, // .. for semaphores
286  AQ, // Q head for active Q
287  *pmain_el, // procesdecriptor for main
288  *pAQ, // head of activeQ (AQ)
289 // *pDmy, // ref to dummy task
290  *pRun, // who is running ?
291  *pSleepSem; // one semaphor for all to sleep at
292 
293 struct k_msg_t *send_pool; // ptr to array for msg sem pool
294 
295 int k_task, k_sem, k_msg; // how many did you request in k_init of descriptors ?
296 char nr_task = 0, nr_sem = 0, nr_send = 0; // counters for created KeRNeL items
297 
298 volatile char k_running = 0, k_err_cnt = 0;
299 
300 volatile unsigned int tcntValue; // counters for timer system
301 volatile int fakecnt, // counters for letting timer ISR go multipla faster than krnl timer
303 
304 static volatile char stopp = 0; // main will loop on stop as dummy task
305 
306 unsigned long k_millis_counter = 0;
307 unsigned int k_tick_size;
308 
309 int tmr_indx; // for travelling Qs in tmr isr
310 
311 /******/
312 /* JDN 180312 - look in krnl.h now as macro
313 
314  see krnl.h using _delay_ms
315  void
316  k_eat_time (unsigned int eatTime)
317  {
318  _delay_ms(eatTime);
319  return;
320  while (10 < eatTime) // _delay_us() performs busywait
321  {
322  eatTime -= 10;
323  _delay_ms (10000);
324  }
325 
326  while (0 < eatTime) // _delay_us() performs busywait
327  {
328  eatTime--;
329  _delay_us (1000);
330  }
331  }
332 */
333 
334 //---QOPS---------------------------------------------------------------------
335 
336 void enQ(struct k_t *Q, struct k_t *el)
337 {
338  el->next = Q;
339  el->pred = Q->pred;
340  Q->pred->next = el;
341  Q->pred = el;
342 }
343 
344 struct k_t *
345 deQ(struct k_t *el)
346 {
347  el->pred->next = el->next;
348  el->next->pred = el->pred;
349 
350  return (el);
351 }
352 
353 void prio_enQ(struct k_t *Q, struct k_t *el)
354 {
355  char prio = el->prio;
356 
357  Q = Q->next; // bq first elm is Q head itself
358 
359  while (Q->prio <= prio) // find place before next with lower prio
360  {
361  Q = Q->next;
362  }
363 
364  el->next = Q; // insert before element referred by Q
365  el->pred = Q->pred;
366  Q->pred->next = el;
367  Q->pred = el;
368 }
369 
370 //---HW timer IRS--timer section------------------------
371 
372 /*
373  The KRNL Timer is driven by timer
374 
375  Install the Interrupt Service Routine (ISR) for Timer2 overflow.
376  This is normally done by writing the address of the ISR in the
377  interrupt vector table but conveniently done by using ISR()
378 
379  Timer2 reload value, globally available
380 */
381 
382 #if (KRNLTMR == 0)
383 
384 extern volatile unsigned long timer0_overflow_count;
385 extern volatile unsigned long timer0_millis;
386 extern unsigned char timer0_fract;
387 #define MICROSECONDS_PER_TIMER0_OVERFLOW (1024) //clockCyclesToMicroseconds(64 * 256))
388 
389 // the whole number of milliseconds per timer0 overflow
390 #define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
391 
392 // the fractional number of milliseconds per timer0 overflow. we shift right
393 // by three to fit these numbers into a byte. (for the clock speeds we care
394 // about - 8 and 16 MHz - this doesn't lose precision.)
395 #define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
396 #define FRACT_MAX (1000 >> 3)
397 
398 #endif
399 
400 /* from wiring.c
401  // the prescaler is set so that timer0 ticks every 64 clock cycles, and the
402  // the overflow handler is called every 256 ticks.
403  #define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
404 
405  // the whole number of milliseconds per timer0 overflow
406  #define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
407 
408  // the fractional number of milliseconds per timer0 overflow. we shift right
409  // by three to fit these numbers into a byte. (for the clock speeds we care
410  // about - 8 and 16 MHz - this doesn't lose precision.)
411  #define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
412  #define FRACT_MAX (1000 >> 3) which is
413 
414 */
415 
416 ISR(KRNLTMRVECTOR, ISR_NAKED) // naked so we have to supply with prolog and epilog (push pop stack of regs)
417 {
418  static struct k_t *pE;
419  PUSHREGS(); // no local vars ! I think
420 
421  // JDN NASTY FOR TIMING ANALYSIS ONLY
422  // PORTB |=0x10;
423 
424 #if WDT_TIMER == 1
425  wdt_reset();
426 #endif
427 
428 #if (KRNLTMR == 0)
429 
430  // STD IS NOT TAKEN TIMER 0 - SEE IN krnl.h
431  // we have overtaken the millis timer so we do it by hand
432  //found in "arduino install"/hardware/arduino/avr/cores/arduino/wiring.c
433  //F = 976.5625Hz, i.e. it increments every 1.024msec
434  // so every
435  // copy these to local variables so they can be stored in registers
436  // (volatile variables must be read from memory on every access)
437  //JDN see below unsigned char f = timer0_fract;
438 
439  unsigned long m = timer0_millis;
440 
441  m += MILLIS_INC;
442  /* JDN if you use the frac part then you will se time advance every 41/42 tick and
443  clock will drift ahead timers -
444  */
445 
446  f += FRACT_INC;
447  if (f >= FRACT_MAX)
448  {
449  f -= FRACT_MAX;
450  m += 1;
451  }
452 
453  timer0_fract = f;
454 
456 
457  timer0_millis = m;
458 #else
459  TCNTx = tcntValue; // Reload the timer
460 #endif
461 
462  if (!k_running)
463  {
464  goto exitt;
465  }
466 
467  if (1 < k_tick_size)
468  {
469  fakecnt--;
470  if (fakecnt <= 0)
471  {
473  }
474  else
475  {
476  goto exitt; // no service
477  }
478  }
479 
480  k_millis_counter += k_tick_size; // my own millis counter
481 
482  // the following may look crazy: to go through all semaphores and tasks
483  // but you may have 3-4 tasks and 3-6 semaphores in your code
484  // so - seems to be efficient :-)
485  // so - it's a good idea not to init krnl with more items
486  // (tasks/Sem/msg descriptors than needed)
487 
488  pE = sem_pool; // Semaphore timer - check timers on semaphores
489 
490  for (tmr_indx = 0; tmr_indx < nr_sem; tmr_indx++)
491  {
492  if (0 < pE->cnt2) // timer on semaphore ?
493  {
494  pE->cnt2--; // yep decrement it
495  if (pE->cnt2 <= 0) // timeout ?
496  {
497  pE->cnt2 = pE->cnt3; // preset again - if cnt3 == 0 and >= 0 the rep timer
498  ki_signal(pE); //issue a signal to the semaphore
499  }
500  }
501  pE++;
502  }
503 
504  pE = task_pool; // Chk timers on tasks - they may be one shoot waiting
505 
506  for (tmr_indx = 0; tmr_indx < nr_task; tmr_indx++)
507  {
508  if (0 < pE->cnt2) // timer active on task ?
509  {
510  pE->cnt2--; // yep so let us do one down count
511  if (pE->cnt2 <= 0) // timeout ? ( == 0 )
512  {
513  ((struct k_t *)(pE->cnt3))->cnt1++; // leaving sem so adjust semcount on sem
514  prio_enQ(pAQ, deQ(pE)); // and rip task of semQ and insert in activeQ
515  pE->cnt2 = -1; // indicate timeout in this semQ
516  }
517  }
518  pE++;
519  }
520 
521  prio_enQ(pAQ, deQ(pRun));
522 
523  K_CHG_STAK();
524 
525 exitt:
526 
527  //JDN NASTY FOR MEA ONLY onn UNO pin8
528  //PORTB &=0xef;
529 
530  POPREGS();
531  RETI();
532 }
535 //----------------------------------------------------------------------------
536 // inspired from ...
537 // http://arduinomega.blogspot.dk/2011/05/timer2-and-overflow-interrupt-lets-get.html
538 // Inspiration from http://popdevelop.com/2010/04/mastering-timer-interrupts-on-the-arduino/
539 // Inspiration from "Multitasking on an AVR" by Richard Barry, March 2004
540 // and http://www.control.aau.dk/~jdn/kernels/krnl/
541 //----------------------------------------------------------------------------
542 // avrfreaks.net
543 // and my old kernel from last century
544 // and a lot other stuff
545 // basic concept from my own very old kernels dated back bef millenium
546 
547 void __attribute__((naked, noinline)) ki_task_shift(void)
548 {
549  PUSHREGS(); // push task regs on stak so we are rdy to task shift
550  K_CHG_STAK();
551  POPREGS(); // restore regs
552  RETI(); // and do a reti NB this also enables interrupt !!!
553 }
554 
555 #ifdef BACKSTOPPER
556 void jumper()
557 {
558  (*(pRun->pt))();
560  while (1)
561  ; // just in case
562 }
563 #endif
564 
565 struct k_t * k_crt_task(void (*pTask)(void), char prio, int stkSize)
566 //k_crt_task (void (*pTask) (void), char prio, char *pStk, int stkSize)
567 {
568  char *pStk;
569  struct k_t *pT;
570  int i;
571  char *s;
572 
573  if ((k_running) || ((prio <= 0) || (DMY_PRIO < prio)) || (k_task <= nr_task))
574  {
575  goto badexit;
576  }
577 
578  pStak = malloc(stkSize);
579  if (pStak == NULL)
580  {
581  goto badexit;
582  }
583  pT = task_pool + nr_task; // lets take a task descriptor
584  pT->nr = nr_task;
585  nr_task++;
586 
587  pT->cnt2 = 0; // no time out running on you for the time being
588  pT->cnt3 = 0; // no time out semaphore
589 
590  pT->cnt1 = (int)(pStk); // ref to my stack
591 
592  // stack paint :-)
593  for (i = 0; i < stkSize; i++) // put hash code on stak to be used by k_unused_stak()
594  {
595  pStk[i] = STAK_HASH;
596  }
597 
598  s = pStk + stkSize - 1; // now we point on top of stak
599  *(s--) = 0x00; // 1 byte safety distance :-)
600 
601  // an interrupt do only push PC on stack by HW - can be 2 or 3 bytes
602  // depending of 368/.../1280/2560
603 #ifdef BACKSTOPPER
604  pT->pt = pTask;
605  *(s--) = lo8(jumper); // so top now holds address of function
606  *(s--) = hi8(jumper); // which is code body for task
607 #else
608  *(s--) = lo8(pTask); // so top now holds address of function
609  *(s--) = hi8(pTask); // which is code body for task
610 #endif
611  // NB NB 2560 use 3 byte for call/ret addresses the rest only 2
612 #if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
613  *(s--) = EIND; // best guess : 3 byte addresses !!! or just 0
614 #endif
615 
616  // r1 is the socalled zero value register
617  // see https://gcc.gnu.org/wiki/avr-gcc
618  // can tmp be non zero (multiplication etc)
619  *(s--) = 0x00; // r1
620  *(s--) = 0x00; // r0
621  *(s--) = 0x00; // sreg
622 
623  //1280 and 2560 need to save rampz reg just in case
624 #if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega2561__)
625  *(s--) = RAMPZ; // best guess 0x3b
626  // obsolete JDN *(s--) = EIND; // best guess
627 #endif
628 
629 #if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2561__)
630  *(s--) = EIND; // best guess 0x3c
631 #endif
632 
633  for (i = 0; i < 30; i++) //r2-r31 = 30 regs
634  {
635  *(s--) = 0x00;
636  }
637 
638  pT->sp_lo = lo8(s); // now we just need to save stakptr
639  pT->sp_hi = hi8(s); // in thread descriptor
640 
641  // HW DEPENDENT PART - ENDE
642 
643  pT->prio = prio; // maxv for holding org prio for inheritance
644  pT->maxv = (int)prio;
645  prio_enQ(pAQ, pT); // and put task in active Q
646 
647  return (pT);
648 
649 badexit:
650  k_err_cnt++;
651  return (NULL);
652 }
653 
654 int freeRam(void)
655 {
656  extern int __heap_start, *__brkval;
657  int x, v;
658  // NASTY
659  x = ((int)&v - (__brkval == 0 ? (int)&__heap_start : (int)__brkval)); // to remove warning
660  return x;
661  // hw specific :-/
662  //return ((int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval));
663 
664  /* from http://www.noah.org/wiki/Arduino_notes#debug_memory_problems_.28out_of_RAM.29
665  int freeRam () {
666  // __brkval is the address of the top of the heap if memory has been allocated.
667  // If __brkval is zero then it means malloc has not used any memory yet, so
668  // we look at the address of __heap_start.
669  extern int __heap_start
670  extern int *__brkval; // address of the top of heap
671  int stack_top;
672  return (int)&stack_top - ((int)__brkval == 0 ? (int)&__heap_start : (int)__brkval);
673  }
674  */
675 }
676 
677 int k_sleep(int time)
678 {
679  int r;
680  if (time <= 0)
681  return -1;
682  r = k_wait(pSleepSem, time);
683  if (r == -1) // timeout ? yes :-)
684  return 0;
685 }
686 
687 void k_eat_ticks(int ticks)
688 {
689  long msc = ticks * k_tick_size; // now in milliseconds
690  if (msc <= 0) // should never happen
691  return;
692  while (msc--)
693  { // not 100% accurate.
694  _delay_ms(1);
695  }
696 }
697 
698 int k_unused_stak(struct k_t *t)
699 {
700  int i;
701  char *pstk;
702 
703  if (t) // another task or yourself - NO CHK of validity !!!!!
704  {
705  pstk = (char *)(t->cnt1);
706  }
707  else
708  {
709  pstk = (char *)(pRun->cnt1);
710  }
711 
712  DI();
713  // look for stack paint
714  i = 0;
715  while (*pstk == STAK_HASH)
716  {
717  pstk++;
718  i++;
719  }
720  EI();
721 
722  return (i);
723 }
724 
725 int k_set_prio(char prio)
726 {
727  int i;
728 
729  if (!k_running)
730  {
731  return (-2);
732  }
733 
734  DI();
735 
736  if ((prio <= 0) || (DMY_PRIO <= prio)) // not legal value my friend
737  {
738  EI();
739  return (-1);
740  }
741  i = pRun->prio;
742 
743  pRun->prio = prio;
744 
745  prio_enQ(pAQ, deQ(pRun));
746  ki_task_shift();
747 
748  EI();
749 
750  return (i);
751 }
752 
753 int k_mut_ceil_set(struct k_t *sem, char prio)
754 {
755  // NB NB assume semaphore is created prior to this call
756  // NO CHECK - no mercy !!!
757  // work only BEFORE k_start
758  if (k_running)
759  {
760  return (-2); // bad bad
761  }
762 
763  if ((prio <= 0) || (DMY_PRIO <= prio))
764  {
765  return (-1); // bad bad
766  }
767  sem->ceiling_prio = prio;
768  return 0; // OK
769 }
770 
771 struct k_t *
772 k_crt_sem(char init_val, int maxvalue)
773 {
774  struct k_t *sem;
775 
776  if (k_running)
777  {
778  return (NULL);
779  }
780 
781  if ((init_val < 0) || (SEM_MAX_VALUE < init_val) || (maxvalue < 0) || (SEM_MAX_VALUE < maxvalue))
782  {
783  goto badexit;
784  }
785 
786  if (k_sem <= nr_sem) // no vacant in buf
787  {
788  goto badexit;
789  }
790 
791  sem = sem_pool + nr_sem; // allocate it
792  sem->nr = nr_sem;
793  nr_sem++;
794 
795  sem->cnt2 = 0; // no timer running
796  sem->next = sem->pred = sem; // point at myself == no one in Q
797  sem->prio = QHD_PRIO;
798  sem->cnt1 = init_val;
799 
800  sem->maxv = maxvalue;
801  sem->clip = 0;
802 
803  sem->ceiling_prio = -1; // to indicate it is not active
804  sem->saved_prio = -1;
805 
806  return (sem);
807 
808 badexit:
809  k_err_cnt++; // one more error so krnl will not start
810 
811  return (NULL);
812 }
813 
814 int k_set_sem_timer(struct k_t *sem, int val)
815 {
816  // there is no k_stop_sem_timer fct just call with val== 0 for stopping timer fct
817 
818  if (val < 0)
819  {
820  val = 0; // stop stop stop :-)
821  }
822 
823  DI();
824  sem->cnt2 = sem->cnt3 = val; // if 0 then timer is not running -
825  EI();
826 
827  return (0);
828 }
829 
830 int ki_signal(struct k_t *sem)
831 {
832  DI(); // just in case
833  if (sem->cnt1 < sem->maxv)
834  {
835 
836  sem->cnt1++; // Salute to Dijkstra
837 #ifdef KRNLBUG
838  k_sem_signal(sem->nr, sem->cnt1);
839 #endif
840 
841  if (sem->cnt1 <= 0)
842  {
843  sem->next->cnt2 = 0; // return code == ok
844  prio_enQ(pAQ, deQ(sem->next));
845  return (0); // task was waiting
846  }
847  else
848  {
849  return (1); // just delivered a signal - no task was waiting
850  }
851  } // CLIP :-(
852  else
853  {
854  if (SEM_MAX_VALUE > sem->clip)
855  {
856  sem->clip++;
857  }
858  // here we are on bad clip failure no signal takes place
859  // signal is lost !!!
860 #ifdef KRNLBUG
861  k_sem_clip(sem->nr, sem->clip);
862 #endif
863  return (-1);
864  }
865 }
866 
867 int k_signal(struct k_t *sem)
868 {
869  int res;
870 
871  DI();
872 
873  res = ki_signal(sem); // 1: ok no task to AQ, 0: ok task to AQ
874 
875  if (res == 0)
876  {
877  ki_task_shift(); // bq maybe started task has higher prio than me
878  }
879 
880  EI();
881 
882  return (res);
883 }
884 
885 /* normally ki_wait should not be used by user */
886 int ki_wait(struct k_t *sem, int timeout)
887 {
888  DI();
889 
890  if (0 < sem->cnt1)
891  {
892  sem->cnt1--; // Salute to Dijkstra
893 #ifdef KRNLBUG
894  k_sem_wait(sem->nr, sem->cnt1);
895 #endif
896  return (1); // ok: 1 bq we are not suspended.
897  }
898 
899  if (timeout < 0) // no luck, dont want to wait so bye bye
900  {
901 
902 #ifdef KRNLBUG
903  k_sem_wait(sem->nr, -1111); // -1111 timeout
904 #endif
905  return (-2);
906  }
907  // from here we want to wait
908  pRun->cnt2 = timeout; // 0 == wait forever
909 
910  if (timeout)
911  { // so we can be removed if timeout occurs
912  pRun->cnt3 = (int)sem; // nasty keep ref to semaphore in task stomach
913  }
914 
915  sem->cnt1--; // Salute to Diocjkstra
916 
917 #ifdef KRNLBUG
918  k_sem_wait(sem->nr, sem->cnt1);
919 #endif
920 
921  enQ(sem, deQ(pRun));
922  ki_task_shift();
923 
924  // back again - have semaphore received signal or timeout ?
925  pRun->cnt3 = 0; // reset ref to timer semaphore
926 
927  return ((char)(pRun->cnt2)); // 0: ok , -1: timeout
928 }
929 
930 int k_wait(struct k_t *sem, int timeout)
931 {
932  int retval;
933  DI();
934  retval = ki_wait(sem, timeout);
935  EI();
936  return retval; // 0: ok, -1: timeout
937 }
938 
939 int k_mut_ceil_enter(struct k_t *sem, int timeout)
940 {
941  int retval;
942  DI();
943  // if ceiling_prio < 0 then its a normal wait call
944  if (sem->ceiling_prio < 0)
945  {
946  retval = ki_wait(sem, timeout); // could call k_wait but just extra fct call
947  EI();
948  return retval;
949  }
950 
951  if (pRun->prio < sem->ceiling_prio)
952  { // I have higher priority than ceiling :-(
953  EI();
954  return CEILINGFAIL;
955  }
956 
957  // now we play imm ceiling protocol
958  sem->saved_prio = pRun->prio; // do im ceiling
959  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
960  prio_enQ(pAQ, deQ(pRun)); // resinsert me in AQ acc to nwe(old) priority
961  retval = ki_wait(sem, timeout);
962  // coming back interrupt is still disabled !
963 
964  // chk if we did get semaphore
965  if (retval < 0)
966  { // NOPE we did not
967  pRun->prio = sem->saved_prio; // reset to my old priority
968  prio_enQ(pAQ, deQ(pRun)); // reinsert me in AQ acc to nwe(old) priority
969  ki_task_shift(); // bq maybe started task has higher prio than me
970  }
971  EI();
972  return retval; // 0(has waited),1(straight through) : ok, -1: timeout
973 }
974 
975 int k_mut_ceil_leave(struct k_t *sem)
976 {
977  int res;
978 
979  DI();
980  if (sem->ceiling_prio < 0)
981  { // just std signal
982  return k_signal(sem);
983  }
984 
985  res = ki_signal(sem); // 1: ok no task to AQ, 0: ok task to AQ
986 
987  // coming back interrupt is still disabled !
988  pRun->prio = sem->saved_prio; // reset to my old priority
989 
990  prio_enQ(pAQ, deQ(pRun)); // resinsert me in AQ acc to nwe(old) priority
991 
992  ki_task_shift(); // bq maybe started task has higher prio than me
993 
994  EI();
995 
996  return (res);
997 }
998 
999 int k_sem_signals_lost(struct k_t *sem)
1000 {
1001  int x;
1002 
1003  DI();
1004 
1005  x = sem->clip;
1006  sem->clip = 0;
1007 
1008  EI();
1009  return x;
1010 }
1011 
1012 int ki_semval(struct k_t *sem)
1013 {
1014  DI(); // dont remove this - bq k_semval depends on it
1015 
1016  return (sem->cnt1);
1017 }
1018 
1019 int k_semval(struct k_t *sem)
1020 {
1021  int v;
1022  v = ki_semval(sem);
1023  EI();
1024  return v;
1025 }
1026 
1027 int ki_msg_count(struct k_msg_t *m)
1028 {
1029  DI(); // dont remove this - bq k_semval depends on it
1030  return m->cnt;
1031 }
1032 
1033 int k_msg_count(struct k_msg_t *m)
1034 {
1035  int v;
1036  // not needed to DI - its in ki_msg_count ... DI ();
1037  v = ki_msg_count(m);
1038  EI();
1039  return v;
1040 }
1041 
1042 struct k_msg_t *
1043 k_crt_send_Q(int nr_el, int el_size, void *pBuf)
1044 {
1045  struct k_msg_t *pMsg;
1046 
1047  if (k_running)
1048  {
1049  return (NULL);
1050  }
1051 
1052  if (k_msg <= nr_send)
1053  {
1054  goto errexit;
1055  }
1056 
1057  if (k_sem <= nr_sem)
1058  {
1059  goto errexit;
1060  }
1061 
1062  pMsg = send_pool + nr_send;
1063  pMsg->nr = nr_send; // I am element nr nr_send in msgQ pool
1064  nr_send++;
1065 
1066  pMsg->sem = k_crt_sem(0, nr_el); // we are using a sem for sync part snd <-> rcv
1067 
1068  if (pMsg->sem == NULL)
1069  {
1070  goto errexit;
1071  }
1072 
1073  pMsg->pBuf = (char *)pBuf;
1074  pMsg->r = pMsg->w = -1;
1075  pMsg->el_size = el_size;
1076  pMsg->nr_el = nr_el;
1077  pMsg->lost_msg = 0;
1078  pMsg->cnt = 0; // count nr elm in Q
1079 
1080  return (pMsg);
1081 
1082 errexit:
1083  k_err_cnt++;
1084  return (NULL);
1085 }
1086 
1087 char ki_send(struct k_msg_t *pB, void *el)
1088 {
1089 
1090  int i;
1091  char *pSrc, *pDst;
1092 
1093  if (pB->nr_el <= pB->cnt)
1094  {
1095  // nope - no room for a putting new msg in Q ?
1096  if (pB->lost_msg < SEM_MAX_VALUE)
1097  {
1098  pB->lost_msg++;
1099  }
1100 #ifdef KRNLBUG
1101  k_send_Q_clip(pB->nr, pB->lost_msg);
1102 #endif
1103  return (-1); // nope
1104  }
1105  else
1106  {
1107 
1108  pB->cnt++;
1109 
1110  pSrc = (char *)el;
1111 
1112  pB->w++;
1113  if (pB->nr_el <= pB->w) // simple wrap around
1114  {
1115  pB->w = 0;
1116  }
1117 
1118  pDst = pB->pBuf + (pB->w * pB->el_size); // calculate where we shall put msg in ringbuf
1119 
1120  for (i = 0; i < pB->el_size; i++)
1121  {
1122  // copy to Q
1123  *(pDst++) = *(pSrc++);
1124  }
1125  return (ki_signal(pB->sem)); // indicate a new msg is in Q
1126  }
1127 }
1128 
1129 char k_send(struct k_msg_t *pB, void *el)
1130 {
1131  char res;
1132 
1133  DI();
1134 
1135  res = ki_send(pB, el);
1136  if (res == 0) // if new task in AQ == someone was waiting for msg
1137  { // if 1 then nobody was waiting so no neeed for task shift
1138  ki_task_shift();
1139  }
1140 
1141  EI();
1142  return (res);
1143 }
1144 
1145 char ki_receive(struct k_msg_t *pB, void *el, int *lost_msg)
1146 {
1147  int i;
1148  char r, *pSrc, *pDst;
1149 
1150  // can be called from ISR bq no blocking
1151  DI(); // just to be sure
1152 
1153  if (0 <= (r = ki_wait(pB->sem, -1)))
1154  {
1155 
1156  pDst = (char *)el;
1157  pB->r++;
1158  pB->cnt--; // got one
1159 
1160  if (pB->nr_el <= pB->r)
1161  {
1162  pB->r = 0;
1163  }
1164 
1165  pSrc = pB->pBuf + pB->r * pB->el_size;
1166 
1167  for (i = 0; i < pB->el_size; i++)
1168  {
1169  *(pDst++) = *(pSrc++);
1170  }
1171  if (lost_msg)
1172  {
1173  *lost_msg = pB->lost_msg;
1174  pB->lost_msg = 0;
1175  }
1176  return (r); // yes
1177  }
1178 
1179  return (-1); // nothing for you my friend
1180 }
1181 
1182 char k_receive(struct k_msg_t *pB, void *el, int timeout, int *lost_msg)
1183 {
1184 
1185  int i;
1186  char r, *pSrc, *pDst;
1187 
1188  DI();
1189 
1190  if (0 <= (r = ki_wait(pB->sem, timeout)))
1191  {
1192  // yes we did get a msg :-)
1193  // ki_wait bq then intr is not enabled when coming back
1194 
1195  pDst = (char *)el;
1196  pB->r++;
1197  pB->cnt--; // got one
1198 
1199  if (pB->nr_el <= pB->r)
1200  {
1201  pB->r = 0;
1202  }
1203 
1204  pSrc = pB->pBuf + pB->r * pB->el_size;
1205 
1206  for (i = 0; i < pB->el_size; i++)
1207  {
1208  *(pDst++) = *(pSrc++);
1209  }
1210 
1211  if (lost_msg)
1212  {
1213  *lost_msg = pB->lost_msg;
1214  pB->lost_msg = 0;
1215  }
1216 
1217  EI();
1218  return (r); // 1 if no suspension bq msg was already present, 0: ok if you have waited on msg
1219  }
1220 
1221  EI();
1222  return (-1); // nothing for you my friend
1223 }
1224 
1225 void k_round_robbin(void)
1226 {
1227 
1228  // reinsert running task in activeQ if round robbin is selected
1229  DI();
1230 
1231  prio_enQ(pAQ, deQ(pRun));
1232  ki_task_shift();
1233 
1234  EI();
1235 }
1236 
1237 void k_release(void)
1238 {
1239 
1240  // let next run
1241  DI();
1242  ki_task_shift();
1243  EI();
1244 }
1245 
1246 /* NASTY void from vrs 2001 it is main itself can be changed back
1247 */
1248 
1249 /*
1250  void
1251  dummy_task (void)
1252  {
1253  while (1) {
1254  k_round_robbin ();
1255  }
1256  }
1257 */
1258 
1259 // char dmy_stk[DMY_STK_SZ]; // dmy duty is nwo maintained by org main
1260 
1261 int k_init(int nrTask, int nrSem, int nrMsg)
1262 {
1263  if (k_running) // are you a fool ???
1264  {
1265  return (-666);
1266  }
1267 
1268  k_task = nrTask + 1; // +1 due to dummy
1269  k_sem = nrSem + nrMsg + 1; // due to that every msgQ has a builtin semaphore
1270  k_msg = nrMsg + 1; // to align so first user msgQ has index 1
1271  nr_send++; // to align so we waste one but ... better equal access
1272  task_pool = (struct k_t *)malloc(k_task * sizeof(struct k_t));
1273  sem_pool = (struct k_t *)malloc(k_sem * sizeof(struct k_t));
1274  send_pool = (struct k_msg_t *)malloc(k_msg * sizeof(struct k_msg_t));
1275 
1276  // we dont accept any errors
1277  if ((task_pool == NULL) || (sem_pool == NULL) || (send_pool == NULL))
1278  {
1279  k_err_cnt++;
1280  goto leave;
1281  }
1282  // init AQ as empty double chained list
1283  pAQ = &AQ;
1284  pAQ->next = pAQ->pred = pAQ;
1285  pAQ->prio = QHD_PRIO;
1286 
1287  // crt dummy
1288  //pDmy = k_crt_task (dummy_task, DMY_PRIO, dmy_stk, DMY_STK_SZ);
1289 
1290  pmain_el = task_pool;
1291  pmain_el->nr = 0;
1292  pmain_el->cnt2 = pmain_el->cnt3 = 0;
1293  nr_task++;
1294  pmain_el->prio = DMY_PRIO; // main is dummy
1295  prio_enQ(pAQ, pmain_el);
1296 
1297  pSleepSem = k_crt_sem(0, 2000);
1298 
1299 leave:
1300  return k_err_cnt;
1301 }
1302 
1303 int k_start(int tick)
1304 {
1305  int tm;
1306  /*
1307  TCCRxB
1308  48,88,168,328, 1280,2560
1309  timer 0 and 2 has same prescaler config:
1310  8 bit:
1311  0 0 0 No clock source (Timer/Counter stopped).
1312  0 0 1 clk T2S /(No prescaling)
1313  0 1 0 clk T2S /8 (From prescaler) 2000000 intr/sec at 1 downcount
1314  0 1 1 clk T2S /32 (From prescaler) 500000 intr/sec ...
1315  1 0 0 clk T2S /64 (From prescaler) 250000
1316  1 0 1 clk T2S /128 (From prescaler) 125000
1317  1 1 0 clk T 2 S /256 (From prescaler) 62500
1318  1 1 1 clk T 2 S /1024 (From prescaler) 15625 eq 15.625 count down for 1 millisec
1319  so 255 counts ~= 80.32 milli sec timer
1320 
1321  timer 1(328+megas), 3,4,5(megas only)
1322  1280, 2560,2561 has same prescaler config :
1323  FOR 16 bits !
1324  prescaler in cs2 cs1 cs0
1325  0 0 0 none
1326  0 0 1 /1 == none
1327  0 1 0 /8 2000000 intr/sec
1328  0 1 1 /64 250000 intr/sec
1329  1 0 0 /256 62500 intr/sec
1330  1 0 1 /1024 15625 intr/sec
1331  16MHz Arduino -> 16000000/1024 = 15625 intr/second at one count
1332  16MHz Arduino -> 16000000/256 = 62500 ticks/second
1333  -------------------------/64 = 250000 ticks/second !
1334 
1335  NB 16 bit counter so values >= 65535 is not working
1336  ************************************************************************************* */
1337 
1338  // will not start if errors during initialization
1339  if (k_err_cnt)
1340  {
1341  return -k_err_cnt;
1342  }
1343  // boundary check
1344  if (tm <= 0)
1345  {
1346  return -555;
1347  }
1348  else if (tick == 1)
1349  {
1350  tm = 1;
1351  k_tick_size = fakecnt = tm; // JDN NEW
1352  fakecnt_preset = 0; // on duty for every interrupt
1353  }
1354  else
1355  {
1356  return -666; // bad timer shall be 1
1357  }
1358 
1359  DI(); // silencio
1360 
1361  // outdated ? JDN NASTY
1362 #if defined(__AVR_ATmega32U4__)
1363  // 32u4 have no intern/extern clock source register
1364 #else
1365  // should be default ASSR &= ~(1 << AS2); // Select clock source: internal I/O clock 32u4 does not have this facility
1366 #endif
1367 
1368 #if (KRNLTMR != 0)
1369  // hm we are heading for 16 bit timers :-)
1370  TCCRxA = 0;
1371  TCCRxB = PRESCALE; // atm328s 2560,...
1372 
1373  if (F_CPU == 16000000L)
1374  {
1375  tcntValue = COUNTMAX - DIVV;
1376  }
1377  else
1378  {
1379  tcntValue = COUNTMAX - DIVV8; // 8 Mhz wwe assume
1380  }
1381 
1382  TCNTx = tcntValue;
1383 
1384  // let us start the show
1385  TIMSKx |= (1 << TOIEx); // enable interrupt
1386 #endif
1387 
1388  DI();
1389  pRun = pmain_el; // just for ki_task_shift
1390 
1391  k_running = 1;
1392 #ifdef WDT_TIMER
1393  k_enable_wdt();
1394 #endif
1395 
1396  ki_task_shift(); // bye bye from here
1397  EI();
1398 
1399  // this while loop bq main are dummy
1400  while (!stopp)
1401  {
1402  }
1403 
1404  return (pmain_el->cnt1); // haps from pocket from kstop
1405 }
1406 
1407 int k_stop(unsigned int exitVal)
1408 {
1409  // DANGEROUS - handle with care - no isr timer control etc etc
1410  // I WILL NEVER USE IT
1411  DI(); // silencio
1412  if (!k_running)
1413  {
1414  EI();
1415  return -1;
1416  }
1417 
1418  pmain_el->cnt1 = exitVal; // transfer in pocket
1419  //NASTY
1420  // stop tick timer isr
1421 #if (KRNLTMR != 0)
1422  TIMSKx &= ~(1 << TOIEx);
1423 #endif
1424 
1425  stopp = 1;
1426  // back to main
1427  AQ.next = pmain_el; // we will be the next BRUTAL WAY TO DO IT NASTY
1428  ki_task_shift();
1429  while (1)
1430  ; // you will never come here
1431 }
1432 
1433 unsigned long
1435 {
1436  unsigned long l;
1437  DI(); // just to be sure
1438  l = k_millis_counter;
1439  return l;
1440 }
1441 
1442 unsigned long
1444 {
1445  unsigned long l;
1446 
1447  DI();
1448  l = k_millis_counter;
1449  EI();
1450  return l;
1451 }
1452 
1453 int k_tmrInfo(void)
1454 {
1455  return (KRNLTMR);
1456 }
1457 
1458 // mem
1459 
1460 #ifdef NEVER
1461 char k_set_preempt(char on)
1462 {
1463  return 1; // JDN HACK
1464  /* obsolete
1465  if (on == 0 || on == 1) {
1466  krnl_preempt_flag = on;
1467  }
1468  return krnl_preempt_flag;
1469  */
1470 }
1471 
1472 char k_get_preempt(void)
1473 {
1474  return 123;
1475  //obsoletereturn krnl_preempt_flag;
1476 }
1477 
1478 #endif
1479 
1480 #ifdef KRNLBUG
1481 
1482 // defined as weak so compiler will take yours instead of mine
1483 void __attribute__((weak)) k_breakout(void)
1484 {
1485 }
1486 
1487 void __attribute__((weak)) k_sem_clip(unsigned char nr, int nrClip)
1488 {
1489 }
1490 
1491 void __attribute__((weak)) k_sem_signal(unsigned char nr, int semVal)
1492 {
1493 }
1494 
1495 void __attribute__((weak)) k_sem_wait(unsigned char nr, int semVal)
1496 {
1497 }
1498 
1499 void __attribute__((weak)) k_send_Q_clip(unsigned char nr, int nrClip)
1500 {
1501 }
1502 
1503 #endif
1504 
1505 #ifdef DYNMEMORY
1506 void *__attribute__((weak)) k_malloc(int k)
1507 {
1508  void *m;
1509  DI();
1510  m = malloc(k);
1511  EI();
1512  return m;
1513 }
1514 
1515 void __attribute__((weak)) k_free(void *m)
1516 {
1517 }
1518 #endif
1519 
1520 #ifdef WDT_TIMER
1521 void __attribute__((weak)) k_enable_wdt(void)
1522 {
1523  DI();
1524  wdt_enable(WDT_PERIOD);
1525  EI();
1526 }
1527 #endif
1528 
1529 /* EOF - JDN */
1530 
1531 /*
1532  #ifdef __cplusplus
1533  }
1534  #endif
1535 */
deQ
struct k_t * deQ(struct k_t *el)
Definition: krnl.c:345
timer0_millis
volatile unsigned long timer0_millis
k_mut_ceil_set
int k_mut_ceil_set(struct k_t *sem, char prio)
Definition: krnl.c:753
SEM_MAX_VALUE
#define SEM_MAX_VALUE
Definition: krnl.h:248
k_set_prio
int k_set_prio(char prio)
Definition: krnl.c:725
k_sem_signals_lost
int k_sem_signals_lost(struct k_t *sem)
Definition: krnl.c:999
nrClip
void int nrClip
Definition: krnl.h:1012
WDT_PERIOD
#define WDT_PERIOD
Definition: krnl.h:236
AQ
int AQ
Definition: krnl.c:286
k_unused_stak
int k_unused_stak(struct k_t *t)
Definition: krnl.c:698
k_msg
int k_msg
Definition: krnl.c:295
k_free
void k_free(void *m)
k_send
char k_send(struct k_msg_t *pB, void *el)
Definition: krnl.c:1129
DMY_PRIO
#define DMY_PRIO
Definition: krnl.h:240
fakecnt
volatile int fakecnt
Definition: krnl.c:301
k_task
int k_task
Definition: krnl.c:295
timer0_overflow_count
volatile unsigned long timer0_overflow_count
task_pool
struct k_t * task_pool
pmain_el
int * pmain_el
Definition: krnl.c:287
BACKSTOPPER
#define BACKSTOPPER
Definition: krnl.h:254
k_sleep
int k_sleep(int time)
Definition: krnl.c:677
ki_millis
unsigned long ki_millis(void)
Definition: krnl.c:1434
send_pool
struct k_msg_t * send_pool
Definition: krnl.c:293
k_t::clip
volatile int clip
Definition: krnl.h:352
K_CHG_STAK
#define K_CHG_STAK()
Definition: krnl.h:475
ki_semval
int ki_semval(struct k_t *sem)
Definition: krnl.c:1012
k_millis
unsigned long k_millis(void)
Definition: krnl.c:1443
k_running
volatile char k_running
Definition: krnl.c:298
STAK_HASH
#define STAK_HASH
Definition: krnl.h:244
k_config
int k_config
Definition: krnl.c:279
timer0_fract
unsigned char timer0_fract
k_msg_t::w
volatile int w
Definition: krnl.h:362
k_t::sp_hi
volatile char sp_hi
Definition: krnl.h:344
jumper
void jumper()
Definition: krnl.c:556
k_msg_t::el_size
volatile int el_size
Definition: krnl.h:361
k_round_robbin
void k_round_robbin(void)
Definition: krnl.c:1225
ISR
ISR(TIMER0_OVF_vect, ISR_NAKED)
Definition: krnl.c:416
k_signal
int k_signal(struct k_t *sem)
Definition: krnl.c:867
k_millis_counter
unsigned long k_millis_counter
Definition: krnl.c:306
enQ
void enQ(struct k_t *Q, struct k_t *el)
Definition: krnl.c:336
k_mut_ceil_leave
int k_mut_ceil_leave(struct k_t *sem)
Definition: krnl.c:975
fakecnt_preset
volatile int fakecnt_preset
Definition: krnl.c:302
k_t::sp_lo
volatile char sp_lo
Definition: krnl.h:343
k_init
int k_init(int nrTask, int nrSem, int nrMsg)
Definition: krnl.c:1261
k_tmrInfo
int k_tmrInfo(void)
Definition: krnl.c:1453
k_msg_t::nr_el
volatile int nr_el
Definition: krnl.h:361
prio_enQ
void prio_enQ(struct k_t *Q, struct k_t *el)
Definition: krnl.c:353
k_tick_size
unsigned int k_tick_size
Definition: krnl.c:307
hi8
#define hi8(X)
Definition: krnl.h:470
ki_wait
int ki_wait(struct k_t *sem, int timeout)
Definition: krnl.c:886
k_stop
int k_stop(unsigned int exitVal)
Definition: krnl.c:1407
k_t::nr
unsigned char nr
Definition: krnl.h:340
ZOMBI_PRIO
#define ZOMBI_PRIO
Definition: krnl.h:241
k_mut_ceil_enter
int k_mut_ceil_enter(struct k_t *sem, int timeout)
Definition: krnl.c:939
MILLIS_INC
#define MILLIS_INC
Definition: krnl.c:390
QHD_PRIO
#define QHD_PRIO
Definition: krnl.h:238
k_t::prio
char prio
Definition: krnl.h:345
k_release
void k_release(void)
Definition: krnl.c:1237
k_err_cnt
volatile char k_err_cnt
Definition: krnl.c:298
k_t::ceiling_prio
char ceiling_prio
Definition: krnl.h:346
tcntValue
volatile unsigned int tcntValue
Definition: krnl.c:300
k_t::cnt2
volatile int cnt2
Definition: krnl.h:349
stopp
static volatile char stopp
Definition: krnl.c:304
KRNLTMRVECTOR
#define KRNLTMRVECTOR
Definition: krnl.c:182
k_t
Definition: krnl.h:335
FRACT_MAX
#define FRACT_MAX
Definition: krnl.c:396
k_msg_t::sem
struct k_t * sem
Definition: krnl.h:359
tmr_indx
int tmr_indx
Definition: krnl.c:309
nr_sem
char nr_sem
Definition: krnl.c:296
pRun
int * pRun
Definition: krnl.c:290
k_t::cnt3
volatile int cnt3
Definition: krnl.h:350
k_set_sem_timer
int k_set_sem_timer(struct k_t *sem, int val)
Definition: krnl.c:814
k_msg_t::cnt
volatile int cnt
Definition: krnl.h:362
ki_msg_count
int ki_msg_count(struct k_msg_t *m)
Definition: krnl.c:1027
k_msg_t
Definition: krnl.h:355
lo8
#define lo8(X)
Definition: krnl.h:469
ki_task_shift
void ki_task_shift(void) __attribute__((naked))
k_wait
int k_wait(struct k_t *sem, int timeout)
Definition: krnl.c:930
pSleepSem
int * pSleepSem
Definition: krnl.c:291
k_t::cnt1
volatile int cnt1
Definition: krnl.h:348
k_t::pred
struct k_t * pred
Definition: krnl.h:342
ki_send
char ki_send(struct k_msg_t *pB, void *el)
Definition: krnl.c:1087
k_crt_sem
struct k_t * k_crt_sem(char init_val, int maxvalue)
Definition: krnl.c:772
k_crt_task
struct k_t * k_crt_task(void(*pTask)(void), char prio, int stkSize)
Definition: krnl.c:565
k_t::saved_prio
char saved_prio
Definition: krnl.h:347
val
void int val
Definition: krnl.h:1019
k_msg_t::r
volatile int r
Definition: krnl.h:362
krnl.h
nr_task
char nr_task
Definition: krnl.c:296
__attribute__
void __attribute__((naked, noinline))
Definition: krnl.c:547
k_msg_t::nr
unsigned char nr
Definition: krnl.h:358
k_t::maxv
volatile int maxv
Definition: krnl.h:351
k_malloc
void * k_malloc(int k)
k_eat_ticks
void k_eat_ticks(int ticks)
Definition: krnl.c:687
ki_signal
int ki_signal(struct k_t *sem)
Definition: krnl.c:830
k_semval
int k_semval(struct k_t *sem)
Definition: krnl.c:1019
freeRam
int freeRam(void)
Definition: krnl.c:654
KRNLBUG
#define KRNLBUG
Definition: krnl.h:222
sem_pool
int * sem_pool
Definition: krnl.c:285
k_sem
int k_sem
Definition: krnl.c:295
k_msg_count
int k_msg_count(struct k_msg_t *m)
Definition: krnl.c:1033
k_t::pt
void(* pt)(void)
Definition: krnl.h:338
k_t::next
struct k_t * next
Definition: krnl.h:341
nr_send
char nr_send
Definition: krnl.c:296
pAQ
int * pAQ
Definition: krnl.c:288
FRACT_INC
#define FRACT_INC
Definition: krnl.c:395
k_receive
char k_receive(struct k_msg_t *pB, void *el, int timeout, int *lost_msg)
Definition: krnl.c:1182
k_msg_t::pBuf
char * pBuf
Definition: krnl.h:360
ki_receive
char ki_receive(struct k_msg_t *pB, void *el, int *lost_msg)
Definition: krnl.c:1145
k_crt_send_Q
struct k_msg_t * k_crt_send_Q(int nr_el, int el_size, void *pBuf)
Definition: krnl.c:1043
k_start
int k_start(int tick)
Definition: krnl.c:1303
k_msg_t::lost_msg
volatile int lost_msg
Definition: krnl.h:361
CEILINGFAIL
#define CEILINGFAIL
Definition: krnl.h:256