X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=src%2Fao_task.c;h=f5850fa4c15bab07b88fcd6c4a191ffd33323762;hp=12b73943f0c1c73eec79064c4b97e8f0dc1f21ab;hb=6492218fc316f8cf6214a577807a8dd0a80a9b6a;hpb=210dbaa23cdacf3a6f2d6e23493e96ee2ac9bca7 diff --git a/src/ao_task.c b/src/ao_task.c index 12b73943..f5850fa4 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -28,10 +28,19 @@ void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant { uint8_t __xdata *stack; + uint8_t task_id; + uint8_t t; if (ao_num_tasks == AO_NUM_TASKS) ao_panic(AO_PANIC_NO_TASK); + for (task_id = 1; task_id != 0; task_id++) { + for (t = 0; t < ao_num_tasks; t++) + if (ao_tasks[t]->task_id == task_id) + break; + if (t == ao_num_tasks) + break; + } ao_tasks[ao_num_tasks++] = task; - task->task_id = ao_num_tasks; + task->task_id = task_id; task->name = name; /* * Construct a stack frame so that it will 'return' @@ -39,32 +48,37 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam */ stack = task->stack; - *stack++ = ((uint16_t) start); - *stack++ = ((uint16_t) start) >> 8; + *stack++ = ((uint16_t) start); /* 0 */ + *stack++ = ((uint16_t) start) >> 8; /* 1 */ /* and the stuff saved by ao_switch */ - *stack++ = 0; /* acc */ - *stack++ = 0x80; /* IE */ - *stack++ = 0; /* DPL */ - *stack++ = 0; /* DPH */ - *stack++ = 0; /* B */ - *stack++ = 0; /* R2 */ - *stack++ = 0; /* R3 */ - *stack++ = 0; /* R4 */ - *stack++ = 0; /* R5 */ - *stack++ = 0; /* R6 */ - *stack++ = 0; /* R7 */ - *stack++ = 0; /* R0 */ - *stack++ = 0; /* R1 */ - *stack++ = 0; /* PSW */ - *stack++ = 0; /* BP */ - task->stack_count = stack - task->stack; + *stack++ = 0; /* 2 acc */ + *stack++ = 0x80; /* 3 IE */ + + /* 4 DPL + * 5 DPH + * 6 B + * 7 R2 + * 8 R3 + * 9 R4 + * 10 R5 + * 11 R6 + * 12 R7 + * 13 R0 + * 14 R1 + * 15 PSW + * 16 BP + */ + for (t = 0; t < 13; t++) + *stack++ = 0; + + task->stack_count = 17; task->wchan = NULL; } /* Task switching function. This must not use any stack variables */ void -ao_yield(void) _naked +ao_yield(void) __naked { /* Save current context */ @@ -93,7 +107,9 @@ ao_yield(void) _naked push _bp _endasm; - if (ao_cur_task_index != AO_NO_TASK_INDEX) + if (ao_cur_task_index == AO_NO_TASK_INDEX) + ao_cur_task_index = ao_num_tasks-1; + else { uint8_t stack_len; __data uint8_t *stack_ptr; @@ -127,6 +143,13 @@ ao_yield(void) _naked break; } + /* Check if the alarm is set for a time which has passed */ + if (ao_cur_task->alarm && + (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) { + ao_cur_task_index = ao_next_task_index; + break; + } + /* Enter lower power mode when there isn't anything to do */ if (ao_next_task_index == ao_cur_task_index) PCON = PCON_IDLE; @@ -179,13 +202,19 @@ ao_yield(void) _naked _endasm; } -void +uint8_t ao_sleep(__xdata void *wchan) { __critical { ao_cur_task->wchan = wchan; } ao_yield(); + ao_cur_task->alarm = 0; + if (ao_cur_task->wchan) { + ao_cur_task->wchan = NULL; + return 1; + } + return 0; } void @@ -198,6 +227,28 @@ ao_wakeup(__xdata void *wchan) ao_tasks[i]->wchan = NULL; } +void +ao_alarm(uint16_t delay) +{ + /* Make sure we sleep *at least* delay ticks, which means adding + * one to account for the fact that we may be close to the next tick + */ + if (!(ao_cur_task->alarm = ao_time() + delay + 1)) + ao_cur_task->alarm = 1; +} + +void +ao_exit(void) __critical +{ + uint8_t i; + ao_num_tasks--; + for (i = ao_cur_task_index; i < ao_num_tasks; i++) + ao_tasks[i] = ao_tasks[i+1]; + ao_cur_task_index = AO_NO_TASK_INDEX; + ao_yield(); + /* we'll never get back here */ +} + void ao_task_info(void) {