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 *
566 k_crt_task(void (*pTask)(void), char prio, int stkSize)
567 //k_crt_task (void (*pTask) (void), char prio, char *pStk, int stkSize)
568 {
569  char *pStk;
570  struct k_t *pT;
571  int i;
572  char *s;
573 
574  if ((k_running) || ((prio <= 0) || (DMY_PRIO < prio)) || (k_task <= nr_task))
575  {
576  goto badexit;
577  }
578 
579  pStak = malloc(stkSize);
580  if (pStak == NULL)
581  {
582  goto badexit;
583  }
584  pT = task_pool + nr_task; // lets take a task descriptor
585  pT->nr = nr_task;
586  nr_task++;
587 
588  pT->cnt2 = 0; // no time out running on you for the time being
589  pT->cnt3 = 0; // no time out semaphore
590 
591  pT->cnt1 = (int)(pStk); // ref to my stack
592 
593  // stack paint :-)
594  for (i = 0; i < stkSize; i++) // put hash code on stak to be used by k_unused_stak()
595  {
596  pStk[i] = STAK_HASH;
597  }
598 
599  s = pStk + stkSize - 1; // now we point on top of stak
600  *(s--) = 0x00; // 1 byte safety distance :-)
601 
602  // an interrupt do only push PC on stack by HW - can be 2 or 3 bytes
603  // depending of 368/.../1280/2560
604 #ifdef BACKSTOPPER
605  pT->pt = pTask;
606  *(s--) = lo8(jumper); // so top now holds address of function
607  *(s--) = hi8(jumper); // which is code body for task
608 #else
609  *(s--) = lo8(pTask); // so top now holds address of function
610  *(s--) = hi8(pTask); // which is code body for task
611 #endif
612  // NB NB 2560 use 3 byte for call/ret addresses the rest only 2
613 #if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega2561__)
614  *(s--) = EIND; // best guess : 3 byte addresses !!! or just 0
615 #endif
616 
617  // r1 is the socalled zero value register
618  // see https://gcc.gnu.org/wiki/avr-gcc
619  // can tmp be non zero (multiplication etc)
620  *(s--) = 0x00; // r1
621  *(s--) = 0x00; // r0
622  *(s--) = 0x00; // sreg
623 
624  //1280 and 2560 need to save rampz reg just in case
625 #if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega2561__)
626  *(s--) = RAMPZ; // best guess 0x3b
627  // obsolete JDN *(s--) = EIND; // best guess
628 #endif
629 
630 #if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2561__)
631  *(s--) = EIND; // best guess 0x3c
632 #endif
633 
634  for (i = 0; i < 30; i++) //r2-r31 = 30 regs
635  {
636  *(s--) = 0x00;
637  }
638 
639  pT->sp_lo = lo8(s); // now we just need to save stakptr
640  pT->sp_hi = hi8(s); // in thread descriptor
641 
642  // HW DEPENDENT PART - ENDE
643 
644  pT->prio = prio; // maxv for holding org prio for inheritance
645  pT->maxv = (int)prio;
646  prio_enQ(pAQ, pT); // and put task in active Q
647 
648  return (pT);
649 
650 badexit:
651  k_err_cnt++;
652  return (NULL);
653 }
654 
655 int freeRam(void)
656 {
657  extern int __heap_start, *__brkval;
658  int x, v;
659  // NASTY
660  x = ((int)&v - (__brkval == 0 ? (int)&__heap_start : (int)__brkval)); // to remove warning
661  return x;
662  // hw specific :-/
663  //return ((int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval));
664 
665  /* from http://www.noah.org/wiki/Arduino_notes#debug_memory_problems_.28out_of_RAM.29
666  int freeRam () {
667  // __brkval is the address of the top of the heap if memory has been allocated.
668  // If __brkval is zero then it means malloc has not used any memory yet, so
669  // we look at the address of __heap_start.
670  extern int __heap_start
671  extern int *__brkval; // address of the top of heap
672  int stack_top;
673  return (int)&stack_top - ((int)__brkval == 0 ? (int)&__heap_start : (int)__brkval);
674  }
675  */
676 }
677 
678 int k_sleep(int time)
679 {
680  int r;
681  if (time <= 0)
682  return -1;
683  r = k_wait(pSleepSem, time);
684  if (r == -1) // timeout ? yes :-)
685  return 0;
686 }
687 
688 void k_eat_ticks(int ticks)
689 {
690  long msc = ticks * k_tick_size; // now in milliseconds
691  if (msc <= 0) // should never happen
692  return;
693  while (msc--)
694  { // not 100% accurate.
695  _delay_ms(1);
696  }
697 }
698 
699 int k_unused_stak(struct k_t *t)
700 {
701  int i;
702  char *pstk;
703 
704  if (t) // another task or yourself - NO CHK of validity !!!!!
705  {
706  pstk = (char *)(t->cnt1);
707  }
708  else
709  {
710  pstk = (char *)(pRun->cnt1);
711  }
712 
713  DI();
714  // look for stack paint
715  i = 0;
716  while (*pstk == STAK_HASH)
717  {
718  pstk++;
719  i++;
720  }
721  EI();
722 
723  return (i);
724 }
725 
726 int k_set_prio(char prio)
727 {
728  int i;
729 
730  if (!k_running)
731  {
732  return (-2);
733  }
734 
735  DI();
736 
737  if ((prio <= 0) || (DMY_PRIO <= prio)) // not legal value my friend
738  {
739  EI();
740  return (-1);
741  }
742  i = pRun->prio;
743 
744  pRun->prio = prio;
745 
746  prio_enQ(pAQ, deQ(pRun));
747  ki_task_shift();
748 
749  EI();
750 
751  return (i);
752 }
753 
754 int k_mut_ceil_set(struct k_t *sem, char prio)
755 {
756  // NB NB assume semaphore is created prior to this call
757  // NO CHECK - no mercy !!!
758  // work only BEFORE k_start
759  if (k_running)
760  {
761  return (-2); // bad bad
762  }
763 
764  if ((prio <= 0) || (DMY_PRIO <= prio))
765  {
766  return (-1); // bad bad
767  }
768  sem->ceiling_prio = prio;
769  return 0; // OK
770 }
771 
772 struct k_t *
773 k_crt_sem(char init_val, int maxvalue)
774 {
775  struct k_t *sem;
776 
777  if (k_running)
778  {
779  return (NULL);
780  }
781 
782  if ((init_val < 0) || (SEM_MAX_VALUE < init_val) || (maxvalue < 0) || (SEM_MAX_VALUE < maxvalue))
783  {
784  goto badexit;
785  }
786 
787  if (k_sem <= nr_sem) // no vacant in buf
788  {
789  goto badexit;
790  }
791 
792  sem = sem_pool + nr_sem; // allocate it
793  sem->nr = nr_sem;
794  nr_sem++;
795 
796  sem->cnt2 = 0; // no timer running
797  sem->next = sem->pred = sem; // point at myself == no one in Q
798  sem->prio = QHD_PRIO;
799  sem->cnt1 = init_val;
800 
801  sem->maxv = maxvalue;
802  sem->clip = 0;
803 
804  sem->ceiling_prio = -1; // to indicate it is not active
805  sem->saved_prio = -1;
806 
807  return (sem);
808 
809 badexit:
810  k_err_cnt++; // one more error so krnl will not start
811 
812  return (NULL);
813 }
814 
815 int k_set_sem_timer(struct k_t *sem, int val)
816 {
817  // there is no k_stop_sem_timer fct just call with val== 0 for stopping timer fct
818 
819  if (val < 0)
820  {
821  val = 0; // stop stop stop :-)
822  }
823 
824  DI();
825  sem->cnt2 = sem->cnt3 = val; // if 0 then timer is not running -
826  EI();
827 
828  return (0);
829 }
830 
831 int ki_signal(struct k_t *sem)
832 {
833  DI(); // just in case
834  if (sem->cnt1 < sem->maxv)
835  {
836 
837  sem->cnt1++; // Salute to Dijkstra
838 #ifdef KRNLBUG
839  k_sem_signal(sem->nr, sem->cnt1);
840 #endif
841 
842  if (sem->cnt1 <= 0)
843  {
844  sem->next->cnt2 = 0; // return code == ok
845  prio_enQ(pAQ, deQ(sem->next));
846  return (0); // task was waiting
847  }
848  else
849  {
850  return (1); // just delivered a signal - no task was waiting
851  }
852  } // CLIP :-(
853  else
854  {
855  if (SEM_MAX_VALUE > sem->clip)
856  {
857  sem->clip++;
858  }
859  // here we are on bad clip failure no signal takes place
860  // signal is lost !!!
861 #ifdef KRNLBUG
862  k_sem_clip(sem->nr, sem->clip);
863 #endif
864  return (-1);
865  }
866 }
867 
868 int k_signal(struct k_t *sem)
869 {
870  int res;
871 
872  DI();
873 
874  res = ki_signal(sem); // 1: ok no task to AQ, 0: ok task to AQ
875 
876  if (res == 0)
877  {
878  ki_task_shift(); // bq maybe started task has higher prio than me
879  }
880 
881  EI();
882 
883  return (res);
884 }
885 
886 /* normally ki_wait should not be used by user */
887 int ki_wait(struct k_t *sem, int timeout)
888 {
889  DI();
890 
891  if (0 < sem->cnt1)
892  {
893  sem->cnt1--; // Salute to Dijkstra
894 #ifdef KRNLBUG
895  k_sem_wait(sem->nr, sem->cnt1);
896 #endif
897  return (1); // ok: 1 bq we are not suspended.
898  }
899 
900  if (timeout < 0) // no luck, dont want to wait so bye bye
901  {
902 
903 #ifdef KRNLBUG
904  k_sem_wait(sem->nr, -1111); // -1111 timeout
905 #endif
906  return (-2);
907  }
908  // from here we want to wait
909  pRun->cnt2 = timeout; // 0 == wait forever
910 
911  if (timeout)
912  { // so we can be removed if timeout occurs
913  pRun->cnt3 = (int)sem; // nasty keep ref to semaphore in task stomach
914  }
915 
916  sem->cnt1--; // Salute to Diocjkstra
917 
918 #ifdef KRNLBUG
919  k_sem_wait(sem->nr, sem->cnt1);
920 #endif
921 
922  enQ(sem, deQ(pRun));
923  ki_task_shift();
924 
925  // back again - have semaphore received signal or timeout ?
926  pRun->cnt3 = 0; // reset ref to timer semaphore
927 
928  return ((char)(pRun->cnt2)); // 0: ok , -1: timeout
929 }
930 
931 int k_wait(struct k_t *sem, int timeout)
932 {
933  int retval;
934  DI();
935  retval = ki_wait(sem, timeout);
936  EI();
937  return retval; // 0: ok, -1: timeout
938 }
939 
940 int k_mut_ceil_enter(struct k_t *sem, int timeout)
941 {
942  int retval;
943  DI();
944  // if ceiling_prio < 0 then its a normal wait call
945  if (sem->ceiling_prio < 0)
946  {
947  retval = ki_wait(sem, timeout); // could call k_wait but just extra fct call
948  EI();
949  return retval;
950  }
951 
952  if (pRun->prio < sem->ceiling_prio)
953  { // I have higher priority than ceiling :-(
954  EI();
955  return CEILINGFAIL;
956  }
957 
958  // now we play imm ceiling protocol
959  sem->saved_prio = pRun->prio; // do im ceiling
960  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
961  prio_enQ(pAQ, deQ(pRun)); // resinsert me in AQ acc to nwe(old) priority
962  retval = ki_wait(sem, timeout);
963  // coming back interrupt is still disabled !
964 
965  // chk if we did get semaphore
966  if (retval < 0)
967  { // NOPE we did not
968  pRun->prio = sem->saved_prio; // reset to my old priority
969  prio_enQ(pAQ, deQ(pRun)); // reinsert me in AQ acc to nwe(old) priority
970  ki_task_shift(); // bq maybe started task has higher prio than me
971  }
972  EI();
973  return retval; // 0(has waited),1(straight through) : ok, -1: timeout
974 }
975 
976 int k_mut_ceil_leave(struct k_t *sem)
977 {
978  int res;
979 
980  DI();
981  if (sem->ceiling_prio < 0)
982  { // just std signal
983  return k_signal(sem);
984  }
985 
986  res = ki_signal(sem); // 1: ok no task to AQ, 0: ok task to AQ
987 
988  // coming back interrupt is still disabled !
989  pRun->prio = sem->saved_prio; // reset to my old priority
990 
991  prio_enQ(pAQ, deQ(pRun)); // resinsert me in AQ acc to nwe(old) priority
992 
993  ki_task_shift(); // bq maybe started task has higher prio than me
994 
995  EI();
996 
997  return (res);
998 }
999 
1000 int k_sem_signals_lost(struct k_t *sem)
1001 {
1002  int x;
1003 
1004  DI();
1005 
1006  x = sem->clip;
1007  sem->clip = 0;
1008 
1009  EI();
1010  return x;
1011 }
1012 
1013 int ki_semval(struct k_t *sem)
1014 {
1015  DI(); // dont remove this - bq k_semval depends on it
1016 
1017  return (sem->cnt1);
1018 }
1019 
1020 int k_semval(struct k_t *sem)
1021 {
1022  int v;
1023  v = ki_semval(sem);
1024  EI();
1025  return v;
1026 }
1027 
1028 int ki_msg_count(struct k_msg_t *m)
1029 {
1030  DI(); // dont remove this - bq k_semval depends on it
1031  return m->cnt;
1032 }
1033 
1034 int k_msg_count(struct k_msg_t *m)
1035 {
1036  int v;
1037  // not needed to DI - its in ki_msg_count ... DI ();
1038  v = ki_msg_count(m);
1039  EI();
1040  return v;
1041 }
1042 
1043 struct k_msg_t *
1044 k_crt_send_Q(int nr_el, int el_size, void *pBuf)
1045 {
1046  struct k_msg_t *pMsg;
1047 
1048  if (k_running)
1049  {
1050  return (NULL);
1051  }
1052 
1053  if (k_msg <= nr_send)
1054  {
1055  goto errexit;
1056  }
1057 
1058  if (k_sem <= nr_sem)
1059  {
1060  goto errexit;
1061  }
1062 
1063  pMsg = send_pool + nr_send;
1064  pMsg->nr = nr_send; // I am element nr nr_send in msgQ pool
1065  nr_send++;
1066 
1067  pMsg->sem = k_crt_sem(0, nr_el); // we are using a sem for sync part snd <-> rcv
1068 
1069  if (pMsg->sem == NULL)
1070  {
1071  goto errexit;
1072  }
1073 
1074  pMsg->pBuf = (char *)pBuf;
1075  pMsg->r = pMsg->w = -1;
1076  pMsg->el_size = el_size;
1077  pMsg->nr_el = nr_el;
1078  pMsg->lost_msg = 0;
1079  pMsg->cnt = 0; // count nr elm in Q
1080 
1081  return (pMsg);
1082 
1083 errexit:
1084  k_err_cnt++;
1085  return (NULL);
1086 }
1087 
1088 char ki_send(struct k_msg_t *pB, void *el)
1089 {
1090 
1091  int i;
1092  char *pSrc, *pDst;
1093 
1094  if (pB->nr_el <= pB->cnt)
1095  {
1096  // nope - no room for a putting new msg in Q ?
1097  if (pB->lost_msg < SEM_MAX_VALUE)
1098  {
1099  pB->lost_msg++;
1100  }
1101 #ifdef KRNLBUG
1102  k_send_Q_clip(pB->nr, pB->lost_msg);
1103 #endif
1104  return (-1); // nope
1105  }
1106  else
1107  {
1108 
1109  pB->cnt++;
1110 
1111  pSrc = (char *)el;
1112 
1113  pB->w++;
1114  if (pB->nr_el <= pB->w) // simple wrap around
1115  {
1116  pB->w = 0;
1117  }
1118 
1119  pDst = pB->pBuf + (pB->w * pB->el_size); // calculate where we shall put msg in ringbuf
1120 
1121  for (i = 0; i < pB->el_size; i++)
1122  {
1123  // copy to Q
1124  *(pDst++) = *(pSrc++);
1125  }
1126  return (ki_signal(pB->sem)); // indicate a new msg is in Q
1127  }
1128 }
1129 
1130 char k_send(struct k_msg_t *pB, void *el)
1131 {
1132  char res;
1133 
1134  DI();
1135 
1136  res = ki_send(pB, el);
1137  if (res == 0) // if new task in AQ == someone was waiting for msg
1138  { // if 1 then nobody was waiting so no neeed for task shift
1139  ki_task_shift();
1140  }
1141 
1142  EI();
1143  return (res);
1144 }
1145 
1146 char ki_receive(struct k_msg_t *pB, void *el, int *lost_msg)
1147 {
1148  int i;
1149  char r, *pSrc, *pDst;
1150 
1151  // can be called from ISR bq no blocking
1152  DI(); // just to be sure
1153 
1154  if (0 <= (r = ki_wait(pB->sem, -1)))
1155  {
1156 
1157  pDst = (char *)el;
1158  pB->r++;
1159  pB->cnt--; // got one
1160 
1161  if (pB->nr_el <= pB->r)
1162  {
1163  pB->r = 0;
1164  }
1165 
1166  pSrc = pB->pBuf + pB->r * pB->el_size;
1167 
1168  for (i = 0; i < pB->el_size; i++)
1169  {
1170  *(pDst++) = *(pSrc++);
1171  }
1172  if (lost_msg)
1173  {
1174  *lost_msg = pB->lost_msg;
1175  pB->lost_msg = 0;
1176  }
1177  return (r); // yes
1178  }
1179 
1180  return (-1); // nothing for you my friend
1181 }
1182 
1183 char k_receive(struct k_msg_t *pB, void *el, int timeout, int *lost_msg)
1184 {
1185 
1186  int i;
1187  char r, *pSrc, *pDst;
1188 
1189  DI();
1190 
1191  if (0 <= (r = ki_wait(pB->sem, timeout)))
1192  {
1193  // yes we did get a msg :-)
1194  // ki_wait bq then intr is not enabled when coming back
1195 
1196  pDst = (char *)el;
1197  pB->r++;
1198  pB->cnt--; // got one
1199 
1200  if (pB->nr_el <= pB->r)
1201  {
1202  pB->r = 0;
1203  }
1204 
1205  pSrc = pB->pBuf + pB->r * pB->el_size;
1206 
1207  for (i = 0; i < pB->el_size; i++)
1208  {
1209  *(pDst++) = *(pSrc++);
1210  }
1211 
1212  if (lost_msg)
1213  {
1214  *lost_msg = pB->lost_msg;
1215  pB->lost_msg = 0;
1216  }
1217 
1218  EI();
1219  return (r); // 1 if no suspension bq msg was already present, 0: ok if you have waited on msg
1220  }
1221 
1222  EI();
1223  return (-1); // nothing for you my friend
1224 }
1225 
1226 void k_round_robbin(void)
1227 {
1228 
1229  // reinsert running task in activeQ if round robbin is selected
1230  DI();
1231 
1232  prio_enQ(pAQ, deQ(pRun));
1233  ki_task_shift();
1234 
1235  EI();
1236 }
1237 
1238 void k_release(void)
1239 {
1240 
1241  // let next run
1242  DI();
1243  ki_task_shift();
1244  EI();
1245 }
1246 
1247 /* NASTY void from vrs 2001 it is main itself can be changed back
1248 */
1249 
1250 /*
1251  void
1252  dummy_task (void)
1253  {
1254  while (1) {
1255  k_round_robbin ();
1256  }
1257  }
1258 */
1259 
1260 // char dmy_stk[DMY_STK_SZ]; // dmy duty is nwo maintained by org main
1261 
1262 int k_init(int nrTask, int nrSem, int nrMsg)
1263 {
1264  if (k_running) // are you a fool ???
1265  {
1266  return (-666);
1267  }
1268 
1269  k_task = nrTask + 1; // +1 due to dummy
1270  k_sem = nrSem + nrMsg + 1; // due to that every msgQ has a builtin semaphore
1271  k_msg = nrMsg + 1; // to align so first user msgQ has index 1
1272  nr_send++; // to align so we waste one but ... better equal access
1273  task_pool = (struct k_t *)malloc(k_task * sizeof(struct k_t));
1274  sem_pool = (struct k_t *)malloc(k_sem * sizeof(struct k_t));
1275  send_pool = (struct k_msg_t *)malloc(k_msg * sizeof(struct k_msg_t));
1276 
1277  // we dont accept any errors
1278  if ((task_pool == NULL) || (sem_pool == NULL) || (send_pool == NULL))
1279  {
1280  k_err_cnt++;
1281  goto leave;
1282  }
1283  // init AQ as empty double chained list
1284  pAQ = &AQ;
1285  pAQ->next = pAQ->pred = pAQ;
1286  pAQ->prio = QHD_PRIO;
1287 
1288  // crt dummy
1289  //pDmy = k_crt_task (dummy_task, DMY_PRIO, dmy_stk, DMY_STK_SZ);
1290 
1291  pmain_el = task_pool;
1292  pmain_el->nr = 0;
1293  pmain_el->cnt2 = pmain_el->cnt3 = 0;
1294  nr_task++;
1295  pmain_el->prio = DMY_PRIO; // main is dummy
1296  prio_enQ(pAQ, pmain_el);
1297 
1298  pSleepSem = k_crt_sem(0, 2000);
1299 
1300 leave:
1301  return k_err_cnt;
1302 }
1303 
1304 int k_start(int tick)
1305 {
1306  int tm;
1307  /*
1308  TCCRxB
1309  48,88,168,328, 1280,2560
1310  timer 0 and 2 has same prescaler config:
1311  8 bit:
1312  0 0 0 No clock source (Timer/Counter stopped).
1313  0 0 1 clk T2S /(No prescaling)
1314  0 1 0 clk T2S /8 (From prescaler) 2000000 intr/sec at 1 downcount
1315  0 1 1 clk T2S /32 (From prescaler) 500000 intr/sec ...
1316  1 0 0 clk T2S /64 (From prescaler) 250000
1317  1 0 1 clk T2S /128 (From prescaler) 125000
1318  1 1 0 clk T 2 S /256 (From prescaler) 62500
1319  1 1 1 clk T 2 S /1024 (From prescaler) 15625 eq 15.625 count down for 1 millisec
1320  so 255 counts ~= 80.32 milli sec timer
1321 
1322  timer 1(328+megas), 3,4,5(megas only)
1323  1280, 2560,2561 has same prescaler config :
1324  FOR 16 bits !
1325  prescaler in cs2 cs1 cs0
1326  0 0 0 none
1327  0 0 1 /1 == none
1328  0 1 0 /8 2000000 intr/sec
1329  0 1 1 /64 250000 intr/sec
1330  1 0 0 /256 62500 intr/sec
1331  1 0 1 /1024 15625 intr/sec
1332  16MHz Arduino -> 16000000/1024 = 15625 intr/second at one count
1333  16MHz Arduino -> 16000000/256 = 62500 ticks/second
1334  -------------------------/64 = 250000 ticks/second !
1335 
1336  NB 16 bit counter so values >= 65535 is not working
1337  ************************************************************************************* */
1338 
1339  // will not start if errors during initialization
1340  if (k_err_cnt)
1341  {
1342  return -k_err_cnt;
1343  }
1344  // boundary check
1345  if (tm <= 0)
1346  {
1347  return -555;
1348  }
1349  else if (tick == 1)
1350  {
1351  tm = 1;
1352  k_tick_size = fakecnt = tm; // JDN NEW
1353  fakecnt_preset = 0; // on duty for every interrupt
1354  }
1355  else
1356  {
1357  return -666; // bad timer shall be 1
1358  }
1359 
1360  DI(); // silencio
1361 
1362  // outdated ? JDN NASTY
1363 #if defined(__AVR_ATmega32U4__)
1364  // 32u4 have no intern/extern clock source register
1365 #else
1366  // should be default ASSR &= ~(1 << AS2); // Select clock source: internal I/O clock 32u4 does not have this facility
1367 #endif
1368 
1369 #if (KRNLTMR != 0)
1370  // hm we are heading for 16 bit timers :-)
1371  TCCRxA = 0;
1372  TCCRxB = PRESCALE; // atm328s 2560,...
1373 
1374  if (F_CPU == 16000000L)
1375  {
1376  tcntValue = COUNTMAX - DIVV;
1377  }
1378  else
1379  {
1380  tcntValue = COUNTMAX - DIVV8; // 8 Mhz wwe assume
1381  }
1382 
1383  TCNTx = tcntValue;
1384 
1385  // let us start the show
1386  TIMSKx |= (1 << TOIEx); // enable interrupt
1387 #endif
1388 
1389  DI();
1390  pRun = pmain_el; // just for ki_task_shift
1391 
1392  k_running = 1;
1393 #ifdef WDT_TIMER
1394  k_enable_wdt();
1395 #endif
1396 
1397  ki_task_shift(); // bye bye from here
1398  EI();
1399 
1400  // this while loop bq main are dummy
1401  while (!stopp)
1402  {
1403  }
1404 
1405  return (pmain_el->cnt1); // haps from pocket from kstop
1406 }
1407 
1408 int k_stop(unsigned int exitVal)
1409 {
1410  // DANGEROUS - handle with care - no isr timer control etc etc
1411  // I WILL NEVER USE IT
1412  DI(); // silencio
1413  if (!k_running)
1414  {
1415  EI();
1416  return -1;
1417  }
1418 
1419  pmain_el->cnt1 = exitVal; // transfer in pocket
1420  //NASTY
1421  // stop tick timer isr
1422 #if (KRNLTMR != 0)
1423  TIMSKx &= ~(1 << TOIEx);
1424 #endif
1425 
1426  stopp = 1;
1427  // back to main
1428  AQ.next = pmain_el; // we will be the next BRUTAL WAY TO DO IT NASTY
1429  ki_task_shift();
1430  while (1)
1431  ; // you will never come here
1432 }
1433 
1434 unsigned long
1436 {
1437  unsigned long l;
1438  DI(); // just to be sure
1439  l = k_millis_counter;
1440  return l;
1441 }
1442 
1443 unsigned long
1445 {
1446  unsigned long l;
1447 
1448  DI();
1449  l = k_millis_counter;
1450  EI();
1451  return l;
1452 }
1453 
1454 int k_tmrInfo(void)
1455 {
1456  return (KRNLTMR);
1457 }
1458 
1459 // mem
1460 
1461 #ifdef NEVER
1462 char k_set_preempt(char on)
1463 {
1464  return 1; // JDN HACK
1465  /* obsolete
1466  if (on == 0 || on == 1) {
1467  krnl_preempt_flag = on;
1468  }
1469  return krnl_preempt_flag;
1470  */
1471 }
1472 
1473 char k_get_preempt(void)
1474 {
1475  return 123;
1476  //obsoletereturn krnl_preempt_flag;
1477 }
1478 
1479 #endif
1480 
1481 #ifdef KRNLBUG
1482 
1483 // defined as weak so compiler will take yours instead of mine
1484 void __attribute__((weak)) k_breakout(void)
1485 {
1486 }
1487 
1488 void __attribute__((weak)) k_sem_clip(unsigned char nr, int nrClip)
1489 {
1490 }
1491 
1492 void __attribute__((weak)) k_sem_signal(unsigned char nr, int semVal)
1493 {
1494 }
1495 
1496 void __attribute__((weak)) k_sem_wait(unsigned char nr, int semVal)
1497 {
1498 }
1499 
1500 void __attribute__((weak)) k_send_Q_clip(unsigned char nr, int nrClip)
1501 {
1502 }
1503 
1504 #endif
1505 
1506 #ifdef DYNMEMORY
1507 void *__attribute__((weak)) k_malloc(int k)
1508 {
1509  void *m;
1510  DI();
1511  m = malloc(k);
1512  EI();
1513  return m;
1514 }
1515 
1516 void __attribute__((weak)) k_free(void *m)
1517 {
1518 }
1519 #endif
1520 
1521 #ifdef WDT_TIMER
1522 void __attribute__((weak)) k_enable_wdt(void)
1523 {
1524  DI();
1525  wdt_enable(WDT_PERIOD);
1526  EI();
1527 }
1528 #endif
1529 
1530 /* EOF - JDN */
1531 
1532 /*
1533  #ifdef __cplusplus
1534  }
1535  #endif
1536 */
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:754
SEM_MAX_VALUE
#define SEM_MAX_VALUE
Definition: krnl.h:248
k_set_prio
int k_set_prio(char prio)
Definition: krnl.c:726
k_sem_signals_lost
int k_sem_signals_lost(struct k_t *sem)
Definition: krnl.c:1000
nrClip
void int nrClip
Definition: krnl.h:1038
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:699
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:1130
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:678
ki_millis
unsigned long ki_millis(void)
Definition: krnl.c:1435
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:1013
k_millis
unsigned long k_millis(void)
Definition: krnl.c:1444
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:1226
k_signal
int k_signal(struct k_t *sem)
Definition: krnl.c:868
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:976
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:1262
k_tmrInfo
int k_tmrInfo(void)
Definition: krnl.c:1454
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:887
k_stop
int k_stop(unsigned int exitVal)
Definition: krnl.c:1408
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:940
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:1238
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:815
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:1028
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:931
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:1088
k_crt_sem
struct k_t * k_crt_sem(char init_val, int maxvalue)
Definition: krnl.c:773
k_crt_task
struct k_t * k_crt_task(void(*pTask)(void), char prio, int stkSize)
Definition: krnl.c:566
ISR
ISR(KRNLTMRVECTOR, ISR_NAKED)
Definition: krnl.c:416
k_t::saved_prio
char saved_prio
Definition: krnl.h:347
val
void int val
Definition: krnl.h:1045
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:688
ki_signal
int ki_signal(struct k_t *sem)
Definition: krnl.c:831
k_semval
int k_semval(struct k_t *sem)
Definition: krnl.c:1020
freeRam
int freeRam(void)
Definition: krnl.c:655
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:1034
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:1183
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:1146
k_crt_send_Q
struct k_msg_t * k_crt_send_Q(int nr_el, int el_size, void *pBuf)
Definition: krnl.c:1044
k_start
int k_start(int tick)
Definition: krnl.c:1304
k_msg_t::lost_msg
volatile int lost_msg
Definition: krnl.h:361
CEILINGFAIL
#define CEILINGFAIL
Definition: krnl.h:256