krnl 1
Loading...
Searching...
No Matches
krnl.h
Go to the documentation of this file.
1
2#define KRNL_VRS 20250606
3/*******************************************************
4 ***** *
5 * *
6 * | |/ /___| _ \| \ | | ___| | *
7 * | ' // _ \ |_) | \| |/ _ \ | *
8 * | . \ __/ _ <| |\ | __/ |___ *
9 * |_|\_\___|_| \_\_| \_|\___|_____| *
10 * *
11 * *
12 * you are watching krnl.c *
13 * *
14 * March 2015,2016,..,2018 *
15 * Author: jdn *
16 * final sep 2022 *
17 * *
18 * this version adapted for Arduino
19 *
20 * (C) 2012,2013,2014
21 * 2017,2018,2019,2021,2022,2023
22 *
23 *
24 * IF YOU ARE LUCKY LOOK HERE
25 *
26 * https://github.com/jdn-aau/krnl
27 *
28 *
29 *
30 * Jens Dalsgaard Nielsen <jdn@es.aau.dk>
31 * http://es.aau.dk/staff/jdn
32 * Section of Automation & Control
33 * Aalborg University,
34 * Denmark
35 *
36 * "THE BEER-WARE LICENSE" (frit efter PHK)
37 * <jdn@es.aau.dk> wrote this file. As long as you
38 * retain this notice you can do whatever you want
39 * with this stuff. If we meet some day, and you think
40 * this stuff is worth it ...
41 * you can buy me a beer in return :-)
42 * or if you are real happy then ...
43 * single malt will be well received :-)
44 *
45 * Use it at your own risk - no warranty
46 *
47 * nice info...
48 * http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_cplusplus
49 * at 20090611
50 * - k_eat_time now eats time in quants of krnl tick speed but not one quant
51 *boundary
52 * - added k_malloc and k_free
53 * k_free dont free memory bq we do not want fragmentation
54 * so DONT USE k_free. I do NOT free memory
55 * - k_malloc and k_free are weak functions so you can just add your own
56 *versions
57 * - watchdog is enabled (2sec and reset in krnl timer) in weak function
58 *k_enable_wdt
59 *
60 * remember to update in krnl.c !!!
61 *****************************************************/
62
63#ifndef KRNL
64#define KRNL
65
66// IMPORTANT DEFINES !!!!
67// IMPORTANT DEFINES !!!!
68// IMPORTANT DEFINES !!!!
69// IMPORTANT DEFINES !!!!
70// IMPORTANT DEFINES !!!!
71
72#define KRNLBUG // KRNLBUG ACTIVATE BREAK OUT FUNCTIONS
73
74// BACKSTOPPER wraps a looping fct around your task so it will just restart
75// like loop function
76// BEWARE bq local variables in the task body just evaporate - as always
77#define BACKSTOPPER
78
79// if you want to use k_malloc
80// NB k_free wont release mem due to possible fragmentation
81// SO DONT USE k_free its just a fake
82// NEVER !!! free men in a rt system...
83// and please do all malloc before starting running
84
85#define DYNMEMORY
86
87// DON NOT CHANGE K_TICK - must be 1 millisec
88#define K_TICK 1
89
90// if defined you will stop in backstopper, else you will jump back to task s
91// see comments about local vars above
92//#define STOP_IN_BACKSTOPPER
93
94//#define WDT_TIMER // uncomment to activate
95#define WDT_PERIOD WDTO_1S
96
97
98// IF YOU WANT READER WRITER LOCK THEN DEFINE
99// experimental - no guarantee
100//https://www.geeksforgeeks.org/readers-writers-problem-writers-preference-solution/?ref=rp
101//https://www.geeksforgeeks.org/readers-writers-problem-set-1-introduction-and-readers-preference-solution/
102// https://www.tutorialspoint.com/readers-writers-problem
103
104//#define READERWRITER
105
106// Define watchdog timer and period
107// if you enable it it will be running at once
108
109// END IMPORTANT DEFINES
110// END IMPORTANT DEFINES
111// END IMPORTANT DEFINES
112// END IMPORTANT DEFINES
113// END IMPORTANT DEFINES
114// END IMPORTANT DEFINES
115
116
117
118// SELECTION OF HW TIMER TO BE USED FOR krnl tick
119// SELECTION OF HW TIMER TO BE USED FOR krnl tick
120// SELECTION OF HW TIMER TO BE USED FOR krnl tick
121
122// Reverted to use only timer 2
123//HAS IMPACT ON PWM !!!! SEE BELOW !!!
124/*
125#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) \
126 || defined(__AVR_ATmega2561__) || defined(__AVR_ATmega1284P__)\
127 || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__)\
128 || defined(__AVR_ATmega328__)
129#define KRNLTMR 2
130
131#elif defined(__AVR_ATmega32U4__)
132//#define KRNLTMR 3
133#error "32u4 hmm AVR cpu type - bad place to come"
134#else
135#error "unknown AVR cpu type - bad place to come"
136#endif
137*/
138/***********************
139
140 NB NB ABOUT WRAP AROUND
141
142 Krnl maintain a milisecond timer (k_millis_counter)
143 It s 32 bit unsigned long so it wraps around after 49.7 days.
144 As all timing internal in krnl is relative (from now) then
145 wrap around will have no influence on krnl !!!fk_eat
146
147 NB NB ABOUT TIMERS PORTS ETC
148
149 You can configure krnl to use timer 1,2,3,4,5
150
151 If you want to use timer 0 then you need to
152
153 - set KRNLTMR = 0 just below in USER CONFIGURATION PART
154 - mangle with Arduino library code in ...
155 hardware/arduino/avr/cores/arduino/wiring.c
156 rename ISR ... with function head:
157 #if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) ||
158defined(__AVR_ATtiny84__) ISR(TIM0_OVF_vect) #else ISR(TIMER0_OVF_vect) #endif
159 to something else : mayby void kurt()
160
161 This is because krnl install an ISR on timer0 and there cant be two
162 Krnl to maintain the millis counters so everything with millis, micros etc is
163as usual.
164
165 Buth normally you cant use timer 0 bq it is used for millis and preallocated.
166
167 See below
168
169 When using a timer you must be aware of that it will prohibit you from things
170like
171 - tone (pwm sound) uses timer2
172
173 ... from http://blog.oscarliang.net/arduino-timer-and-interrupt-tutorial/
174
175 Timer0:
176 - 8bit timer.
177 - In the Arduino world Timer0 is been used for the timer functions, like
178delay(), millis() and micros().
179 - If you change Timer0 registers, this may influence the Arduino timer
180function.
181 - So you should know what you are doing.
182
183 - 16bit timer.
184 - In the Arduino world the Servo library uses Timer1 on Arduino Uno (Timer5
185on Arduino Mega).
186
187 Timer2:
188 - 8bit timer like Timer0.
189 - In the Arduino world the tone() function uses Timer2.
190
191 Timer3 16 bits
192 - 1280/1284P and 2560 only
193
194 Timer4, Timer5 16 bits
195 - 1280 and 2560 only
196
197 On Uno
198 - Pins 5 and 6: controlled by timer0
199 - Pins 9 and 10: controlled by timer1
200 - Pins 11 and 3: controlled by timer2
201
202 On the Arduino Mega we have 6 timers and 15 PWM outputs:
203
204 TODO pinout below need checkup
205
206 - Pins 4 and 13: controlled by timer0
207 - Pins 11 and 12: controlled by timer1
208 - Pins 9 and10: controlled by timer2
209 - Pin 2, 3 and 5: controlled by timer 3
210 - Pin 6, 7 and 8: controlled by timer 4
211 - Pin 46, 45 and 44:: controlled by timer 5
212
213 ... from http://arduino-info.wikispGitte Merete
214Holm-Pedersenaces.com/Timers-Arduino
215
216 - Servo Library uses Timer1.
217 -- You can’t use PWM on Pin 9, 10 when you use the Servo Library on an
218Arduino.
219 -- For Arduino Mega it is a bit more difficult. The timer needed depends on
220the number of servos.
221 -- Each timer can handle 12 servos.
222 -- For the first 12 servos timer 5 will be used (losing PWM on Pin 44,45,46).
223 -- For 24 Servos timer 5 and 1 will be used (losing PWM on Pin
22411,12,44,45,46)..
225 -- For 36 servos timer 5, 1 and 3 will be used (losing PWM on Pin
2262,3,5,11,12,44,45,46)..
227 -- For 48 servos all 16bit timers 5,1,3 and 4 will be used (losing all PWM
228pins).
229
230 - Pin 11 has shared functionality PWM and MOSI.
231 -- MOSI is needed for the SPI interface, You can’t use PWM on Pin 11 and the
232SPI interface at the same time on Arduino.
233 -- On the Arduino Mega the SPI pins are on different pins.
234
235 - tone() function uses at least timer2.
236 -- You can’t use PWM on Pin 3,11 when you use the tone() function an Arduino
237and Pin 9,10 on Arduino Mega.
238
239 SO BEWARE !!!
240
241 PERFORMANCE
242
243 std internal speed 1 kHz
244
245 Rudimentary prog with one task the timer ISR takes about 21 usec
246 Uno, leonardo and mega measures the same
247
248 period:
249 timer0 1024 usec for 1 msec ...
250 timer1,2,3... 1007 usec for 1 msec
251
252 >>>>>>>>>>>>
253
254 MODIFY OF/hardware/arduino/avr/cores/arduino/wiring.c
255
256 I have added the MOD part (MOD: modification)
257
258 So if you go for timer0
259 1)remove the // in front of #define MOD
260 2) change here in krnl.h KRNLTMR to 0 for your architecture
261
262 ONLY SUPPORT FOR AVR's (uno,leonardo,nano,mega,...)
263
264 //#define MOD
265
266 MAY WORK OR NOT !!!! BEWARE /Jens
267
268 #if defined (MOD)
269
270 void justFakeFctHead()
271 #else
272 #if defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) ||
273defined(__AVR_ATtiny84__) ISR(TIM0_OVF_vect) 769769876987 lalalalalalal #else
274 ISR(TIMER0_OVF_vect)
275 #endif
276
277 #endif
278 >>>>>>>>>>>>
279
280***********************************************************/
281
282
283// >>>>>>>>>>>>>>>>> USER CONFIGURATION PART <<<<<<<<<<<<<<<<<<
284
285
286
287// We do use a char forholding prio so ax max interval is 0 -> 127
288// as Qheads has lowest prio we here have the limit 0-99 for tasks
289// see below
290#define QHD_PRIO 102 // Queue head prio - for sentinel use
291#define ZOMBI_PRIO (QHD_PRIO - 1)
292#define DMY_PRIO (QHD_PRIO - 2) // dummy task prio (0 == highest prio)
293
294// no real dummytask - we do use ya old mmin loop "task""
295#define DMY_STK_SZ 90 // staksize for dummy
296
297#define STAK_HASH 0x5c // just a hashcode
298#define MAX_SEM_VAL 30000 // NB is also max for nr elem in msgQ !
299#define MAX_INT 0x7FFF
300
301#define CEILINGFAILNOTCEIL -3
302#define CEILINGFAILPRIO -4
303
304/* which timer to use for krnl heartbeat
305 timer 0 ( 8 bit) is normally used by millis - avoid !
306 timer 1 (16 bit)
307 timer 2 ( 8 bit) not impl on 32u4
308 timer 3 (16 bit) 32u4/1280/1284p/2560 only
309 timer 4 (16 bit) 1280/2560 only (MEGA)
310 timer 5 (16 bit) 1280/2560 only (MEGA)
311 */
312
313// END USER CONFIGURATION
314
315//----------------------------------------------------------
316
317#ifdef __cplusplus
318extern "C" {
319#endif
320
321
322/***** KeRNeL data types *****/
323struct k_t {
324#ifdef BACKSTOPPER
325 void (*pt)(void);
326#endif
327 unsigned char nr;
328 struct k_t *next, // task,sem: double chain lists ptr
329 *pred; // task,sem: double chain lists ptr
330 volatile char sp_lo, // sem:vacant | task: low 8 byte of stak adr
331 sp_hi; // sem: vacant |task: high 8 byte of stak adr
332 char prio, // task & sem: priority
334 saved_prio; // semaohore
335 volatile int cnt1, // sem: sem counter | task: ptr to stak
336 cnt2, // asem: dyn part of time counter | task: timeout
337 cnt3, // sem: preset timer value | task: ptr to Q we are hanging in
338 maxv, // sem: max value | task: org priority
339 clip; // sem: counter for lost signals | task: vacant
340};
341
342extern unsigned char k_coopFlag;
343
344struct k_msg_t {
345 // msg type
346 unsigned char nr;
347 struct k_t *sem;
348 char *pBuf; // ptr to user supplied ringbuffer
349 volatile int nr_el, el_size, lost_msg;
350 volatile int r, w, cnt;
351};
352
353#ifdef READERWRITER
354struct k_rwlock_t {
355 int nrReaders;
356 struct k_t *rdwrSem, *rdSem, *fifoSem;
357};
358#endif
359/***** KeRNeL variables *****/
360
361// keep track of k alloc
362extern int k_task, k_sem, k_msg;
363extern volatile char krnl_preempt_flag;
364extern char dmy_stk[DMY_STK_SZ];
365
366extern volatile char k_wdt_enabled;
367
368// QUEUES
369extern struct k_t *task_pool, *sem_pool, AQ, // activeQ
370 *pmain_el, *pAQ, *pDmy, // ptr to dummy task descriptor
371 *pRun, // ptr to running task
373
374extern struct k_msg_t *send_pool;
375
376extern char nr_task, nr_sem, nr_send;
377
378extern volatile char k_running; // no running
379
380extern volatile char k_err_cnt; // every time an error occurs cnt is incr by one
381extern unsigned long k_millis_counter;
382extern char k_preempt_flag;
383
384/******************************************************
385 MACROS MACROS
386
387 PUSHREGS AND POPREGS
388 is actual staklayout plus task address at top
389 A push/pop takes 2 cycles
390 a call takes 3 cycles
391 ret/iret 3-4 cycles
392 So a PUSHREGS is 33 instructions(@ 2 cycles) = 66 cycles ~= 66 cycles /"16
393MHz" ~= 4.1 usec So an empty iSR which preserves all registers takes 2*4.1usec +
3948-10 cycles (intr + iret) ~= 9 usec So max isr speed with all regs saved is
395around 100 kHz but then with no code inside ISR !
396
397 WARNING
398 The 2560 series has 3 bytes PC the rest only 2 bytes PC !!! (PC. program
399counter) and no tall has rampz and eind register
400
401 REGISTER NAMING AND INTERNAL ADRESSING
402
403https://en.wikipedia.org/wiki/Atmel_AVR_instruction_set
404http://www.rjhcoding.com/avr-asm-io.php
405Register I/O address Data address
406SREG 0x3F 0x5F
407SP 0x3E:0x3D 0x5E:0x5D
408EIND 0x3C 0x5C
409RAMPZ 0x3B 0x5B
410RAMPY 0x3A 0x5A
411RAMPX 0x39 0x59
412RAMPD 0x38 0x58
413A typical ATmega memory map may look like:
414
415Data address I/O address Contents
4160x0000 – 0x001F Registers R0 – R31
417
418general purpose regs
419r0 mem addr
420...
4210 0 0x0000
4221 1 0x0001
4232 2
4243 3
4254 4
4265 5
4276 6
4287 7
4298 8
4309 9
431a 10
432b 11
433c 12
434d 13
435e 14
436f 15
43710 16
43811 17
43912 18
44013 19
44114 20
44215 21
44316 22
44417 23
44518 24
44619 25
4471a 26 Xref L
4481b 27 Xreg H
4491c 28 Yreg L
4501d 29 Yreg H
4511e 30 Zreg L
4521f 31 Zreg H 0x001F
453
4540x0020 – 0x003F 0x00 – 0x1F I/O registers (bit-addressable)
4550x0040 – 0x005F 0x20 – 0x3F I/O registers (not bit-addressable)
4560x0060 – 0x00FF Extended I/O registers (memory-mapped I/O only)
4570x0100 – RAMEND Internal SRAM
458
459 Register addresses
460 IO adr data addr
461 0x3f SREG 0x5f
462 0x3e SPH
463 0x3d SPL
464 0x3c EIND 0x5c 1280/2560 only
465 0x3b RAMPZ 0x5b 1280/2560/1284p only
466 ...
467 0x1f R31
468 etc
469 0x01 R1
470 0x00 R0
471
472 PC is NOT available
473 */
474
475#define lo8(X) ((unsigned char)((unsigned int)(X)))
476#define hi8(X) ((unsigned char)((unsigned int)(X) >> 8))
477
478#define DI() __asm__ volatile("cli")
479#define EI() __asm__ volatile("sei")
480#define RETI() __asm__ volatile("reti")
481
482extern volatile char k_bug_on;
483
484// IF KRLBUG IS DEFINED THEN breakout is called for every time a taskshift appears
485// IF KRLBUG IS DEFINED THEN breakout is called for every time a taskshift appears
486
487#ifdef KRNLBUG
488#define K_CHG_STAK() \
489 \
490 if (pRun != AQ.next) { \
491 pRun->sp_lo = SPL; \
492 pRun->sp_hi = SPH; \
493 pRun = AQ.next; \
494 k_breakout(); \
495 SPL = pRun->sp_lo; \
496 SPH = pRun->sp_hi; \
497 }
498
499#else
500#define K_CHG_STAK() \
501 if (pRun != AQ.next) { \
502 pRun->sp_lo = SPL; \
503 pRun->sp_hi = SPH; \
504 pRun = AQ.next; \
505 SPL = pRun->sp_lo; \
506 SPH = pRun->sp_hi; \
507 }
508
509#endif
510
511
512
513/* below: r1 must/shall always assumed to be zero in c code (gcc issue I think)
514*/
515
516// AVR / ARDUINO PART PUSH POP
517// 0x3b RAMPZ extended z-pointer register
518// 0x3c EIND extended indirect register
519
520
521/* below: r1 must/shall always assumed to be zero in c code (gcc issue I think)
522 */
523
524#if defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1280__) || \
525 defined(__AVR_ATmega2561__)
526
527// 0x3b RAMPZ extended z-pointer register
528// 0x3c EIND extended indirect register
529
530#define PUSHREGS() \
531 __asm__ volatile("push r1 \n\t" \
532 "push r0 \n\t" \
533 "in r0, __SREG__ \n\t" \
534 "cli \n\t" \
535 "push r0 \n\t" \
536 "in r0 , 0x3b \n\t" \
537 "push r0 \n\t" \
538 "in r0 , 0x3c \n\t" \
539 "push r0 \n\t" \
540 "clr r1 \n\t" \
541 "push r2 \n\t" \
542 "push r3 \n\t" \
543 "push r4 \n\t" \
544 "push r5 \n\t" \
545 "push r6 \n\t" \
546 "push r7 \n\t" \
547 "push r8 \n\t" \
548 "push r9 \n\t" \
549 "push r10 \n\t" \
550 "push r11 \n\t" \
551 "push r12 \n\t" \
552 "push r13 \n\t" \
553 "push r14 \n\t" \
554 "push r15 \n\t" \
555 "push r16 \n\t" \
556 "push r17 \n\t" \
557 "push r18 \n\t" \
558 "push r19 \n\t" \
559 "push r20 \n\t" \
560 "push r21 \n\t" \
561 "push r22 \n\t" \
562 "push r23 \n\t" \
563 "push r24 \n\t" \
564 "push r25 \n\t" \
565 "push r26 \n\t" \
566 "push r27 \n\t" \
567 "push r28 \n\t" \
568 "push r29 \n\t" \
569 "push r30 \n\t" \
570 "push r31 \n\t")
571
572#define POPREGS() \
573 __asm__ volatile("pop r31 \n\t" \
574 "pop r30 \n\t" \
575 "pop r29 \n\t" \
576 "pop r28 \n\t" \
577 "pop r27 \n\t" \
578 "pop r26 \n\t" \
579 "pop r25 \n\t" \
580 "pop r24 \n\t" \
581 "pop r23 \n\t" \
582 "pop r22 \n\t" \
583 "pop r21 \n\t" \
584 "pop r20 \n\t" \
585 "pop r19 \n\t" \
586 "pop r18 \n\t" \
587 "pop r17 \n\t" \
588 "pop r16 \n\t" \
589 "pop r15 \n\t" \
590 "pop r14 \n\t" \
591 "pop r13 \n\t" \
592 "pop r12 \n\t" \
593 "pop r11 \n\t" \
594 "pop r10 \n\t" \
595 "pop r9 \n\t" \
596 "pop r8 \n\t" \
597 "pop r7 \n\t" \
598 "pop r6 \n\t" \
599 "pop r5 \n\t" \
600 "pop r4 \n\t" \
601 "pop r3 \n\t" \
602 "pop r2 \n\t" \
603 "pop r0 \n\t" \
604 "out 0x3c , r0 \n\t " \
605 "pop r0 \n\t" \
606 "out 0x3b , r0 \n\t " \
607 "pop r0 \n\t" \
608 "out __SREG__ , r0 \n\t " \
609 "pop r0 \n\t" \
610 "pop r1 \n\t")
611
612#elif defined(__AVR_ATmega1284P__)
613
614// 0x3b RAMPZ extended z-pointer register
615// 0x3c EIND extended indirect register
616
617#define PUSHREGS() \
618 __asm__ volatile("push r1 \n\t" \
619 "push r0 \n\t" \
620 "in r0, __SREG__ \n\t" \
621 "cli \n\t" \
622 "push r0 \n\t" \
623 "in r0 , 0x3b \n\t" \
624 "push r0 \n\t" \
625 "clr r1 \n\t" \
626 "push r2 \n\t" \
627 "push r3 \n\t" \
628 "push r4 \n\t" \
629 "push r5 \n\t" \
630 "push r6 \n\t" \
631 "push r7 \n\t" \
632 "push r8 \n\t" \
633 "push r9 \n\t" \
634 "push r10 \n\t" \
635 "push r11 \n\t" \
636 "push r12 \n\t" \
637 "push r13 \n\t" \
638 "push r14 \n\t" \
639 "push r15 \n\t" \
640 "push r16 \n\t" \
641 "push r17 \n\t" \
642 "push r18 \n\t" \
643 "push r19 \n\t" \
644 "push r20 \n\t" \
645 "push r21 \n\t" \
646 "push r22 \n\t" \
647 "push r23 \n\t" \
648 "push r24 \n\t" \
649 "push r25 \n\t" \
650 "push r26 \n\t" \
651 "push r27 \n\t" \
652 "push r28 \n\t" \
653 "push r29 \n\t" \
654 "push r30 \n\t" \
655 "push r31 \n\t")
656
657#define POPREGS() \
658 __asm__ volatile("pop r31 \n\t" \
659 "pop r30 \n\t" \
660 "pop r29 \n\t" \
661 "pop r28 \n\t" \
662 "pop r27 \n\t" \
663 "pop r26 \n\t" \
664 "pop r25 \n\t" \
665 "pop r24 \n\t" \
666 "pop r23 \n\t" \
667 "pop r22 \n\t" \
668 "pop r21 \n\t" \
669 "pop r20 \n\t" \
670 "pop r19 \n\t" \
671 "pop r18 \n\t" \
672 "pop r17 \n\t" \
673 "pop r16 \n\t" \
674 "pop r15 \n\t" \
675 "pop r14 \n\t" \
676 "pop r13 \n\t" \
677 "pop r12 \n\t" \
678 "pop r11 \n\t" \
679 "pop r10 \n\t" \
680 "pop r9 \n\t" \
681 "pop r8 \n\t" \
682 "pop r7 \n\t" \
683 "pop r6 \n\t" \
684 "pop r5 \n\t" \
685 "pop r4 \n\t" \
686 "pop r3 \n\t" \
687 "pop r2 \n\t" \
688 "pop r0 \n\t" \
689 "out 0x3b , r0 \n\t " \
690 "pop r0 \n\t" \
691 "out __SREG__ , r0 \n\t " \
692 "pop r0 \n\t" \
693 "pop r1 \n\t")
694
695#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328PB__) \
696 || defined(__AVR_ATmega328__) || defined(__AVR_ATmega32U4__)
697
698#define PUSHREGS() \
699 __asm__ volatile("push r1 \n\t" \
700 "push r0 \n\t" \
701 "in r0, __SREG__ \n\t" \
702 "cli \n\t" \
703 "push r0 \n\t" \
704 "clr r1 \n\t" \
705 "push r2 \n\t" \
706 "push r3 \n\t" \
707 "push r4 \n\t" \
708 "push r5 \n\t" \
709 "push r6 \n\t" \
710 "push r7 \n\t" \
711 "push r8 \n\t" \
712 "push r9 \n\t" \
713 "push r10 \n\t" \
714 "push r11 \n\t" \
715 "push r12 \n\t" \
716 "push r13 \n\t" \
717 "push r14 \n\t" \
718 "push r15 \n\t" \
719 "push r16 \n\t" \
720 "push r17 \n\t" \
721 "push r18 \n\t" \
722 "push r19 \n\t" \
723 "push r20 \n\t" \
724 "push r21 \n\t" \
725 "push r22 \n\t" \
726 "push r23 \n\t" \
727 "push r24 \n\t" \
728 "push r25 \n\t" \
729 "push r26 \n\t" \
730 "push r27 \n\t" \
731 "push r28 \n\t" \
732 "push r29 \n\t" \
733 "push r30 \n\t" \
734 "push r31 \n\t")
735
736#define POPREGS() \
737 __asm__ volatile("pop r31 \n\t" \
738 "pop r30 \n\t" \
739 "pop r29 \n\t" \
740 "pop r28 \n\t" \
741 "pop r27 \n\t" \
742 "pop r26 \n\t" \
743 "pop r25 \n\t" \
744 "pop r24 \n\t" \
745 "pop r23 \n\t" \
746 "pop r22 \n\t" \
747 "pop r21 \n\t" \
748 "pop r20 \n\t" \
749 "pop r19 \n\t" \
750 "pop r18 \n\t" \
751 "pop r17 \n\t" \
752 "pop r16 \n\t" \
753 "pop r15 \n\t" \
754 "pop r14 \n\t" \
755 "pop r13 \n\t" \
756 "pop r12 \n\t" \
757 "pop r11 \n\t" \
758 "pop r10 \n\t" \
759 "pop r9 \n\t" \
760 "pop r8 \n\t" \
761 "pop r7 \n\t" \
762 "pop r6 \n\t" \
763 "pop r5 \n\t" \
764 "pop r4 \n\t" \
765 "pop r3 \n\t" \
766 "pop r2 \n\t" \
767 "pop r0 \n\t" \
768 "out __SREG__ , r0 \n\t " \
769 "pop r0 \n\t" \
770 "pop r1 \n\t")
771
772#else
773#error "unknown arch"
774#endif
775
776
777// function prototypes
778// naming convention
779// k_... function do a DI/EI and can impose task shift
780// ki_... expects interrupt to be disablet and do no task shift
781// rest is internal functions
782
783#ifdef DYNMEMORY
784
790void *k_malloc(int k);
791
799void k_free(void *m);
800#endif
801
813void k_wdt_enable(int t);
814
820void k_wdt_disable();
821
830unsigned long ki_millis(void);
831
841unsigned long k_millis(void);
842
851void k_eat_msec(unsigned int eatTime);
852
860void ki_task_shift(void) __attribute__((naked));
861
871int k_sleep(int time);
872
883struct k_t *k_crt_task(void (*pTask)(void), char prio, char *pS, int stkSize);
884
891
892int k_set_prio(char prio);
893
904struct k_t *k_crt_sem(int init_val, int maxvalue);
905
906
919struct k_t *k_crt_mut(char ceiling_prio, int init_val, int maxvalue);
920
921
929int k_mut_ceil_set(struct k_t *sem, char prio);
930
941int k_mut_ceil_enter(struct k_t *sem, int timeout);
942
951int k_mut_ceil_leave(struct k_t *sem);
952
965int k_mut_ceil(struct k_t *sem, int timeout, void (*fct)(void));
966
978int k_set_sem_timer(struct k_t *sem, int val);
979
989int ki_signal(struct k_t *sem);
990
1004int k_signal(struct k_t *sem);
1005
1019int k_wait(struct k_t *sem, int timeout);
1020
1036int k_wait2(struct k_t *sem, int timeout, int *nrClip);
1037
1045int k_sem_signals_lost(struct k_t *sem);
1046
1059int ki_wait(struct k_t *sem, int timeout);
1060
1071int ki_semval(struct k_t *sem);
1072
1082int k_semval(struct k_t *sem);
1083
1093int k_clear_sem(struct k_t *sem);
1094
1101int ki_msg_count(struct k_msg_t *msgbuffer);
1102
1111int k_msg_count(struct k_msg_t *m);
1112
1113/*********************************************************************
1114************************* DEBUG BREAKOUT FUNCTIONS *******************
1115**********************************************************************
1116*fk_mut
1117* Breakout functions can be removed by commenting out define of
1118* KRNLBUG in krnl.h (located around line 216)
1119
1120* All semaphore calls k_sem_clip, k_sem_signal, k_Sem_wait are all called
1121* AFTER decrement/incr of semaphore has taken place BUT before eventually
1122* taskshift.
1123*
1124* For message buffers/semaphores an internal semaphore is used for
1125synchronization
1126* so referring to the msgQ is by
1127* struct k_msg_t *msgSem; msgSem->sem->nr
1128*
1129*/
1130
1131#ifdef KRNLBUG
1142
1143void __attribute__((weak)) k_sem_clip(unsigned char nr, int nrClip);
1144#endif
1145
1146#ifdef KRNLBUG
1156
1157
1158void __attribute__((weak)) k_sem_signal(unsigned char nr, int val);
1159#endif
1160
1161#ifdef KRNLBUG
1169
1170
1171void __attribute__((weak)) k_sem_wait(unsigned char nr, int val);
1172#endif
1173
1174#ifdef KRNLBUG
1186
1187void __attribute__((weak)) k_send_Q_clip(unsigned char nr, int nrClip);
1188#endif
1189
1190struct k_msg_t *k_crt_send_Q(int nr_el, int el_size, void *pBuf);
1191
1204char ki_send(struct k_msg_t *pB, void *el);
1205
1216char k_send(struct k_msg_t *pB, void *el);
1217
1231char k_receive(struct k_msg_t *pB, void *el, int timeout, int *lost_msg);
1232
1249char ki_receive(struct k_msg_t *pB, void *el, int *lost_msg);
1250
1258int ki_clear_msg_Q(struct k_msg_t *pB);
1259
1264int k_clear_msg_Q(struct k_msg_t *pB);
1265
1266#ifdef READERWRITER
1270void k_rwInit(struct k_rwlock_t *lock);
1271
1275int k_rwRdEnter(struct k_rwlock_t *lock, int timeout);
1276
1280int k_rwWrEnter(struct k_rwlock_t *lock, int timeout);
1281
1285int k_rwRdLeave(struct k_rwlock_t *lock);
1286
1290int k_rwWrLeave(struct k_rwlock_t *lock);
1291
1292#endif
1293
1298int k_tmrInfo(void); // tm in milliseconds
1299
1308int k_init(int nrTask, int nrSem, int nrMsg);
1309
1318
1319int k_start(void); // tm in milliseconds
1320
1328int k_stop(); // tm in milliseconds
1329
1334void k_reset();
1335
1342
1351int k_stk_chk(struct k_t *t);
1352
1360int ki_unused_stak(struct k_t *t);
1361
1368int k_unused_stak(struct k_t *t);
1369
1376int ki_my_unused_stak();
1377
1383void k_round_robbin(void);
1384
1391void k_release(void);
1392
1395void k_set_coop_multitask(unsigned char onn);
1396
1401int freeRam(void);
1402
1403#ifdef KRNLBUG
1404
1405/*
1406 Breakout function called from scheduler
1407 You can use to examine who is runnning and who is next
1408 NB NB should be fast code and remember interrupt is and must be disables
1409 pRun->nr Nr of running.
1410 dummy has nr == 0
1411 then task is numbered 1.. in acc with order of creation of tasks
1412 k_breakout is defined as weak function so you can write your own k_breakout
1413 The builtin k_breakout has no code and just a placeholder to be subst
1414 with your code.
1415 setting led8-12 on uno as task number
1416 PORTB = (1 << pRun->nr) | led13
1417*/
1418
1419void __attribute__((weak)) k_breakout(void);
1420#endif
1421
1422#ifdef __cplusplus
1423}
1424#endif
1425#endif // #ifndef KRNL
struct k_t * pTask
int k_msg
Definition krnl.c:153
char nr_send
Definition krnl.c:154
struct k_t * pRun
Definition krnl.c:148
int k_sem
Definition krnl.c:153
struct k_t * pAQ
Definition krnl.c:147
volatile char k_running
Definition krnl.c:156
int k_task
Definition krnl.c:153
struct k_t * pSleepSem
Definition krnl.c:149
struct k_t * sem_pool
Definition krnl.c:144
struct k_t * pmain_el
Definition krnl.c:146
char nr_sem
Definition krnl.c:154
struct k_msg_t * send_pool
Definition krnl.c:151
char nr_task
Definition krnl.c:154
struct k_t AQ
Definition krnl.c:145
volatile char k_err_cnt
Definition krnl.c:156
unsigned char k_coopFlag
Definition krnl.c:166
struct k_t * task_pool
Definition krnl.c:143
unsigned long k_millis(void)
return no of millisec sincs start NB no leap seconds - its clean
Definition krnl.c:1247
int k_signal(struct k_t *sem)
Signal a semaphore w eventually task shift.
Definition krnl.c:636
void ki_task_shift(void)
shift running to task in front in AQ
Definition krnl.c:302
#define DMY_STK_SZ
Definition krnl.h:295
void k_reset()
unsigned long ki_millis(void)
returns no msec since start - no DI/EI lock Returns nr of milliseconds since krnl was started by k_st...
Definition krnl.c:1240
void k_eat_msec(unsigned int eatTime)
eat milliseconds - to mimik time consuming code
Definition krnl.c:246
volatile char k_bug_on
volatile char krnl_preempt_flag
void k_free(void *m)
a krnl free which do nothing. call free empty - no function if dft as weak so you can supply with you...
Definition krnl.c:1363
int k_stk_chk(struct k_t *t)
int ki_semval(struct k_t *sem)
return sem counter value - Its a ki_ fct so intr is not enabled by leave
Definition krnl.c:801
int k_msg_count(struct k_msg_t *m)
return no of pending messages
Definition krnl.c:833
void k_wdt_disable()
disable HW watchdog disable wdt Disable the watchdog timer
Definition krnl.c:1376
volatile char k_wdt_enabled
void k_breakout(void)
int k_tmrInfo(void)
Definition krnl.c:1256
void k_sem_signal(unsigned char nr, int val)
breakout for k_signal
Definition krnl.c:1345
int k_mut_ceil_set(struct k_t *sem, char prio)
set ceiling priority on a mutex
Definition krnl.c:529
char k_receive(struct k_msg_t *pB, void *el, int timeout, int *lost_msg)
Definition krnl.c:991
int ki_signal(struct k_t *sem)
signal a semaphore from AN ISR - no task shift , do not enable intr,...
Definition krnl.c:605
void k_release(void)
Definition krnl.c:1084
int k_wait2(struct k_t *sem, int timeout, int *nrClip)
wait with add info .´- nr of in max limit from signals since last time(saturation)
Definition krnl.c:691
int k_sleep(int time)
let task sleep for a number of milliseconds
Definition krnl.c:445
void k_wdt_enable(int t)
enable HW watchdog Call wdt_enable (AVR lib) DI(); wdt_enable(WDT_PERIOD); EI(); WDT_PERIOD is in KRN...
Definition krnl.c:1369
void k_send_Q_clip(unsigned char nr, int nrClip)
breakout for k_send
int k_start(void)
Definition krnl.c:1149
char ki_receive(struct k_msg_t *pB, void *el, int *lost_msg)
Definition krnl.c:959
int k_semval(struct k_t *sem)
as ki_semval but to enable intr after leave
Definition krnl.c:807
int k_set_prio(char prio)
Definition krnl.c:503
char ki_send(struct k_msg_t *pB, void *el)
Definition krnl.c:908
int k_wait(struct k_t *sem, int timeout)
stand wait on semaphore call with timeout facility
Definition krnl.c:683
int k_clear_msg_Q(struct k_msg_t *pB)
Definition krnl.c:900
int ki_unused_stak(struct k_t *t)
Definition krnl.c:472
int k_mut_ceil_leave(struct k_t *sem)
leave a "ceiled mutex" enter with k_mut_ceil_enter
Definition krnl.c:771
void k_set_coop_multitask(unsigned char onn)
Definition krnl.c:1236
int ki_my_unused_stak()
Definition krnl.c:455
int k_stop()
Definition krnl.c:1212
void k_round_robbin(void)
Definition krnl.c:1073
void * k_malloc(int k)
overruled malloc call malloc protected by DI and EI if dft as weak so you can supply with your own
Definition krnl.c:1355
int ki_msg_count(struct k_msg_t *msgbuffer)
returns no of pending msg on msgf sem - a ki_ fct so no enable of interrupt
Definition krnl.c:828
int k_set_sem_timer(struct k_t *sem, int val)
attach a periodic timer to a semaphore, to be used for realtime
Definition krnl.c:586
int k_unused_stak(struct k_t *t)
Definition krnl.c:493
char k_send(struct k_msg_t *pB, void *el)
Definition krnl.c:944
int k_sem_signals_lost(struct k_t *sem)
return signals lost on a sem(saturation) (and reset the saturation counter) Returns how many signals ...
Definition krnl.c:789
int freeRam(void)
Definition krnl.c:420
int k_mut_ceil_enter(struct k_t *sem, int timeout)
set ceiling priority on a mutex
Definition krnl.c:739
struct k_t * pDmy
Definition krnl.h:370
int k_mut_ceil(struct k_t *sem, int timeout, void(*fct)(void))
mutex entet, call fct, leave ceil in one call
Definition krnl.c:726
struct k_t * k_crt_sem(int init_val, int maxvalue)
change task priority and reinserts it in task Q and do a task shift
Definition krnl.c:544
struct k_t * k_crt_mut(char ceiling_prio, int init_val, int maxvalue)
crt a std semaphore to be used as mutex
Definition krnl.c:703
int k_init(int nrTask, int nrSem, int nrMsg)
Definition krnl.c:1108
struct k_msg_t * k_crt_send_Q(int nr_el, int el_size, void *pBuf)
Definition krnl.c:841
struct k_t * k_crt_task(void(*pTask)(void), char prio, char *pS, int stkSize)
create a task - only to be called before k_start creates a task and put it in the active Q
Definition krnl.c:328
char k_preempt_flag
void k_sem_wait(unsigned char nr, int val)
breakout for k_wait
Definition krnl.c:1347
int ki_wait(struct k_t *sem, int timeout)
a wait call with no disable - fct might no be usefull
Definition krnl.c:653
void k_sem_clip(unsigned char nr, int nrClip)
char dmy_stk[90]
int ki_clear_msg_Q(struct k_msg_t *pB)
Definition krnl.c:882
int k_clear_sem(struct k_t *sem)
reset sem counter to 0 is no tasks is waiting - usefull ?
Definition krnl.c:814
struct k_t * sem
Definition mutex.ino:3
unsigned long k_millis_counter
Definition krnl.c:161
volatile int k
Definition simpleisr.ino:7
volatile int m
Definition simpleisr.ino:7
unsigned char nr
Definition krnl.h:346
volatile int el_size
Definition krnl.h:349
volatile int r
Definition krnl.h:350
struct k_t * sem
Definition krnl.h:347
char * pBuf
Definition krnl.h:348
volatile int w
Definition krnl.h:350
volatile int nr_el
Definition krnl.h:349
volatile int lost_msg
Definition krnl.h:349
volatile int cnt
Definition krnl.h:350
Definition krnl.h:323
volatile char sp_lo
Definition krnl.h:330
struct k_t * pred
Definition krnl.h:329
char ceiling_prio
Definition krnl.h:333
volatile int cnt2
Definition krnl.h:336
volatile int cnt1
Definition krnl.h:335
void(* pt)(void)
Definition krnl.h:325
char prio
Definition krnl.h:332
struct k_t * next
Definition krnl.h:328
volatile int maxv
Definition krnl.h:338
unsigned char nr
Definition krnl.h:327
volatile char sp_hi
Definition krnl.h:331
volatile int clip
Definition krnl.h:339
volatile int cnt3
Definition krnl.h:337
char saved_prio
Definition krnl.h:334