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