@@ -24,31 +24,119 @@ extern "C" {
24
24
25
25
#if defined(ARDUINO_ARCH_AVR)
26
26
typedef uint8_t reg_t ;
27
+
28
+ #include < stdlib.h>
29
+
30
+ struct __freelist {
31
+ size_t sz;
32
+ struct __freelist *nx;
33
+ };
34
+
35
+ uint32_t __mainloopstack = DEFAULT_STACK_SIZE;
36
+
37
+ void *__poison_malloc (size_t len)
38
+ {
39
+ extern size_t __malloc_margin;
40
+ extern char *__malloc_heap_start;
41
+ extern char *__malloc_heap_end;
42
+ extern char *__brkval;
43
+ extern struct __freelist *__flp;
44
+
45
+ struct __freelist *fp1, *fp2, *sfp1, *sfp2;
46
+ char *cp;
47
+ size_t s, avail;
48
+
49
+ if (len < sizeof (struct __freelist ) - sizeof (size_t ))
50
+ len = sizeof (struct __freelist ) - sizeof (size_t );
51
+
52
+ for (s = 0 , fp1 = __flp, fp2 = 0 ;
53
+ fp1;
54
+ fp2 = fp1, fp1 = fp1->nx ) {
55
+ if (fp1->sz < len)
56
+ continue ;
57
+ if (fp1->sz == len) {
58
+ if (fp2)
59
+ fp2->nx = fp1->nx ;
60
+ else
61
+ __flp = fp1->nx ;
62
+ return &(fp1->nx );
63
+ }
64
+ else {
65
+ if (s == 0 || fp1->sz < s) {
66
+ s = fp1->sz ;
67
+ sfp1 = fp1;
68
+ sfp2 = fp2;
69
+ }
70
+ }
71
+ }
72
+
73
+ if (s) {
74
+ if (s - len < sizeof (struct __freelist )) {
75
+ if (sfp2)
76
+ sfp2->nx = sfp1->nx ;
77
+ else
78
+ __flp = sfp1->nx ;
79
+ return &(sfp1->nx );
80
+ }
81
+
82
+ cp = (char *)sfp1;
83
+ s -= len;
84
+ cp += s;
85
+ sfp2 = (struct __freelist *)cp;
86
+ sfp2->sz = len;
87
+ sfp1->sz = s - sizeof (size_t );
88
+ return &(sfp2->nx );
89
+ }
90
+
91
+ if (__brkval == 0 )
92
+ __brkval = __malloc_heap_start;
93
+ cp = __malloc_heap_end;
94
+
95
+ if (cp == 0 )
96
+ cp = (char *)(RAMEND + __mainloopstack) - __malloc_margin;
97
+
98
+ if (cp <= __brkval)
99
+ return 0 ;
100
+
101
+ avail = cp - __brkval;
102
+
103
+ if (avail >= len && avail >= len + sizeof (size_t )) {
104
+ fp1 = (struct __freelist *)__brkval;
105
+ __brkval += len + sizeof (size_t );
106
+ fp1->sz = len;
107
+ return &(fp1->nx );
108
+ }
109
+
110
+ return 0 ;
111
+
112
+ }
113
+
114
+
27
115
#ifdef EIND
28
- #define GET_FAR_ADDRESS (var ) ({ \
29
- uint32_t tmp;\
30
- __asm__ __volatile__ ( \
31
- " ldi %A0, lo8(%1) \n\t " \
32
- " ldi %B0, hi8(%1) \n\t " \
33
- " ldi %C0, hh8(%1) \n\t " \
34
- " clr %D0 \n\t " \
35
- : \
36
- " =d" (tmp) \
37
- : \
38
- " p" (&(var)) \
39
- ); \
40
- tmp;\
41
- })
116
+ #define GET_FAR_ADDRESS (var ) ({ \
117
+ uint32_t tmp;\
118
+ __asm__ __volatile__ ( \
119
+ " ldi %A0, lo8(%1) \n\t " \
120
+ " ldi %B0, hi8(%1) \n\t " \
121
+ " ldi %C0, hh8(%1) \n\t " \
122
+ " clr %D0 \n\t " \
123
+ : \
124
+ " =d" (tmp) \
125
+ : \
126
+ " p" (&(var)) \
127
+ ); \
128
+ tmp;\
129
+ })
42
130
#endif
43
131
#define NUM_REGS 40 // r0/31 + sp(2) + pc(2) + data(2) + ftask(2)
44
- #define SPL_REG 32
45
- #define SPH_REG 33
46
- #define PCL_REG 34
132
+ #define PCL_REG 34
47
133
#define PCH_REG 35
48
134
#define DATAL_REG 36
49
135
#define DATAH_REG 37
50
136
#define TASKFL_REG 38
51
137
#define TASKFH_REG 39
138
+ #define SPL_REG 32
139
+ #define SPH_REG 33
52
140
53
141
#define STACK_EM0 0xFFFF
54
142
#define STACK_EM1 0xFFFE
@@ -63,7 +151,6 @@ extern "C" {
63
151
64
152
#define STACK_EM0 0xFFFFFFFF
65
153
#define STACK_EM1 0xFFFFFFFE
66
-
67
154
#endif
68
155
69
156
typedef struct CoopTask {
@@ -74,6 +161,7 @@ typedef struct CoopTask {
74
161
} CoopTask;
75
162
76
163
static CoopTask *cur = 0 ;
164
+ CoopTask *mainloop = 0 ;
77
165
78
166
static CoopTask* __attribute__ ((noinline)) coopSchedule(char taskDied) {
79
167
CoopTask* next = cur->next ;
@@ -104,7 +192,8 @@ static void _NAKED_ _NONINLINE_ coopTaskStart(void) {
104
192
" movw 30, r4 \n\t "
105
193
" ldd r26, Z+34 ;increment PC, next call ret without call ftask(data) \n\t "
106
194
" ldd r27, Z+35 \n\t "
107
- " adiw r26, 62 ;offset ret\n\t "
195
+ " adiw r26, 60 ;offset ret\n\t "
196
+ " adiw r26, 6 ;offset ret\n\t "
108
197
" movw r18, r26 \n\t "
109
198
" std Z+34, r18 \n\t "
110
199
" std Z+35, r19 \n\t "
@@ -119,11 +208,14 @@ static void _NAKED_ _NONINLINE_ coopTaskStart(void) {
119
208
" movw r4, r24 ;r25:r24 cur task\n\t "
120
209
" movw 30, r4 ;load context \n\t "
121
210
" ldd r6, Z+32 ;load stack\n\t "
211
+ " in r0, __SREG__ ;safe interrupt\n\t "
212
+ " cli \n\t "
122
213
" mov r28,r6 \n\t "
123
214
" out __SP_L__, r6 \n\t "
124
215
" ldd r6, Z+33 \n\t "
125
216
" mov r29,r6 \n\t "
126
217
" out __SP_H__, r6 \n\t "
218
+ " out __SREG__, r0 \n\t "
127
219
" ldd r0, Z+0 ;load register \n\t "
128
220
" ldd r1, Z+1 \n\t "
129
221
" ldd r2, Z+2 \n\t "
@@ -210,6 +302,8 @@ static void _NAKED_ _NONINLINE_ coopDoYield(CoopTask* curTask _UNUSED_) {
210
302
" std Z+33, r4 \n\t "
211
303
" ldi r24, 0 ;next coop \n\t "
212
304
" call coopSchedule \n\t "
305
+ " in r0, __SREG__ ;safe interrupt\n\t "
306
+ " cli \n\t "
213
307
" movw r4, r24 ;load context \n\t "
214
308
" movw 30, r4 \n\t "
215
309
" ldd r6, Z+32 \n\t "
@@ -221,6 +315,7 @@ static void _NAKED_ _NONINLINE_ coopDoYield(CoopTask* curTask _UNUSED_) {
221
315
" ldd r6, Z+34 ;load pc\n\t "
222
316
" ldd r7, Z+35 \n\t "
223
317
" movw r30, r6 \n\t "
318
+ " out __SREG__, r0 \n\t "
224
319
" icall ;call coopTaskStart if begin else return after icall \n\t "
225
320
" movw r30, r4 ;need reload structure \n\t "
226
321
" ldd r0, Z+0 ;load register \n\t "
@@ -346,8 +441,9 @@ static void _NAKED_ _NONINLINE_ coopDoYield(CoopTask* curTask) {
346
441
347
442
static int coopInit (void ) {
348
443
CoopTask* task;
349
-
444
+
350
445
task = reinterpret_cast <CoopTask *>(malloc (sizeof (CoopTask)));
446
+
351
447
if (!task)
352
448
return 0 ;
353
449
@@ -356,24 +452,24 @@ static int coopInit(void) {
356
452
task->stackPtr = NULL ;
357
453
358
454
#ifdef ARDUINO_ARCH_AVR
455
+ mainloop = task;
359
456
task->regs [SPL_REG] = 0 ;
360
457
task->regs [SPH_REG] = 0 ;
361
458
#ifdef EIND
362
- uint32_t pf = GET_FAR_ADDRESS (coopTaskStart);
363
- task->regs [PCL_REG] = ((uint16_t )(pf) + 62 ) & 0xFF ;
364
- task->regs [PCH_REG] = (((uint16_t )(pf) + 62 ) >> 8 ) & 0xFF ;
459
+ uint32_t pf = GET_FAR_ADDRESS (coopTaskStart);
460
+ task->regs [PCL_REG] = ((uint16_t )(pf) + 66 ) & 0xFF ;
461
+ task->regs [PCH_REG] = (((uint16_t )(pf) + 66 ) >> 8 ) & 0xFF ;
365
462
#else
366
- task->regs [PCL_REG] = ((uint16_t )(coopTaskStart) + 62 ) & 0xFF ;
367
- task->regs [PCH_REG] = (((uint16_t )(coopTaskStart) + 62 ) >> 8 ) & 0xFF ;
463
+ task->regs [PCL_REG] = ((uint16_t )(coopTaskStart) + 66 ) & 0xFF ;
464
+ task->regs [PCH_REG] = (((uint16_t )(coopTaskStart) + 66 ) >> 8 ) & 0xFF ;
368
465
#endif
369
466
task->regs [DATAL_REG] = 0 ;
370
467
task->regs [DATAH_REG] = 0 ;
371
468
task->regs [TASKFL_REG] = 0 ;
372
469
task->regs [TASKFH_REG] = 0 ;
373
470
#endif
374
-
471
+
375
472
cur = task;
376
-
377
473
return 1 ;
378
474
}
379
475
@@ -397,15 +493,16 @@ static int coopSpawn(SchedulerParametricTask taskF, void* taskData, uint32_t sta
397
493
task->regs [DATAL_REG] = (uint16_t )(taskData) & 0xFF ;
398
494
task->regs [DATAH_REG] = ((uint16_t )(taskData) >> 8 ) & 0xFF ;
399
495
#ifdef EIND
400
- uint32_t pf = GET_FAR_ADDRESS (coopTaskStart);
401
- task->regs [PCL_REG] = (uint16_t )(pf) & 0xFF ;
496
+ uint32_t pf = GET_FAR_ADDRESS (coopTaskStart);
497
+ task->regs [PCL_REG] = (uint16_t )(pf) & 0xFF ;
402
498
task->regs [PCH_REG] = ((uint16_t )(pf) >> 8 ) & 0xFF ;
403
499
#else
404
500
task->regs [PCL_REG] = (uint16_t )(coopTaskStart) & 0xFF ;
405
501
task->regs [PCH_REG] = ((uint16_t )(coopTaskStart) >> 8 ) & 0xFF ;
406
502
#endif
407
503
task->regs [SPL_REG] = (uint16_t )(stack + stackSz - 1 ) & 0xFF ;
408
- task->regs [SPH_REG] = ((uint16_t )(stack + stackSz - 1 ) >> 8 ) & 0xFF ;
504
+ task->regs [SPH_REG] = ((uint16_t )(stack + stackSz - 1 ) >> 8 ) & 0xFF ;
505
+
409
506
410
507
#elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD)
411
508
task->regs [TASKF_REG] = (uint32_t ) taskF;
@@ -434,6 +531,27 @@ void yield(void) {
434
531
coopDoYield (cur);
435
532
}
436
533
534
+ #if defined(ARDUINO_ARCH_AVR)
535
+
536
+ void *__scheduler_malloc (size_t len)
537
+ {
538
+ extern int __heap_start, *__brkval;
539
+ int v = (__brkval == NULL ) ? __heap_start : (int )(__brkval);
540
+ char * c[5 ];
541
+ if ( (int )(c) < v )
542
+ {
543
+ return __poison_malloc (len);
544
+ }
545
+
546
+ #pragma pop_macro("malloc")
547
+ return malloc (len);
548
+ #pragma push_macro("malloc")
549
+ #undef malloc
550
+ #define malloc __scheduler_malloc
551
+ }
552
+
553
+ #endif
554
+
437
555
}; // extern "C"
438
556
439
557
SchedulerClass::SchedulerClass () {
@@ -450,27 +568,29 @@ static void startLoopHelper(void *taskData) {
450
568
451
569
void SchedulerClass::startLoop (SchedulerTask task, stacksz_t stackSize)
452
570
{
571
+ if ( stackSize < DEFAULT_MIN_STACK_SIZE)
572
+ stackSize = DEFAULT_MIN_STACK_SIZE;
453
573
coopSpawn (startLoopHelper, reinterpret_cast <void *>(task), stackSize);
454
574
}
455
575
456
576
static void startTaskHelper (void *taskData) {
457
577
SchedulerTask task = reinterpret_cast <SchedulerTask>(taskData);
458
578
task ();
459
- #if defined( ARDUINO_ARCH_AVR)
460
- yield ();
579
+ #ifdef ARDUINO_ARCH_AVR
580
+ yield ();
461
581
#endif
462
582
}
463
583
464
584
void SchedulerClass::start (SchedulerTask task, stacksz_t stackSize) {
585
+ if ( stackSize < DEFAULT_MIN_STACK_SIZE)
586
+ stackSize = DEFAULT_MIN_STACK_SIZE;
465
587
coopSpawn (startTaskHelper, reinterpret_cast <void *>(task), stackSize);
466
588
}
467
589
468
590
void SchedulerClass::start (SchedulerParametricTask task, void *taskData, stacksz_t stackSize) {
469
- coopSpawn (task, taskData, stackSize);
591
+ if ( stackSize < DEFAULT_MIN_STACK_SIZE)
592
+ stackSize = DEFAULT_MIN_STACK_SIZE;
593
+ coopSpawn (task, taskData, stackSize);
470
594
}
471
595
472
596
SchedulerClass Scheduler;
473
-
474
- #undef _NONINLINE_
475
- #undef _NOKED_
476
- #undef _UNUSED_
0 commit comments