Skip to content

Commit cfee2c8

Browse files
committed
add avr in library.properties
fix malloc(It will be strengthened as soon as possible), fix interrupt, need clean code
1 parent aee3187 commit cfee2c8

File tree

3 files changed

+132
-39
lines changed

3 files changed

+132
-39
lines changed

library.properties

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
name=Scheduler
2-
version=0.4.4
2+
version=0.4.5
33
author=Arduino
44
maintainer=Arduino <info@arduino.cc>
5-
sentence=Allows multiple tasks to run at the same time, without interrupting each other. For Arduino sam and samd architectures only (Due, Zero...).
5+
sentence=Allows multiple tasks to run at the same time, without interrupting each other. For Arduino avr/sam and samd architectures only (Uno, Due, Zero...).
66
paragraph=The Scheduler library enables the Arduino to run multiple functions at the same time. This allows tasks to happen without interrupting each other.</br>This is a cooperative scheduler in that the CPU switches from one task to another. The library includes methods for passing control between tasks.
77
category=Other
88
url=http://www.arduino.cc/en/Reference/Scheduler
9-
architectures=sam,samd
9+
architectures=avr,sam,samd

src/Scheduler.cpp

Lines changed: 122 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -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

69153
typedef 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)
456547
static 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

468559
void SchedulerClass::start(SchedulerParametricTask task, void *taskData, stacksz_t stackSize) {
469-
coopSpawn(task, taskData, stackSize);
560+
coopSpawn(task, taskData, stackSize);
470561
}
471562

472563
SchedulerClass Scheduler;
473-
474-
#undef _NONINLINE_
475-
#undef _NOKED_
476-
#undef _UNUSED_

src/Scheduler.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@
2020
#include <Arduino.h>
2121

2222
#if defined(ARDUINO_ARCH_AVR)
23+
#define malloc __scheduler_malloc
24+
2325
typedef uint16_t stacksz_t;
2426

2527
#if ((RAMEND - RAMSTART) < 1000)
2628
#pragma GCC error "board is not supported"
2729
//invoche a real fatal error
28-
#include "board is not supported"
30+
#include "board is not supported"
2931
#elif ((RAMEND - RAMSTART) < 2000)
3032
#define DEFAULT_STACK_SIZE 200
3133
#elif ((RAMEND - RAMSTART) < 3000)
@@ -45,6 +47,10 @@
4547
extern "C" {
4648
typedef void (*SchedulerTask)(void);
4749
typedef void (*SchedulerParametricTask)(void *);
50+
51+
#if defined(ARDUINO_ARCH_AVR)
52+
void *__scheduler_malloc(size_t len);
53+
#endif
4854
}
4955

5056
class SchedulerClass {

0 commit comments

Comments
 (0)