@@ -24,31 +24,116 @@ 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
+ void *__scheduler_malloc (size_t len)
36
+ {
37
+ extern size_t __malloc_margin;
38
+ extern char *__malloc_heap_start;
39
+ extern char *__malloc_heap_end;
40
+ extern char *__brkval;
41
+ extern struct __freelist *__flp;
42
+
43
+ struct __freelist *fp1, *fp2, *sfp1, *sfp2;
44
+ char *cp;
45
+ size_t s, avail;
46
+
47
+ if (len < sizeof (struct __freelist ) - sizeof (size_t ))
48
+ len = sizeof (struct __freelist ) - sizeof (size_t );
49
+
50
+ for (s = 0 , fp1 = __flp, fp2 = 0 ;
51
+ fp1;
52
+ fp2 = fp1, fp1 = fp1->nx ) {
53
+ if (fp1->sz < len)
54
+ continue ;
55
+ if (fp1->sz == len) {
56
+ if (fp2)
57
+ fp2->nx = fp1->nx ;
58
+ else
59
+ __flp = fp1->nx ;
60
+ return &(fp1->nx );
61
+ }
62
+ else {
63
+ if (s == 0 || fp1->sz < s) {
64
+ s = fp1->sz ;
65
+ sfp1 = fp1;
66
+ sfp2 = fp2;
67
+ }
68
+ }
69
+ }
70
+
71
+ if (s) {
72
+ if (s - len < sizeof (struct __freelist )) {
73
+ if (sfp2)
74
+ sfp2->nx = sfp1->nx ;
75
+ else
76
+ __flp = sfp1->nx ;
77
+ return &(sfp1->nx );
78
+ }
79
+
80
+ cp = (char *)sfp1;
81
+ s -= len;
82
+ cp += s;
83
+ sfp2 = (struct __freelist *)cp;
84
+ sfp2->sz = len;
85
+ sfp1->sz = s - sizeof (size_t );
86
+ return &(sfp2->nx );
87
+ }
88
+
89
+ if (__brkval == 0 )
90
+ __brkval = __malloc_heap_start;
91
+ cp = __malloc_heap_end;
92
+
93
+ if (cp == 0 )
94
+ {
95
+ cp = (char *)(RAMEND - DEFAULT_STACK_SIZE) - __malloc_margin;
96
+ }
97
+ if (cp <= __brkval)
98
+ return 0 ;
99
+
100
+ avail = cp - __brkval;
101
+
102
+ if (avail >= len && avail >= len + sizeof (size_t )) {
103
+ fp1 = (struct __freelist *)__brkval;
104
+ __brkval += len + sizeof (size_t );
105
+ fp1->sz = len;
106
+ return &(fp1->nx );
107
+ }
108
+
109
+ return 0 ;
110
+ }
111
+
27
112
#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
- })
113
+ #define GET_FAR_ADDRESS (var ) ({ \
114
+ uint32_t tmp;\
115
+ __asm__ __volatile__ ( \
116
+ " ldi %A0, lo8(%1) \n\t " \
117
+ " ldi %B0, hi8(%1) \n\t " \
118
+ " ldi %C0, hh8(%1) \n\t " \
119
+ " clr %D0 \n\t " \
120
+ : \
121
+ " =d" (tmp) \
122
+ : \
123
+ " p" (&(var)) \
124
+ ); \
125
+ tmp;\
126
+ })
42
127
#endif
43
128
#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
129
+ #define PCL_REG 34
47
130
#define PCH_REG 35
48
131
#define DATAL_REG 36
49
132
#define DATAH_REG 37
50
133
#define TASKFL_REG 38
51
134
#define TASKFH_REG 39
135
+ #define SPL_REG 32
136
+ #define SPH_REG 33
52
137
53
138
#define STACK_EM0 0xFFFF
54
139
#define STACK_EM1 0xFFFE
@@ -63,7 +148,6 @@ extern "C" {
63
148
64
149
#define STACK_EM0 0xFFFFFFFF
65
150
#define STACK_EM1 0xFFFFFFFE
66
-
67
151
#endif
68
152
69
153
typedef struct CoopTask {
@@ -104,7 +188,8 @@ static void _NAKED_ _NONINLINE_ coopTaskStart(void) {
104
188
" movw 30, r4 \n\t "
105
189
" ldd r26, Z+34 ;increment PC, next call ret without call ftask(data) \n\t "
106
190
" ldd r27, Z+35 \n\t "
107
- " adiw r26, 62 ;offset ret\n\t "
191
+ " adiw r26, 60 ;offset ret\n\t "
192
+ " adiw r26, 6 ;offset ret\n\t "
108
193
" movw r18, r26 \n\t "
109
194
" std Z+34, r18 \n\t "
110
195
" std Z+35, r19 \n\t "
@@ -119,11 +204,14 @@ static void _NAKED_ _NONINLINE_ coopTaskStart(void) {
119
204
" movw r4, r24 ;r25:r24 cur task\n\t "
120
205
" movw 30, r4 ;load context \n\t "
121
206
" ldd r6, Z+32 ;load stack\n\t "
207
+ " in r0, __SREG__ ;safe interrupt\n\t "
208
+ " cli \n\t "
122
209
" mov r28,r6 \n\t "
123
210
" out __SP_L__, r6 \n\t "
124
211
" ldd r6, Z+33 \n\t "
125
212
" mov r29,r6 \n\t "
126
213
" out __SP_H__, r6 \n\t "
214
+ " out __SREG__, r0 \n\t "
127
215
" ldd r0, Z+0 ;load register \n\t "
128
216
" ldd r1, Z+1 \n\t "
129
217
" ldd r2, Z+2 \n\t "
@@ -210,6 +298,8 @@ static void _NAKED_ _NONINLINE_ coopDoYield(CoopTask* curTask _UNUSED_) {
210
298
" std Z+33, r4 \n\t "
211
299
" ldi r24, 0 ;next coop \n\t "
212
300
" call coopSchedule \n\t "
301
+ " in r0, __SREG__ ;safe interrupt\n\t "
302
+ " cli \n\t "
213
303
" movw r4, r24 ;load context \n\t "
214
304
" movw 30, r4 \n\t "
215
305
" ldd r6, Z+32 \n\t "
@@ -221,6 +311,7 @@ static void _NAKED_ _NONINLINE_ coopDoYield(CoopTask* curTask _UNUSED_) {
221
311
" ldd r6, Z+34 ;load pc\n\t "
222
312
" ldd r7, Z+35 \n\t "
223
313
" movw r30, r6 \n\t "
314
+ " out __SREG__, r0 \n\t "
224
315
" icall ;call coopTaskStart if begin else return after icall \n\t "
225
316
" movw r30, r4 ;need reload structure \n\t "
226
317
" ldd r0, Z+0 ;load register \n\t "
@@ -359,12 +450,12 @@ static int coopInit(void) {
359
450
task->regs [SPL_REG] = 0 ;
360
451
task->regs [SPH_REG] = 0 ;
361
452
#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 ;
453
+ uint32_t pf = GET_FAR_ADDRESS (coopTaskStart);
454
+ task->regs [PCL_REG] = ((uint16_t )(pf) + 66 ) & 0xFF ;
455
+ task->regs [PCH_REG] = (((uint16_t )(pf) + 66 ) >> 8 ) & 0xFF ;
365
456
#else
366
- task->regs [PCL_REG] = ((uint16_t )(coopTaskStart) + 62 ) & 0xFF ;
367
- task->regs [PCH_REG] = (((uint16_t )(coopTaskStart) + 62 ) >> 8 ) & 0xFF ;
457
+ task->regs [PCL_REG] = ((uint16_t )(coopTaskStart) + 66 ) & 0xFF ;
458
+ task->regs [PCH_REG] = (((uint16_t )(coopTaskStart) + 66 ) >> 8 ) & 0xFF ;
368
459
#endif
369
460
task->regs [DATAL_REG] = 0 ;
370
461
task->regs [DATAH_REG] = 0 ;
@@ -373,7 +464,6 @@ static int coopInit(void) {
373
464
#endif
374
465
375
466
cur = task;
376
-
377
467
return 1 ;
378
468
}
379
469
@@ -397,15 +487,16 @@ static int coopSpawn(SchedulerParametricTask taskF, void* taskData, uint32_t sta
397
487
task->regs [DATAL_REG] = (uint16_t )(taskData) & 0xFF ;
398
488
task->regs [DATAH_REG] = ((uint16_t )(taskData) >> 8 ) & 0xFF ;
399
489
#ifdef EIND
400
- uint32_t pf = GET_FAR_ADDRESS (coopTaskStart);
401
- task->regs [PCL_REG] = (uint16_t )(pf) & 0xFF ;
490
+ uint32_t pf = GET_FAR_ADDRESS (coopTaskStart);
491
+ task->regs [PCL_REG] = (uint16_t )(pf) & 0xFF ;
402
492
task->regs [PCH_REG] = ((uint16_t )(pf) >> 8 ) & 0xFF ;
403
493
#else
404
494
task->regs [PCL_REG] = (uint16_t )(coopTaskStart) & 0xFF ;
405
495
task->regs [PCH_REG] = ((uint16_t )(coopTaskStart) >> 8 ) & 0xFF ;
406
496
#endif
407
497
task->regs [SPL_REG] = (uint16_t )(stack + stackSz - 1 ) & 0xFF ;
408
- task->regs [SPH_REG] = ((uint16_t )(stack + stackSz - 1 ) >> 8 ) & 0xFF ;
498
+ task->regs [SPH_REG] = ((uint16_t )(stack + stackSz - 1 ) >> 8 ) & 0xFF ;
499
+
409
500
410
501
#elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD)
411
502
task->regs [TASKF_REG] = (uint32_t ) taskF;
@@ -456,8 +547,8 @@ void SchedulerClass::startLoop(SchedulerTask task, stacksz_t stackSize)
456
547
static void startTaskHelper (void *taskData) {
457
548
SchedulerTask task = reinterpret_cast <SchedulerTask>(taskData);
458
549
task ();
459
- #if defined( ARDUINO_ARCH_AVR)
460
- yield ();
550
+ #ifdef ARDUINO_ARCH_AVR
551
+ yield ();
461
552
#endif
462
553
}
463
554
@@ -466,11 +557,7 @@ void SchedulerClass::start(SchedulerTask task, stacksz_t stackSize) {
466
557
}
467
558
468
559
void SchedulerClass::start (SchedulerParametricTask task, void *taskData, stacksz_t stackSize) {
469
- coopSpawn (task, taskData, stackSize);
560
+ coopSpawn (task, taskData, stackSize);
470
561
}
471
562
472
563
SchedulerClass Scheduler;
473
-
474
- #undef _NONINLINE_
475
- #undef _NOKED_
476
- #undef _UNUSED_
0 commit comments