X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fcore%2Fao_task.c;h=df70b906ccfa6bec6c793c417a25bc4d4e652ff6;hb=4b13d3c659240e5a8347b1ba7ab0bf1d8355eba3;hp=a19a6a6f5e62f1f484ea09991c89d30cae9c7b79;hpb=f6f54d70b768dca1715ddddea64a4df00d82b09e;p=fw%2Faltos diff --git a/src/core/ao_task.c b/src/core/ao_task.c index a19a6a6f..df70b906 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -15,7 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" +#include +#include +#if HAS_SAMPLE_PROFILE +#include +#endif +#if HAS_STACK_GUARD +#include +#endif #define AO_NO_TASK_INDEX 0xff @@ -28,6 +35,20 @@ __xdata struct ao_task *__data ao_cur_task; ao_arch_task_globals #endif +#define AO_CHECK_STACK 0 + +#if AO_CHECK_STACK +static uint8_t in_yield; + +static inline void ao_check_stack(void) { + uint8_t q; + if (!in_yield && ao_cur_task && &q < &ao_cur_task->stack[0]) + ao_panic(AO_PANIC_STACK); +} +#else +#define ao_check_stack() +#endif + void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant { @@ -53,6 +74,8 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam ao_arch_init_stack(task, start); } +__xdata uint8_t ao_idle; + /* Task switching function. This must not use any stack variables */ void ao_yield(void) ao_arch_naked_define @@ -63,52 +86,68 @@ ao_yield(void) ao_arch_naked_define ao_cur_task_index = ao_num_tasks-1; else { +#if HAS_SAMPLE_PROFILE + uint16_t tick = ao_sample_profile_timer_value(); + uint16_t run = tick - ao_cur_task->start; + if (run > ao_cur_task->max_run) + ao_cur_task->max_run = run; + ++ao_cur_task->yields; +#endif ao_arch_save_stack(); } ao_arch_isr_stack(); +#if AO_CHECK_STACK + in_yield = 1; +#endif /* Find a task to run. If there isn't any runnable task, * this loop will run forever, which is just fine */ { - __pdata uint8_t ao_next_task_index = ao_cur_task_index; + __pdata uint8_t ao_last_task_index = ao_cur_task_index; for (;;) { - ++ao_next_task_index; - if (ao_next_task_index == ao_num_tasks) - ao_next_task_index = 0; + ++ao_cur_task_index; + if (ao_cur_task_index == ao_num_tasks) + ao_cur_task_index = 0; + + ao_cur_task = ao_tasks[ao_cur_task_index]; - ao_cur_task = ao_tasks[ao_next_task_index]; - if (ao_cur_task->wchan == NULL) { - ao_cur_task_index = ao_next_task_index; + /* Check for ready task */ + if (ao_cur_task->wchan == NULL) 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; + (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) break; - } /* Enter lower power mode when there isn't anything to do */ - if (ao_next_task_index == ao_cur_task_index) { + if (ao_cur_task_index == ao_last_task_index) ao_arch_cpu_idle(); - } } +#if HAS_SAMPLE_PROFILE + ao_cur_task->start = ao_sample_profile_timer_value(); +#endif } +#if HAS_STACK_GUARD + ao_mpu_stack_guard(ao_cur_task->stack); +#endif +#if AO_CHECK_STACK + cli(); + in_yield = 0; +#endif ao_arch_restore_stack(); } uint8_t ao_sleep(__xdata void *wchan) { - ao_arch_critical( - ao_cur_task->wchan = wchan; - ); + ao_cur_task->wchan = wchan; ao_yield(); if (ao_cur_task->wchan) { ao_cur_task->wchan = NULL; + ao_cur_task->alarm = 0; return 1; } return 0; @@ -119,6 +158,7 @@ ao_wakeup(__xdata void *wchan) { uint8_t i; + ao_check_stack(); for (i = 0; i < ao_num_tasks; i++) if (ao_tasks[i]->wchan == wchan) ao_tasks[i]->wchan = NULL; @@ -140,6 +180,16 @@ ao_clear_alarm(void) ao_cur_task->alarm = 0; } +static __xdata uint8_t ao_forever; + +void +ao_delay(uint16_t ticks) +{ + ao_alarm(ticks); + ao_sleep(&ao_forever); + ao_clear_alarm(); +} + void ao_exit(void) { @@ -157,14 +207,14 @@ ao_exit(void) void ao_task_info(void) { - uint8_t i; + uint8_t i; __xdata struct ao_task *task; for (i = 0; i < ao_num_tasks; i++) { task = ao_tasks[i]; printf("%12s: wchan %04x\n", task->name, - (int16_t) task->wchan); + (int) task->wchan); } }