altos: struct ao_log_mega doesn't have a ground temp value
[fw/altos] / src / core / ao_task.c
index 32826114c4e5e855fa6e1159378c57321cb2c9ae..65654731aeaeaccc9f45477e156ffa1419d13c0b 100644 (file)
@@ -15,7 +15,7 @@
  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  */
 
-#include "ao.h"
+#include <ao.h>
 
 #define AO_NO_TASK_INDEX       0xff
 
@@ -28,6 +28,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
 {
@@ -68,48 +82,50 @@ ao_yield(void) ao_arch_naked_define
 
        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_next_task_index];
-                       if (ao_cur_task->wchan == NULL) {
-                               ao_cur_task_index = ao_next_task_index;
+                       ao_cur_task = ao_tasks[ao_cur_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 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();
-       ao_cur_task->alarm = 0;
        if (ao_cur_task->wchan) {
                ao_cur_task->wchan = NULL;
+               ao_cur_task->alarm = 0;
                return 1;
        }
        return 0;
@@ -120,6 +136,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;
@@ -135,6 +152,22 @@ ao_alarm(uint16_t delay)
                ao_cur_task->alarm = 1;
 }
 
+void
+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)
 {
@@ -152,14 +185,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);
        }
 }