dit projekt
krnl.h
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  * final sep 2022 *
15  * *
16  * this version adapted for Arduino
17  *
18  * (C) 2012,2013,2014
19  * 2017,2018,2019,2021,2022,2023
20  *
21  *
22  * IF YOU ARE LUCKY LOOK HERE
23  *
24  * https://github.com/jdn-aau/krnl
25  *
26  *
27  *
28  * Jens Dalsgaard Nielsen <jdn@es.aau.dk>
29  * http://es.aau.dk/staff/jdn
30  * Section of Automation & Control
31  * Aalborg University,
32  * Denmark
33  *
34  * "THE BEER-WARE LICENSE" (frit efter PHK)
35  * <jdn@es.aau.dk> wrote this file. As long as you
36  * retain this notice you can do whatever you want
37  * with this stuff. If we meet some day, and you think
38  * this stuff is worth it ...
39  * you can buy me a beer in return :-)
40  * or if you are real happy then ...
41  * single malt will be well received :-)
42  *
43  * Use it at your own risk - no warranty
44  *
45  * nice info...
46  * http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_cplusplus
47  * at 20090611
48  * - k_eat_time now eats time in quants of krnl tick speed but not one quant
49  *boundary
50  * - added k_malloc and k_free
51  * k_free dont free memory bq we do not want fragmentation
52  * so DONT USE k_free. I do NOT free memory
53  * - k_malloc and k_free are weak functions so you can just add your own
54  *versions
55  * - watchdog is enabled (2sec and reset in krnl timer) in weak function
56  *k_enable_wdt
57  *
58  * remember to update in krnl.c !!!
59  *****************************************************/
60 #define KRNL_VRS 20240525
61 
62 #ifndef KRNL
63 #define KRNL
64 
65 // IMPORTANT DEFINES !!!!
66 // IMPORTANT DEFINES !!!!
67 // IMPORTANT DEFINES !!!!
68 // IMPORTANT DEFINES !!!!
69 // IMPORTANT DEFINES !!!!
70 
71 #define KRNLBUG // KRNLBUG ACTIVATE BREAK OUT FUNCTIONS
72 
73 // BACKSTOPPER wraps a looping fct around your task so it will just restart
74 // like loop function
75 // BEWARE bq local variables in the task body just evaporate - as always
76 #define BACKSTOPPER
77 
78 // if you want to use k_malloc
79 // NB k_free wont release mem due to possible fragmentation
80 // SO DONT USE k_free its just a fake
81 // NEVER !!! free men in a rt system...
82 // and please do all malloc before starting running
83 
84 #define DYNMEMORY
85 
86 // DON NOT CHANGE K_TICK - must be 1 millisec
87 #define K_TICK 1
88 
89 // if defined you will stop in backstopper, else you will jump back to task s
90 // see comments about local vars above
91 //#define STOP_IN_BACKSTOPPER
92 
93 //#define WDT_TIMER
94 #define WDT_PERIOD WDTO_1S
95 
96 
97 // IF YOU WANT READER WRITER LOCK THEN DEFINE
98 // experimental - no guarantee
99 //https://www.geeksforgeeks.org/readers-writers-problem-writers-preference-solution/?ref=rp
100 //https://www.geeksforgeeks.org/readers-writers-problem-set-1-introduction-and-readers-preference-solution/
101 // https://www.tutorialspoint.com/readers-writers-problem
102 
103 //#define READERWRITER
104 
105 // Define watchdog timer and period
106 // if you enable it it will be running at once
107 
108 // END IMPORTANT DEFINES
109 // END IMPORTANT DEFINES
110 // END IMPORTANT DEFINES
111 // END IMPORTANT DEFINES
112 // END IMPORTANT DEFINES
113 // END IMPORTANT DEFINES
114 
115 
116 
117 // SELECTION OF HW TIMER TO BE USED FOR krnl tick
118 // SELECTION OF HW TIMER TO BE USED FOR krnl tick
119 // SELECTION OF HW TIMER TO BE USED FOR krnl tick
120 
121 // Reverted to use only timer 2
122 //HAS IMPACT ON PWM !!!! SEE BELOW !!!
123 
124 #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) \
125  || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega1284P__)\
126  || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__)\
127  || defined(__AVR_ATmega328__)
128 #define KRNLTMR 2
129 
130 #elif defined(__AVR_ATmega32U4__)
131 //#define KRNLTMR 3
132 #error "32u4 hmm AVR cpu type - bad place to come"
133 #else
134 #error "unknown AVR cpu type - bad place to come"
135 #endif
136 
137 /***********************
138 
139  NB NB ABOUT WRAP AROUND
140 
141  Krnl maintain a milisecond timer (k_millis_counter)
142  It s 32 bit unsigned long so it wraps around after 49.7 days.
143  As all timing internal in krnl is relative (from now) then
144  wrap around will have no influence on krnl !!!fk_eat
145 
146  NB NB ABOUT TIMERS PORTS ETC
147 
148  You can configure krnl to use timer 1,2,3,4,5
149 
150  If you want to use timer 0 then you need to
151 
152  - set KRNLTMR = 0 just below in USER CONFIGURATION PART
153  - mangle with Arduino library code in ...
154  hardware/arduino/avr/cores/arduino/wiring.c
155  rename ISR ... with function head:
156  #if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) ||
157 defined(__AVR_ATtiny84__) ISR(TIM0_OVF_vect) #else ISR(TIMER0_OVF_vect) #endif
158  to something else : mayby void kurt()
159 
160  This is because krnl install an ISR on timer0 and there cant be two
161  Krnl to maintain the millis counters so everything with millis, micros etc is
162 as usual.
163 
164  Buth normally you cant use timer 0 bq it is used for millis and preallocated.
165 
166  See below
167 
168  When using a timer you must be aware of that it will prohibit you from things
169 like
170  - tone (pwm sound) uses timer2
171 
172  ... from http://blog.oscarliang.net/arduino-timer-and-interrupt-tutorial/
173 
174  Timer0:
175  - 8bit timer.
176  - In the Arduino world Timer0 is been used for the timer functions, like
177 delay(), millis() and micros().
178  - If you change Timer0 registers, this may influence the Arduino timer
179 function.
180  - So you should know what you are doing.
181 
182  - 16bit timer.
183  - In the Arduino world the Servo library uses Timer1 on Arduino Uno (Timer5
184 on Arduino Mega).
185 
186  Timer2:
187  - 8bit timer like Timer0.
188  - In the Arduino world the tone() function uses Timer2.
189 
190  Timer3 16 bits
191  - 1280/1284P and 2560 only
192 
193  Timer4, Timer5 16 bits
194  - 1280 and 2560 only
195 
196  On Uno
197  - Pins 5 and 6: controlled by timer0
198  - Pins 9 and 10: controlled by timer1
199  - Pins 11 and 3: controlled by timer2
200 
201  On the Arduino Mega we have 6 timers and 15 PWM outputs:
202 
203  TODO pinout below need checkup
204 
205  - Pins 4 and 13: controlled by timer0
206  - Pins 11 and 12: controlled by timer1
207  - Pins 9 and10: controlled by timer2
208  - Pin 2, 3 and 5: controlled by timer 3
209  - Pin 6, 7 and 8: controlled by timer 4
210  - Pin 46, 45 and 44:: controlled by timer 5
211 
212  ... from http://arduino-info.wikispGitte Merete
213 Holm-Pedersenaces.com/Timers-Arduino
214 
215  - Servo Library uses Timer1.
216  -- You can’t use PWM on Pin 9, 10 when you use the Servo Library on an
217 Arduino.
218  -- For Arduino Mega it is a bit more difficult. The timer needed depends on
219 the number of servos.
220  -- Each timer can handle 12 servos.
221  -- For the first 12 servos timer 5 will be used (losing PWM on Pin 44,45,46).
222  -- For 24 Servos timer 5 and 1 will be used (losing PWM on Pin
223 11,12,44,45,46)..
224  -- For 36 servos timer 5, 1 and 3 will be used (losing PWM on Pin
225 2,3,5,11,12,44,45,46)..
226  -- For 48 servos all 16bit timers 5,1,3 and 4 will be used (losing all PWM
227 pins).
228 
229  - Pin 11 has shared functionality PWM and MOSI.
230  -- MOSI is needed for the SPI interface, You can’t use PWM on Pin 11 and the
231 SPI interface at the same time on Arduino.
232  -- On the Arduino Mega the SPI pins are on different pins.
233 
234  - tone() function uses at least timer2.
235  -- You can’t use PWM on Pin 3,11 when you use the tone() function an Arduino
236 and Pin 9,10 on Arduino Mega.
237 
238  SO BEWARE !!!
239 
240  PERFORMANCE
241 
242  std internal speed 1 kHz
243 
244  Rudimentary prog with one task the timer ISR takes about 21 usec
245  Uno, leonardo and mega measures the same
246 
247  period:
248  timer0 1024 usec for 1 msec ...
249  timer1,2,3... 1007 usec for 1 msec
250 
251  >>>>>>>>>>>>
252 
253  MODIFY OF/hardware/arduino/avr/cores/arduino/wiring.c
254 
255  I have added the MOD part (MOD: modification)
256 
257  So if you go for timer0
258  1)remove the // in front of #define MOD
259  2) change here in krnl.h KRNLTMR to 0 for your architecture
260 
261  ONLY SUPPORT FOR AVR's (uno,leonardo,nano,mega,...)
262 
263  //#define MOD
264 
265  MAY WORK OR NOT !!!! BEWARE /Jens
266 
267  #if defined (MOD)
268 
269  void justFakeFctHead()
270  #else
271  #if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) ||
272 defined(__AVR_ATtiny84__) ISR(TIM0_OVF_vect) 769769876987 lalalalalalal #else
273  ISR(TIMER0_OVF_vect)
274  #endif
275 
276  #endif
277  >>>>>>>>>>>>
278 
279 ***********************************************************/
280 
281 
282 // set bit clear bit
283 
284 #ifndef sbi
285 #define sbi(r, b) r |= _BV(b)
286 #endif
287 
288 #ifndef cbi
289 #define cbi(r, b) r &= ~_BV(b)
290 #endif
291 
292 #ifndef rbi
293 #define cbi(r, b) r &= ~_BV(b)
294 #endif
295 
296 // >>>>>>>>>>>>>>>>> USER CONFIGURATION PART <<<<<<<<<<<<<<<<<<
297 
298 // We do use a char forholding prio so ax max interval is 0 -> 127
299 // as Qheads has lowest prio we here have the limit 0-99 for tasks
300 // see below
301 #define QHD_PRIO 102 // Queue head prio - for sentinel use
302 #define ZOMBI_PRIO (QHD_PRIO - 1)
303 #define DMY_PRIO (QHD_PRIO - 2) // dummy task prio (0 == highest prio)
304 
305 // no real dummytask - we do use ya old mmin loop "task""
306 #define DMY_STK_SZ 90 // staksize for dummy
307 
308 #define STAK_HASH 0x5c // just a hashcode
309 #define MAX_SEM_VAL 30000 // NB is also max for nr elem in msgQ !
310 #define MAX_INT 0x7FFF
311 
312 #define CEILINGFAILNOTCEIL -3
313 #define CEILINGFAILPRIO -4
314 
315 /* which timer to use for krnl heartbeat
316  timer 0 ( 8 bit) is normally used by millis - avoid !
317  timer 1 (16 bit)
318  timer 2 ( 8 bit) not 32u4
319  timer 3 (16 bit) 32u4/1280/1284p/2560 only
320  timer 4 (16 bit) 1280/2560 only (MEGA)
321  timer 5 (16 bit) 1280/2560 only (MEGA)
322  */
323 
324 // END USER CONFIGURATION
325 
326 //----------------------------------------------------------
327 
328 #ifdef __cplusplus
329 extern "C" {
330 #endif
331 
332 
333 /***** KeRNeL data types *****/
334 struct k_t {
335 #ifdef BACKSTOPPER
336  void (*pt)(void);
337 #endif
338  unsigned char nr;
339  struct k_t *next, // task,sem: double chain lists ptr
340  *pred; // task,sem: double chain lists ptr
341  volatile char sp_lo, // sem:vacant | task: low 8 byte of stak adr
342  sp_hi; // sem: vacant |task: high 8 byte of stak adr
343  char prio, // task & sem: priority
344  ceiling_prio, // sem
345  saved_prio; // semaohore
346  volatile int cnt1, // sem: sem counter | task: ptr to stak
347  cnt2, // asem: dyn part of time counter | task: timeout
348  cnt3, // sem: preset timer value | task: ptr to Q we are hanging in
349  maxv, // sem: max value | task: org priority
350  clip; // sem: counter for lost signals | task: vacant
351 };
352 
353 extern unsigned char k_coopFlag;
354 
355 struct k_msg_t {
356  // msg type
357  unsigned char nr;
358  struct k_t *sem;
359  char *pBuf; // ptr to user supplied ringbuffer
360  volatile int nr_el, el_size, lost_msg;
361  volatile int r, w, cnt;
362 };
363 
364 #ifdef READERWRITER
365 struct k_rwlock_t {
366  int nrReaders;
367  struct k_t *rdwrSem, *rdSem, *fifoSem;
368 };
369 #endif
370 /***** KeRNeL variables *****/
371 
372 // keep track of k alloc
373 extern int k_task, k_sem, k_msg;
374 extern volatile char krnl_preempt_flag;
375 extern char dmy_stk[DMY_STK_SZ];
376 
377 extern volatile char k_wdt_enabled;
378 
379 // QUEUES
380 extern struct k_t *task_pool, *sem_pool, AQ, // activeQ
381  *pmain_el, *pAQ, *pDmy, // ptr to dummy task descriptor
382  *pRun, // ptr to running task
384 
385 extern struct k_msg_t *send_pool;
386 
387 extern char nr_task, nr_sem, nr_send;
388 
389 extern volatile char k_running; // no running
390 
391 extern volatile char k_err_cnt; // every time an error occurs cnt is incr by one
392 extern unsigned long k_millis_counter;
393 extern char k_preempt_flag;
394 
395 /******************************************************
396  MACROS MACROS
397 
398  PUSHREGS AND POPREGS
399  is actual staklayout plus task address at top
400  A push/pop takes 2 cycles
401  a call takes 3 cycles
402  ret/iret 3-4 cycles
403  So a PUSHREGS is 33 instructions(@ 2 cycles) = 66 cycles ~= 66 cycles /"16
404 MHz" ~= 4.1 usec So an empty iSR which preserves all registers takes 2*4.1usec +
405 8-10 cycles (intr + iret) ~= 9 usec So max isr speed with all regs saved is
406 around 100 kHz but then with no code inside ISR !
407 
408  WARNING
409  The 2560 series has 3 bytes PC the rest only 2 bytes PC !!! (PC. program
410 counter) and no tall has rampz and eind register
411 
412  REGISTER NAMING AND INTERNAL ADRESSING
413 
414 https://en.wikipedia.org/wiki/Atmel_AVR_instruction_set
415 http://www.rjhcoding.com/avr-asm-io.php
416 Register I/O address Data address
417 SREG 0x3F 0x5F
418 SP 0x3E:0x3D 0x5E:0x5D
419 EIND 0x3C 0x5C
420 RAMPZ 0x3B 0x5B
421 RAMPY 0x3A 0x5A
422 RAMPX 0x39 0x59
423 RAMPD 0x38 0x58
424 A typical ATmega memory map may look like:
425 
426 Data address I/O address Contents
427 0x0000 – 0x001F Registers R0 – R31
428 
429 general purpose regs
430 r0 mem addr
431 ...
432 0 0 0x0000
433 1 1 0x0001
434 2 2
435 3 3
436 4 4
437 5 5
438 6 6
439 7 7
440 8 8
441 9 9
442 a 10
443 b 11
444 c 12
445 d 13
446 e 14
447 f 15
448 10 16
449 11 17
450 12 18
451 13 19
452 14 20
453 15 21
454 16 22
455 17 23
456 18 24
457 19 25
458 1a 26 Xref L
459 1b 27 Xreg H
460 1c 28 Yreg L
461 1d 29 Yreg H
462 1e 30 Zreg L
463 1f 31 Zreg H 0x001F
464 
465 0x0020 – 0x003F 0x00 – 0x1F I/O registers (bit-addressable)
466 0x0040 – 0x005F 0x20 – 0x3F I/O registers (not bit-addressable)
467 0x0060 – 0x00FF Extended I/O registers (memory-mapped I/O only)
468 0x0100 – RAMEND Internal SRAM
469 
470  Register addresses
471  IO adr data addr
472  0x3f SREG 0x5f
473  0x3e SPH
474  0x3d SPL
475  0x3c EIND 0x5c 1280/2560 only
476  0x3b RAMPZ 0x5b 1280/2560/1284p only
477  ...
478  0x1f R31
479  etc
480  0x01 R1
481  0x00 R0
482 
483  PC is NOT available
484  */
485 
486 #define lo8(X) ((unsigned char)((unsigned int)(X)))
487 #define hi8(X) ((unsigned char)((unsigned int)(X) >> 8))
488 
489 #define DI() __asm__ volatile("cli")
490 #define EI() __asm__ volatile("sei")
491 #define RETI() __asm__ volatile("reti")
492 
493 extern volatile char k_bug_on;
494 
495 // IF KRLBUG IS DEFINED THEN breakout is called for every time a taskshift appears
496 // IF KRLBUG IS DEFINED THEN breakout is called for every time a taskshift appears
497 
498 #ifdef KRNLBUG
499 #define K_CHG_STAK() \
500  \
501  if (pRun != AQ.next) { \
502  pRun->sp_lo = SPL; \
503  pRun->sp_hi = SPH; \
504  pRun = AQ.next; \
505  k_breakout(); \
506  SPL = pRun->sp_lo; \
507  SPH = pRun->sp_hi; \
508  }
509 
510 #else
511 #define K_CHG_STAK() \
512  if (pRun != AQ.next) { \
513  pRun->sp_lo = SPL; \
514  pRun->sp_hi = SPH; \
515  pRun = AQ.next; \
516  SPL = pRun->sp_lo; \
517  SPH = pRun->sp_hi; \
518  }
519 
520 #endif
521 
522 
523 
524 /* below: r1 must/shall always assumed to be zero in c code (gcc issue I think)
525 */
526 
527 // AVR / ARDUINO PART PUSH POP
528 // 0x3b RAMPZ extended z-pointer register
529 // 0x3c EIND extended indirect register
530 
531 
532 /* below: r1 must/shall always assumed to be zero in c code (gcc issue I think)
533  */
534 
535 #if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) || \
536  defined(__AVR_ATmega2561__)
537 
538 // 0x3b RAMPZ extended z-pointer register
539 // 0x3c EIND extended indirect register
540 
541 #define PUSHREGS() \
542  __asm__ volatile("push r1 \n\t" \
543  "push r0 \n\t" \
544  "in r0, __SREG__ \n\t" \
545  "cli \n\t" \
546  "push r0 \n\t" \
547  "in r0 , 0x3b \n\t" \
548  "push r0 \n\t" \
549  "in r0 , 0x3c \n\t" \
550  "push r0 \n\t" \
551  "clr r1 \n\t" \
552  "push r2 \n\t" \
553  "push r3 \n\t" \
554  "push r4 \n\t" \
555  "push r5 \n\t" \
556  "push r6 \n\t" \
557  "push r7 \n\t" \
558  "push r8 \n\t" \
559  "push r9 \n\t" \
560  "push r10 \n\t" \
561  "push r11 \n\t" \
562  "push r12 \n\t" \
563  "push r13 \n\t" \
564  "push r14 \n\t" \
565  "push r15 \n\t" \
566  "push r16 \n\t" \
567  "push r17 \n\t" \
568  "push r18 \n\t" \
569  "push r19 \n\t" \
570  "push r20 \n\t" \
571  "push r21 \n\t" \
572  "push r22 \n\t" \
573  "push r23 \n\t" \
574  "push r24 \n\t" \
575  "push r25 \n\t" \
576  "push r26 \n\t" \
577  "push r27 \n\t" \
578  "push r28 \n\t" \
579  "push r29 \n\t" \
580  "push r30 \n\t" \
581  "push r31 \n\t")
582 
583 #define POPREGS() \
584  __asm__ volatile("pop r31 \n\t" \
585  "pop r30 \n\t" \
586  "pop r29 \n\t" \
587  "pop r28 \n\t" \
588  "pop r27 \n\t" \
589  "pop r26 \n\t" \
590  "pop r25 \n\t" \
591  "pop r24 \n\t" \
592  "pop r23 \n\t" \
593  "pop r22 \n\t" \
594  "pop r21 \n\t" \
595  "pop r20 \n\t" \
596  "pop r19 \n\t" \
597  "pop r18 \n\t" \
598  "pop r17 \n\t" \
599  "pop r16 \n\t" \
600  "pop r15 \n\t" \
601  "pop r14 \n\t" \
602  "pop r13 \n\t" \
603  "pop r12 \n\t" \
604  "pop r11 \n\t" \
605  "pop r10 \n\t" \
606  "pop r9 \n\t" \
607  "pop r8 \n\t" \
608  "pop r7 \n\t" \
609  "pop r6 \n\t" \
610  "pop r5 \n\t" \
611  "pop r4 \n\t" \
612  "pop r3 \n\t" \
613  "pop r2 \n\t" \
614  "pop r0 \n\t" \
615  "out 0x3c , r0 \n\t " \
616  "pop r0 \n\t" \
617  "out 0x3b , r0 \n\t " \
618  "pop r0 \n\t" \
619  "out __SREG__ , r0 \n\t " \
620  "pop r0 \n\t" \
621  "pop r1 \n\t")
622 
623 #elif defined(__AVR_ATmega1284P__)
624 
625 // 0x3b RAMPZ extended z-pointer register
626 // 0x3c EIND extended indirect register
627 
628 #define PUSHREGS() \
629  __asm__ volatile("push r1 \n\t" \
630  "push r0 \n\t" \
631  "in r0, __SREG__ \n\t" \
632  "cli \n\t" \
633  "push r0 \n\t" \
634  "in r0 , 0x3b \n\t" \
635  "push r0 \n\t" \
636  "clr r1 \n\t" \
637  "push r2 \n\t" \
638  "push r3 \n\t" \
639  "push r4 \n\t" \
640  "push r5 \n\t" \
641  "push r6 \n\t" \
642  "push r7 \n\t" \
643  "push r8 \n\t" \
644  "push r9 \n\t" \
645  "push r10 \n\t" \
646  "push r11 \n\t" \
647  "push r12 \n\t" \
648  "push r13 \n\t" \
649  "push r14 \n\t" \
650  "push r15 \n\t" \
651  "push r16 \n\t" \
652  "push r17 \n\t" \
653  "push r18 \n\t" \
654  "push r19 \n\t" \
655  "push r20 \n\t" \
656  "push r21 \n\t" \
657  "push r22 \n\t" \
658  "push r23 \n\t" \
659  "push r24 \n\t" \
660  "push r25 \n\t" \
661  "push r26 \n\t" \
662  "push r27 \n\t" \
663  "push r28 \n\t" \
664  "push r29 \n\t" \
665  "push r30 \n\t" \
666  "push r31 \n\t")
667 
668 #define POPREGS() \
669  __asm__ volatile("pop r31 \n\t" \
670  "pop r30 \n\t" \
671  "pop r29 \n\t" \
672  "pop r28 \n\t" \
673  "pop r27 \n\t" \
674  "pop r26 \n\t" \
675  "pop r25 \n\t" \
676  "pop r24 \n\t" \
677  "pop r23 \n\t" \
678  "pop r22 \n\t" \
679  "pop r21 \n\t" \
680  "pop r20 \n\t" \
681  "pop r19 \n\t" \
682  "pop r18 \n\t" \
683  "pop r17 \n\t" \
684  "pop r16 \n\t" \
685  "pop r15 \n\t" \
686  "pop r14 \n\t" \
687  "pop r13 \n\t" \
688  "pop r12 \n\t" \
689  "pop r11 \n\t" \
690  "pop r10 \n\t" \
691  "pop r9 \n\t" \
692  "pop r8 \n\t" \
693  "pop r7 \n\t" \
694  "pop r6 \n\t" \
695  "pop r5 \n\t" \
696  "pop r4 \n\t" \
697  "pop r3 \n\t" \
698  "pop r2 \n\t" \
699  "pop r0 \n\t" \
700  "out 0x3b , r0 \n\t " \
701  "pop r0 \n\t" \
702  "out __SREG__ , r0 \n\t " \
703  "pop r0 \n\t" \
704  "pop r1 \n\t")
705 
706 #elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) \
707  || defined(__AVR_ATmega328__) || defined(__AVR_ATmega32U4__)
708 
709 #define PUSHREGS() \
710  __asm__ volatile("push r1 \n\t" \
711  "push r0 \n\t" \
712  "in r0, __SREG__ \n\t" \
713  "cli \n\t" \
714  "push r0 \n\t" \
715  "clr r1 \n\t" \
716  "push r2 \n\t" \
717  "push r3 \n\t" \
718  "push r4 \n\t" \
719  "push r5 \n\t" \
720  "push r6 \n\t" \
721  "push r7 \n\t" \
722  "push r8 \n\t" \
723  "push r9 \n\t" \
724  "push r10 \n\t" \
725  "push r11 \n\t" \
726  "push r12 \n\t" \
727  "push r13 \n\t" \
728  "push r14 \n\t" \
729  "push r15 \n\t" \
730  "push r16 \n\t" \
731  "push r17 \n\t" \
732  "push r18 \n\t" \
733  "push r19 \n\t" \
734  "push r20 \n\t" \
735  "push r21 \n\t" \
736  "push r22 \n\t" \
737  "push r23 \n\t" \
738  "push r24 \n\t" \
739  "push r25 \n\t" \
740  "push r26 \n\t" \
741  "push r27 \n\t" \
742  "push r28 \n\t" \
743  "push r29 \n\t" \
744  "push r30 \n\t" \
745  "push r31 \n\t")
746 
747 #define POPREGS() \
748  __asm__ volatile("pop r31 \n\t" \
749  "pop r30 \n\t" \
750  "pop r29 \n\t" \
751  "pop r28 \n\t" \
752  "pop r27 \n\t" \
753  "pop r26 \n\t" \
754  "pop r25 \n\t" \
755  "pop r24 \n\t" \
756  "pop r23 \n\t" \
757  "pop r22 \n\t" \
758  "pop r21 \n\t" \
759  "pop r20 \n\t" \
760  "pop r19 \n\t" \
761  "pop r18 \n\t" \
762  "pop r17 \n\t" \
763  "pop r16 \n\t" \
764  "pop r15 \n\t" \
765  "pop r14 \n\t" \
766  "pop r13 \n\t" \
767  "pop r12 \n\t" \
768  "pop r11 \n\t" \
769  "pop r10 \n\t" \
770  "pop r9 \n\t" \
771  "pop r8 \n\t" \
772  "pop r7 \n\t" \
773  "pop r6 \n\t" \
774  "pop r5 \n\t" \
775  "pop r4 \n\t" \
776  "pop r3 \n\t" \
777  "pop r2 \n\t" \
778  "pop r0 \n\t" \
779  "out __SREG__ , r0 \n\t " \
780  "pop r0 \n\t" \
781  "pop r1 \n\t")
782 
783 #else
784 #error "unknown arch"
785 #endif
786 
787 
788 // function prototypes
789 // naming convention
790 // k_... function do a DI/EI and can impose task shift
791 // ki_... expects interrupt to be disablet and do no task shift
792 // rest is internal functions
793 
794 #ifdef DYNMEMORY
795 
800 void *k_malloc(int k);
801 
808 void k_free(void *m);
809 #endif
810 
821 void __attribute__((weak)) k_wdt_enable(int t);
822 
827 void __attribute__((weak)) k_wdt_disable();
828 
836 unsigned long ki_millis(void);
837 
843 int k_ticksize(void);
844 
852 unsigned long k_millis(void);
853 
860 void k_eat_msec(unsigned int eatTime);
861 
866 void ki_task_shift(void) __attribute__((naked));
867 
875 int k_sleep(int time);
876 
885 struct k_t *k_crt_task(void (*pTask)(void), char prio, char *pS, int stkSize);
886 
894 int k_set_prio(char prio);
895 
904 struct k_t *k_crt_sem(int init_val, int maxvalue);
905 
924 struct k_t *k_crt_mut(char ceiling_prio, int init_val, int maxvalue);
925 
926 int k_mut_ceil_set(struct k_t *sem, char prio);
927 
936 int k_mut_ceil_enter(struct k_t *sem, int timeout);
937 
944 int k_mut_ceil_leave(struct k_t *sem);
945 
956 int k_mut_ceil(struct k_t *sem, int timeout, void (*fct)(void));
957 
967 int k_set_sem_timer(struct k_t *sem, int val);
968 
976 int ki_signal(struct k_t *sem);
977 
987 int k_signal(struct k_t *sem);
988 
1000 int k_wait(struct k_t *sem, int timeout);
1001 
1015 int k_wait2(struct k_t *sem, int timeout, int *nrClip);
1016 
1023 int k_sem_signals_lost(struct k_t *sem);
1024 
1035 int ki_wait(struct k_t *sem, int timeout);
1036 
1045 int ki_semval(struct k_t *sem);
1046 
1054 int k_semval(struct k_t *sem);
1055 
1063 int k_clear_sem(struct k_t *sem);
1064 
1070 int ki_msg_count(struct k_msg_t *msgbuffer);
1071 
1079 int k_msg_count(struct k_msg_t *m);
1080 
1081 /*********************************************************************
1082 ************************* DEBUG BREAKOUT FUNCTIONS *******************
1083 **********************************************************************
1084 *
1085 * Breakout functions can be removed by commenting out define of
1086 * KRNLBUG in krnl.h (located around line 216)
1087 
1088 * All semaphore calls k_sem_clip, k_sem_signal, k_Sem_wait are all called
1089 * AFTER decrement/incr of semaphore has taken place BUT before eventually
1090 * taskshift.
1091 *
1092 * For message buffers/semaphores an internal semaphore is used for
1093 synchronization
1094 * so referring to the msgQ is by
1095 * struct k_msg_t *msgSem; msgSem->sem->nr
1096 *
1097 */
1098 
1109 #ifdef KRNLBUG
1110 void __attribute__((weak)) k_sem_clip(unsigned char nr, int nrClip);
1111 #endif
1112 
1119 #ifdef KRNLBUG
1120 void __attribute__((weak)) k_sem_signal(unsigned char nr, int val);
1121 #endif
1122 
1128 #ifdef KRNLBUG
1129 void __attribute__((weak)) k_sem_wait(unsigned char nr, int val);
1130 #endif
1131 
1141 #ifdef KRNLBUG
1142 void __attribute__((weak)) k_send_Q_clip(unsigned char nr, int nrClip);
1143 #endif
1144 
1145 struct k_msg_t *k_crt_send_Q(int nr_el, int el_size, void *pBuf);
1146 
1159 char ki_send(struct k_msg_t *pB, void *el);
1160 
1171 char k_send(struct k_msg_t *pB, void *el);
1172 
1186 char k_receive(struct k_msg_t *pB, void *el, int timeout, int *lost_msg);
1187 
1204 char ki_receive(struct k_msg_t *pB, void *el, int *lost_msg);
1205 
1213 int ki_clear_msg_Q(struct k_msg_t *pB);
1214 
1219 int k_clear_msg_Q(struct k_msg_t *pB);
1220 
1221 #ifdef READERWRITER
1225 void k_rwInit(struct k_rwlock_t *lock);
1226 
1230 int k_rwRdEnter(struct k_rwlock_t *lock, int timeout);
1231 
1235 int k_rwWrEnter(struct k_rwlock_t *lock, int timeout);
1236 
1240 int k_rwRdLeave(struct k_rwlock_t *lock);
1241 
1245 int k_rwWrLeave(struct k_rwlock_t *lock);
1246 
1247 #endif
1248 
1253 int k_tmrInfo(void); // tm in milliseconds
1254 
1263 int k_init(int nrTask, int nrSem, int nrMsg);
1264 
1274 int k_start(void); // tm in milliseconds
1275 
1283 int k_stop(); // tm in milliseconds
1284 
1289 void k_reset();
1290 
1306 int k_stk_chk(struct k_t *t);
1307 
1315 int ki_unused_stak(struct k_t *t);
1316 
1323 int k_unused_stak(struct k_t *t);
1324 
1331 int ki_my_unused_stak();
1332 
1338 void k_round_robbin(void);
1339 
1346 void k_release(void);
1347 
1350 void k_set_coop_multitask(unsigned char onn);
1351 
1356 int freeRam(void);
1357 
1358 #ifdef KRNLBUG
1359 
1373 void __attribute__((weak)) k_breakout(void);
1374 #endif
1375 
1376 #ifdef __cplusplus
1377 }
1378 #endif
1379 #endif // #ifndef KRNL
struct k_t * pTask
Definition: k00hacksPWM.ino:4
void k_breakout()
Definition: k02twotasks.ino:93
void k_sem_clip(unsigned char nr, int nrClip)
unsigned long k_millis(void)
Definition: krnl.c:1322
int k_signal(struct k_t *sem)
Definition: krnl.c:681
#define DMY_STK_SZ
Definition: krnl.h:306
int k_msg
Definition: krnl.h:373
void k_reset()
unsigned long ki_millis(void)
Definition: krnl.c:1315
void k_eat_msec(unsigned int eatTime)
Definition: krnl.c:292
volatile char k_bug_on
volatile char krnl_preempt_flag
void k_free(void *m)
int k_stk_chk(struct k_t *t)
int ki_semval(struct k_t *sem)
Definition: krnl.c:846
char nr_send
Definition: krnl.h:387
struct k_t * pRun
Definition: krnl.h:382
int k_sem
Definition: krnl.h:373
int k_msg_count(struct k_msg_t *m)
Definition: krnl.c:878
char dmy_stk[DMY_STK_SZ]
struct k_t * pAQ
Definition: krnl.h:381
volatile char k_wdt_enabled
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
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
int k_sleep(int time)
Definition: krnl.c:491
void * k_malloc(int k)
volatile char k_running
Definition: krnl.c:208
int k_task
Definition: krnl.c:205
int k_start(void)
Definition: krnl.c:1192
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
struct k_t * pSleepSem
Definition: krnl.h:383
int k_semval(struct k_t *sem)
Definition: krnl.c:852
void __attribute__((weak)) k_wdt_enable(int t)
struct k_t * sem_pool
Definition: krnl.h:380
int k_set_prio(char prio)
Definition: krnl.c:548
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
struct k_t * pmain_el
Definition: krnl.h:381
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.h:387
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
void ki_task_shift(void) __attribute__((naked))
int k_stop()
Definition: krnl.c:1292
void k_round_robbin(void)
Definition: krnl.c:1118
struct k_t * k_crt_task(void(*pTask)(void), char prio, char *pS, int stkSize)
Definition: krnl.c:374
int ki_msg_count(struct k_msg_t *msgbuffer)
Definition: krnl.c:873
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 int val
Definition: krnl.h:1120
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
struct k_t * pDmy
Definition: krnl.h:381
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
struct k_t AQ
Definition: krnl.h:380
volatile char k_err_cnt
Definition: krnl.c:208
void int nrClip
Definition: krnl.h:1110
char k_preempt_flag
unsigned char k_coopFlag
Definition: krnl.c:218
struct k_t * task_pool
Definition: krnl.c:195
int ki_wait(struct k_t *sem, int timeout)
Definition: krnl.c:698
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
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