summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src-avr/ao.h4
-rw-r--r--src-avr/ao_task.c45
2 files changed, 32 insertions, 17 deletions
diff --git a/src-avr/ao.h b/src-avr/ao.h
index 242c26c7..90298a3e 100644
--- a/src-avr/ao.h
+++ b/src-avr/ao.h
@@ -50,7 +50,11 @@
struct ao_task {
__xdata void *wchan; /* current wait channel (NULL if running) */
uint16_t alarm; /* abort ao_sleep time */
+#ifdef AVR
+ uint8_t *sp; /* saved stack pointer */
+#else
uint8_t stack_count; /* amount of saved stack */
+#endif
uint8_t task_id; /* unique id */
__code char *name; /* task name */
uint8_t stack[AO_STACK_SIZE]; /* saved stack */
diff --git a/src-avr/ao_task.c b/src-avr/ao_task.c
index 3c6b34a4..b3bee6c9 100644
--- a/src-avr/ao_task.c
+++ b/src-avr/ao_task.c
@@ -31,22 +31,22 @@ __xdata struct ao_task *__data ao_cur_task;
static void
ao_init_stack(__xdata struct ao_task *task, void (*start)(void))
{
- uint8_t *stack = task->stack + AO_STACK_SIZE - 1;
+ uint8_t *sp = task->stack + AO_STACK_SIZE - 1;
uint16_t a = (uint16_t) start;
int i;
/* Return address */
- PUSH8(stack, a);
- PUSH8(stack, (a >> 8));
+ PUSH8(sp, a);
+ PUSH8(sp, (a >> 8));
/* Clear register values */
i = 32;
while (i--)
- PUSH8(stack, 0);
+ PUSH8(sp, 0);
/* SREG with interrupts enabled */
- PUSH8(stack, 0x80);
- task->stack_count = stack - task->stack;
+ PUSH8(sp, 0x80);
+ task->sp = sp;
}
#else
static void
@@ -102,6 +102,19 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam
ao_init_stack(task, start);
}
+void
+ao_show_task_from(void)
+{
+ if (ao_cur_task)
+ printf("switching from %s\n", ao_cur_task->name);
+}
+
+void
+ao_show_task_to(void)
+{
+ printf("switching to %s\n", ao_cur_task->name);
+}
+
/* Task switching function. This must not use any stack variables */
void
ao_yield(void) __naked
@@ -114,6 +127,7 @@ ao_yield(void) __naked
asm("push r14" "\n\t" "push r13" "\n\t" "push r12" "\n\t" "push r11" "\n\t" "push r10");
asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5");
asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0");
+ cli();
asm("in r0, __SREG__" "\n\t" "push r0");
sei();
#else
@@ -150,11 +164,9 @@ ao_yield(void) __naked
{
#ifdef AVR
uint8_t sp_l, sp_h;
- uint8_t *sp;
asm("in %0,__SP_L__" : "=&r" (sp_l) );
asm("in %0,__SP_H__" : "=&r" (sp_h) );
- sp = (uint8_t *) ((uint16_t) sp_l | ((uint16_t) sp_h << 8));
- ao_cur_task->stack_count = sp - ao_cur_task->stack;
+ ao_cur_task->sp = (uint8_t *) ((uint16_t) sp_l | ((uint16_t) sp_h << 8));
#else
uint8_t stack_len;
__data uint8_t *stack_ptr;
@@ -175,6 +187,7 @@ ao_yield(void) __naked
SP = AO_STACK_START - 1;
#endif
+ ao_show_task_from();
/* Find a task to run. If there isn't any runnable task,
* this loop will run forever, which is just fine
*/
@@ -209,10 +222,11 @@ ao_yield(void) __naked
#ifdef AVR
{
- uint8_t *sp = (ao_cur_task->stack + ao_cur_task->stack_count);
uint8_t sp_l, sp_h;
- sp_l = (uint16_t) sp;
- sp_h = ((uint16_t) sp) >> 8;
+ sp_l = (uint16_t) ao_cur_task->sp;
+ sp_h = ((uint16_t) ao_cur_task->sp) >> 8;
+ ao_show_task_to();
+ cli();
asm("out __SP_H__,%0" : : "r" (sp_h) );
asm("out __SP_L__,%0" : : "r" (sp_l) );
asm("pop r0" "\n\t"
@@ -325,16 +339,13 @@ void
ao_task_info(void)
{
uint8_t i;
- uint8_t pc_loc;
__xdata struct ao_task *task;
for (i = 0; i < ao_num_tasks; i++) {
task = ao_tasks[i];
- pc_loc = task->stack_count - 17;
- printf("%12s: wchan %04x pc %04x\n",
+ printf("%12s: wchan %04x\n",
task->name,
- (int16_t) task->wchan,
- (task->stack[pc_loc]) | (task->stack[pc_loc+1] << 8));
+ (int16_t) task->wchan);
}
}