For Cortex-M3,Cortex-M0, Multitask scheduler library. Arduino due compatible
Dependents: scheduler-demo-cq-lpc11u35 scheduler-demo scheduler-demo-cq-lpc11u35 mbed-scli-test
Revision 0:c68459544a17, committed 2013-08-25
- Comitter:
- dinau
- Date:
- Sun Aug 25 16:48:21 2013 +0900
- Child:
- 1:8967b575bb46
- Commit message:
- for mbed
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Scheduler.cpp Sun Aug 25 16:48:21 2013 +0900
@@ -0,0 +1,307 @@
+/*
+ * Copyright (C) 2012 audin
+ * This program is licensed under the Apache License, Version 2.0.
+ * Modified 2012/10: For working on Cortex-M0 and M3.
+ * Defined static tcb option for the cpu that has quite a less SRAM < 8kbyte.
+ *
+ * Original file is arduino-1.5\hardware\arduino\sam\libraries\Scheduler
+ */
+
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include "Scheduler.h"
+
+#define _ARM_CM0_ 1 /* 1: Cortex-M0 or M3, 0: Cortex-M3 */
+#define _USE_MALLOC_ 0 /* 1: 8kbyte >= SRAM, 0: 8kbyte < SRAM */
+
+
+#if _USE_MALLOC_
+# include <stdlib.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+uint32_t millis(void);
+
+#define NUM_REGS 10 // r4-r11, sp, lr
+
+typedef struct CoopTask {
+ uint32_t regs[NUM_REGS];
+ void* stackPtr;
+ struct CoopTask* next;
+ struct CoopTask* prev;
+} CoopTask;
+
+#if !_USE_MALLOC_
+static uint32_t id = 0;
+static CoopTask tcb[ COOP_TASK_NUM_MAX ];
+static uint8_t task_stack[ COOP_TASK_NUM_MAX - 1 ][ MIN_STACK_SIZE ];
+#endif
+
+static CoopTask *cur = 0;
+
+CoopTask* __attribute__((noinline)) coopSchedule(char taskDied) {
+ CoopTask* next = cur->next;
+
+#if _USE_MALLOC_
+ if (taskDied) {
+ // Halt if last task died.
+ if (next == cur)
+ while (1)
+ ;
+
+ // Delete task
+ if (cur->stackPtr)
+ free(cur->stackPtr);
+ cur->next->prev = cur->prev;
+ cur->prev->next = cur->next;
+ free(cur);
+ }
+#endif
+ cur = next;
+ return next;
+}
+
+static void __attribute__((naked)) __attribute__((noinline)) coopTaskStart(void) {
+#if _ARM_CM0_
+ /* for Cortex-m0 */
+ __asm (
+ "mov r0, r5;"
+ "blx r4;"
+ "mov r0, #1;"
+ "bl coopSchedule;"
+ /**** "ldmia r0, {r4-r12, lr};" */
+ "add r0, r0, #16;"
+ "ldmia r0!, {r4-r7};" /* get r7->r11, r6->r10, r5->r9, r4->r8 */
+ "mov r11, r7;"
+ "mov r10, r6;"
+ "mov r9, r5;"
+ "mov r8 , r4;"
+
+ "ldmia r0!, {r4-r5};" /* get r5->lr, r4->r12 */
+ "mov lr, r5;"
+ "mov r12, r4;"
+
+ "sub r0, r0, #40;" /* set offset for r4, 40 = 10reg * 4byte */
+ "ldmia r0!, {r4-r7};" /* get r7,r6,r5,r4 */
+ /**** end ldmia converted by Cortex-M0 instructions */
+ "msr msp, r12;" /* use main stack */
+ "bx lr;"
+ );
+#else
+ /* for Cortex-m3 or ARM code cpu */
+ asm (
+ "mov r0, r5;" /* r5 = new task func */
+ "blx r4;" /* r4 = helper func */
+ "mov r0, #1;"
+ "bl coopSchedule;"
+ "ldmia r0, {r4-r12, lr};"
+ "mov sp, r12;"
+ "bx lr;"
+ );
+#endif
+}
+
+static void __attribute__((naked)) __attribute__((noinline)) coopDoYield(CoopTask* curTask) {
+#if _ARM_CM0_
+ /* for Cortex-m0 */
+ __asm (
+ "mrs r12, msp;"
+ /**** "stmia r0, {r4-r12, lr};" */
+ "stmia r0!, {r4-r7};" /* first store r4-r7 data */
+
+ "mov r4, r8;"
+ "mov r5, r9;"
+ "mov r6, r10;"
+ "mov r7, r11;"
+ "stmia r0!, {r4-r7};" /* store r8-r11 */
+
+ "mov r4, r12;"
+ "mov r5, lr;"
+ "stmia r0!, {r4,r5};" /* store r12, lr */
+ /**** end stmia converted by cortex-m0 instructions */
+
+ "mov r0, #0;"
+ "bl coopSchedule;"
+
+ /**** "ldmia r0, {r4-r12, lr};" */
+ "add r0, r0, #16;" /* set offset for r8 */
+ "ldmia r0!, {r4-r7};" /* get r7->r11, r6->r10, r5->r9, r4->r8 */
+ "mov r11, r7;"
+ "mov r10, r6;"
+ "mov r9, r5;"
+ "mov r8 , r4;"
+
+ "ldmia r0!, {r4-r5};" /* get r5->lr, r4->r12 */
+ "mov lr, r5;"
+ "mov r12, r4;"
+
+ "sub r0, r0, #40;" /* set offset for r4, 40 = 10reg * 4byte */
+ "ldmia r0!, {r4-r7};"
+ /**** end ldmia converted by Cortex-M0 instructions */
+
+ "msr msp, r12;"
+ "bx lr;"
+ );
+#else
+ /* for Cortex-m3 or ARM code cpu */
+ __asm (
+ "mov r12, sp;"
+ "stmia r0, {r4-r12, lr};"
+ "mov r0, #0;"
+ "bl coopSchedule;"
+ "ldmia r0, {r4-r12, lr};"
+ "mov sp, r12;"
+ "bx lr;"
+ );
+#endif
+
+}
+
+static int coopInit(void) {
+ CoopTask* task;
+#if _USE_MALLOC_
+# ifdef __cplusplus
+ task = reinterpret_cast<CoopTask *>(malloc(sizeof(CoopTask)));
+# else
+ task = (CoopTask *)(malloc(sizeof(CoopTask)));
+# endif
+ if (!task)
+ return 0;
+#else
+ task = &tcb[ id ];
+#endif
+ task->next = task;
+ task->prev = task;
+ task->stackPtr = 0;
+ cur = task;
+
+ return 1;
+}
+
+static int coopSpawn(SchedulerParametricTask taskF, void* taskData, uint32_t stackSz) {
+#if _USE_MALLOC_
+ uint8_t *stack = (uint8_t*)malloc(stackSz);
+ if (!stack)
+ return 0;
+# ifdef __cplusplus
+ CoopTask *task = reinterpret_cast<CoopTask *>(malloc(sizeof(CoopTask)));
+# else
+ CoopTask *task = (CoopTask *)(malloc(sizeof(CoopTask)));
+# endif
+ if (!task) {
+ free(stack);
+ return 0;
+ }
+#else
+ uint8_t *stack = task_stack[ id ];
+ id++;
+ CoopTask *task = &tcb[ id ];
+#endif
+ task->stackPtr = stack;
+ task->regs[0] = (uint32_t) taskF; /* Helper func: r4 */
+ task->regs[1] = (uint32_t) taskData; /* New task : r5 */
+#if _USE_MALLOC_
+ task->regs[8] = ((uint32_t)(stack + stackSz)) & ~7;
+#else
+ task->regs[8] = ((uint32_t)(stack + MIN_STACK_SIZE)) & ~7; /* r12 */
+#endif
+ task->regs[9] = (uint32_t) & coopTaskStart; /* lr */
+
+ task->prev = cur;
+ task->next = cur->next;
+ cur->next->prev = task;
+ cur->next = task;
+
+ // These are here so compiler is sure that function is
+ // referenced in both variants (cancels a warning)
+ if (stackSz == 0xFFFFFFFF)
+ coopSchedule(0);
+ if (stackSz == 0xFFFFFFFE)
+ coopSchedule(1);
+
+ return 1;
+}
+
+void yield(void) {
+ coopDoYield(cur);
+}
+
+void wait(uint32_t ms) {
+ uint32_t start = millis();
+ while (millis() - start < ms)
+ yield();
+}
+
+#ifdef __cplusplus
+}; // extern "C"
+#endif
+
+void scheduler_init( void ) {
+ coopInit();
+}
+
+static void startLoopHelper(void *taskData) {
+#ifdef __cplusplus
+ SchedulerTask task = reinterpret_cast<SchedulerTask>(taskData);
+#else
+ SchedulerTask task = (SchedulerTask)(taskData);
+#endif
+ while (1){
+ task();
+ }
+}
+
+static void startTaskHelper(void *taskData) {
+#ifdef __cplusplus
+ SchedulerTask task = reinterpret_cast<SchedulerTask>(taskData);
+#else
+ SchedulerTask task = (SchedulerTask)(taskData);
+#endif
+ task();
+}
+
+void scheduler_start( SchedulerTask task ) {
+ coopSpawn( startTaskHelper, (void *)(task), MIN_STACK_SIZE );
+}
+
+void scheduler_startLoop( SchedulerTask task) {
+ coopSpawn( startLoopHelper, (void *)(task), MIN_STACK_SIZE );
+}
+
+#ifdef __cplusplus
+SchedulerClass::SchedulerClass() {
+ coopInit();
+}
+
+void SchedulerClass::startLoop(SchedulerTask task, uint32_t stackSize) {
+ coopSpawn(startLoopHelper, reinterpret_cast<void *>(task), stackSize);
+}
+
+void SchedulerClass::start(SchedulerTask task, uint32_t stackSize) {
+ coopSpawn(startTaskHelper, reinterpret_cast<void *>(task), stackSize);
+}
+
+void SchedulerClass::start(SchedulerParametricTask task, void *taskData, uint32_t stackSize) {
+ coopSpawn(task, taskData, stackSize);
+}
+
+SchedulerClass Scheduler;
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/Scheduler.h Sun Aug 25 16:48:21 2013 +0900
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 audin
+ * This program is licensed under the Apache License, Version 2.0.
+ * Modified 2012/11: v02:
+ * Added external definition of stack size and task number.
+ * Modified 2012/10: v01:
+ * For working on Cortex-M0 and M3.
+ * Defined static tcb option for the cpu that has quite a less SRAM < 8kbyte.
+ *
+ * Original file is arduino-1.5\hardware\arduino\sam\libraries\Scheduler
+ */
+
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _SCHEDULDER_H_
+#define _SCHEDULDER_H_
+
+/*
+ * If you explicitly specify stack size, activate below,
+ * or used "Default settings"
+ */
+//#define SCHEDULER_TASK_NUM_MAX 4
+//#define SCHEDULER_TASK_STACK_SIZE_EACH 200
+
+/*
+ * Otherwise you can add compile option CFLAGS like this,
+ -DSCHEDULER_TASK_NUM_MAX=4
+ -DSCHEDULER_TASK_STACK_SIZE_EACH=200
+*/
+
+/* Default settings */
+/******************************************************************************************/
+#ifndef SCHEDULER_TASK_NUM_MAX
+#define COOP_TASK_NUM_MAX 4 /* Define max task number( include main loop ) */
+#else
+#define COOP_TASK_NUM_MAX (SCHEDULER_TASK_NUM_MAX)
+#endif
+
+#ifndef SCHEDULER_TASK_STACK_SIZE_EACH
+#define MIN_STACK_SIZE (200) /* Minimum stack size per task, exclude main loop */
+#else
+#define MIN_STACK_SIZE (SCHEDULER_TASK_STACK_SIZE_EACH)
+#endif
+/* Thanks Ms.HI */
+/******************************************************************************************/
+
+#include <stdint.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+ typedef void (*SchedulerTask)(void);
+ typedef void (*SchedulerParametricTask)(void *);
+
+ void scheduler_init( void );
+ void scheduler_startLoop( SchedulerTask task );
+ void scheduler_start( SchedulerTask task );
+
+ void wait(uint32_t ms);
+ void yield();
+#ifdef __cplusplus
+}
+#endif
+
+
+#if __cplusplus
+class SchedulerClass {
+public:
+ SchedulerClass();
+ static void startLoop(SchedulerTask task, uint32_t stackSize = MIN_STACK_SIZE);
+ static void start(SchedulerTask task, uint32_t stackSize = MIN_STACK_SIZE);
+ static void start(SchedulerParametricTask task, void *data, uint32_t stackSize = MIN_STACK_SIZE);
+
+ static void wait(uint32_t ms) { ::wait(ms); };
+ static void yield() { ::yield(); };
+};
+
+extern SchedulerClass Scheduler;
+
+#endif
+
+#endif /* _SCHEDULDER_H_ */
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/keywords.txt Sun Aug 25 16:48:21 2013 +0900 @@ -0,0 +1,22 @@ +####################################### +# Syntax Coloring Map For Scheduler +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +Scheduler KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +yield KEYWORD2 +wait KEYWORD2 +startLoop KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### +