@@ -24,31 +24,116 @@ extern "C" {
2424
2525#if defined(ARDUINO_ARCH_AVR)
2626 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+
27112#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+ })
42127#endif
43128 #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
47130 #define PCH_REG 35
48131 #define DATAL_REG 36
49132 #define DATAH_REG 37
50133 #define TASKFL_REG 38
51134 #define TASKFH_REG 39
135+ #define SPL_REG 32
136+ #define SPH_REG 33
52137
53138 #define STACK_EM0 0xFFFF
54139 #define STACK_EM1 0xFFFE
@@ -63,7 +148,6 @@ extern "C" {
63148
64149 #define STACK_EM0 0xFFFFFFFF
65150 #define STACK_EM1 0xFFFFFFFE
66-
67151#endif
68152
69153typedef struct CoopTask {
@@ -104,7 +188,8 @@ static void _NAKED_ _NONINLINE_ coopTaskStart(void) {
104188 " movw 30, r4 \n\t "
105189 " ldd r26, Z+34 ;increment PC, next call ret without call ftask(data) \n\t "
106190 " 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 "
108193 " movw r18, r26 \n\t "
109194 " std Z+34, r18 \n\t "
110195 " std Z+35, r19 \n\t "
@@ -119,11 +204,14 @@ static void _NAKED_ _NONINLINE_ coopTaskStart(void) {
119204 " movw r4, r24 ;r25:r24 cur task\n\t "
120205 " movw 30, r4 ;load context \n\t "
121206 " ldd r6, Z+32 ;load stack\n\t "
207+ " in r0, __SREG__ ;safe interrupt\n\t "
208+ " cli \n\t "
122209 " mov r28,r6 \n\t "
123210 " out __SP_L__, r6 \n\t "
124211 " ldd r6, Z+33 \n\t "
125212 " mov r29,r6 \n\t "
126213 " out __SP_H__, r6 \n\t "
214+ " out __SREG__, r0 \n\t "
127215 " ldd r0, Z+0 ;load register \n\t "
128216 " ldd r1, Z+1 \n\t "
129217 " ldd r2, Z+2 \n\t "
@@ -210,6 +298,8 @@ static void _NAKED_ _NONINLINE_ coopDoYield(CoopTask* curTask _UNUSED_) {
210298 " std Z+33, r4 \n\t "
211299 " ldi r24, 0 ;next coop \n\t "
212300 " call coopSchedule \n\t "
301+ " in r0, __SREG__ ;safe interrupt\n\t "
302+ " cli \n\t "
213303 " movw r4, r24 ;load context \n\t "
214304 " movw 30, r4 \n\t "
215305 " ldd r6, Z+32 \n\t "
@@ -221,6 +311,7 @@ static void _NAKED_ _NONINLINE_ coopDoYield(CoopTask* curTask _UNUSED_) {
221311 " ldd r6, Z+34 ;load pc\n\t "
222312 " ldd r7, Z+35 \n\t "
223313 " movw r30, r6 \n\t "
314+ " out __SREG__, r0 \n\t "
224315 " icall ;call coopTaskStart if begin else return after icall \n\t "
225316 " movw r30, r4 ;need reload structure \n\t "
226317 " ldd r0, Z+0 ;load register \n\t "
@@ -359,12 +450,12 @@ static int coopInit(void) {
359450 task->regs [SPL_REG] = 0 ;
360451 task->regs [SPH_REG] = 0 ;
361452#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 ;
365456#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 ;
368459#endif
369460 task->regs [DATAL_REG] = 0 ;
370461 task->regs [DATAH_REG] = 0 ;
@@ -373,7 +464,6 @@ static int coopInit(void) {
373464#endif
374465
375466 cur = task;
376-
377467 return 1 ;
378468}
379469
@@ -397,15 +487,16 @@ static int coopSpawn(SchedulerParametricTask taskF, void* taskData, uint32_t sta
397487 task->regs [DATAL_REG] = (uint16_t )(taskData) & 0xFF ;
398488 task->regs [DATAH_REG] = ((uint16_t )(taskData) >> 8 ) & 0xFF ;
399489#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 ;
402492 task->regs [PCH_REG] = ((uint16_t )(pf) >> 8 ) & 0xFF ;
403493#else
404494 task->regs [PCL_REG] = (uint16_t )(coopTaskStart) & 0xFF ;
405495 task->regs [PCH_REG] = ((uint16_t )(coopTaskStart) >> 8 ) & 0xFF ;
406496#endif
407497 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+
409500
410501#elif defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD)
411502 task->regs [TASKF_REG] = (uint32_t ) taskF;
@@ -456,8 +547,8 @@ void SchedulerClass::startLoop(SchedulerTask task, stacksz_t stackSize)
456547static void startTaskHelper (void *taskData) {
457548 SchedulerTask task = reinterpret_cast <SchedulerTask>(taskData);
458549 task ();
459- #if defined( ARDUINO_ARCH_AVR)
460- yield ();
550+ #ifdef ARDUINO_ARCH_AVR
551+ yield ();
461552#endif
462553}
463554
@@ -466,11 +557,7 @@ void SchedulerClass::start(SchedulerTask task, stacksz_t stackSize) {
466557}
467558
468559void SchedulerClass::start (SchedulerParametricTask task, void *taskData, stacksz_t stackSize) {
469- coopSpawn (task, taskData, stackSize);
560+ coopSpawn (task, taskData, stackSize);
470561}
471562
472563SchedulerClass Scheduler;
473-
474- #undef _NONINLINE_
475- #undef _NOKED_
476- #undef _UNUSED_
0 commit comments