altos: Declare task stack as union of uint8_t and uint32_t
[fw/altos] / src / avr / ao_arch.h
index c695a725669bf2e64bf77f49d31088f779fc3676..d3454f917fc6f75aa32d5879d2d3d9a4cf821198 100644 (file)
@@ -3,7 +3,8 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * AVR definitions and code fragments for AltOS
  */
 
-#define AO_STACK_SIZE  128
+#ifndef AO_STACK_SIZE
+#define AO_STACK_SIZE  116
+#endif
+
+#define AO_PORT_TYPE   uint8_t
 
 /* Various definitions to make GCC look more like SDCC */
 
 #define ao_arch_naked_declare  __attribute__((naked))
 #define ao_arch_naked_define
-#define __pdata
-#define __data
-#define __xdata
-#define __code const
-#define __reentrant
-#define __critical
 #define __interrupt(n)
 #define __at(n)
 
@@ -67,7 +66,11 @@ extern void putchar(char c);
 extern char getchar(void);
 extern void ao_avr_stdio_init(void);
 
-extern const uint16_t ao_serial_number;
+#define AO_ROMCONFIG_VERSION   2
+
+#define AO_ROMCONFIG_SYMBOL(a) const
+
+extern AO_ROMCONFIG_SYMBOL(0) uint16_t ao_serial_number;
 
 #define AVR_PUSH8(stack, val)  (*((stack)--) = (val))
 
@@ -75,27 +78,25 @@ extern uint8_t      ao_cpu_sleep_disable;
 
 #define ao_arch_task_globals   uint8_t ao_cpu_sleep_disable;
 
-#define ao_arch_task_members\
-       uint8_t *sp;                    /* saved stack pointer */
-
-#define ao_arch_init_stack(task, start) do {                   \
-       uint8_t         *sp = task->stack + AO_STACK_SIZE - 1;  \
-       uint16_t        a = (uint16_t) start;                   \
-       int             i;                                      \
-                                                               \
-       /* Return address */                                    \
-       AVR_PUSH8(sp, a);                                       \
-       AVR_PUSH8(sp, (a >> 8));                                \
-                                                               \
-       /* Clear register values */                             \
-       i = 32;                                                 \
-       while (i--)                                             \
-               AVR_PUSH8(sp, 0);                               \
-                                                               \
-       /* SREG with interrupts enabled */                      \
-       AVR_PUSH8(sp, 0x80);                                    \
-       task->sp = sp;                                          \
-} while (0);
+#define ao_arch_init_stack(task, start) \
+       do {                                                            \
+               uint8_t         *sp = task->stack8 + AO_STACK_SIZE - 1; \
+               uint16_t        a = (uint16_t) start;                   \
+               int             i;                                      \
+                                                                       \
+               /* Return address */                                    \
+               AVR_PUSH8(sp, a);                                       \
+               AVR_PUSH8(sp, (a >> 8));                                \
+                                                                       \
+               /* Clear register values */                             \
+               i = 32;                                                 \
+               while (i--)                                             \
+                       AVR_PUSH8(sp, 0);                               \
+                                                                       \
+               /* SREG with interrupts enabled */                      \
+               AVR_PUSH8(sp, 0x80);                                    \
+               task->sp8 = sp;                                         \
+       } while (0);
        
 #define ao_arch_save_regs() do {                                       \
                asm("push r31" "\n\t" "push r30");                      \
@@ -105,30 +106,40 @@ extern uint8_t    ao_cpu_sleep_disable;
                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();                                                  \
        } while (0)
 
 #define ao_arch_save_stack() do {                                      \
                uint8_t sp_l, sp_h;                                     \
                asm("in %0,__SP_L__" : "=&r" (sp_l) );                  \
                asm("in %0,__SP_H__" : "=&r" (sp_h) );                  \
-               ao_cur_task->sp = (uint8_t *) ((uint16_t) sp_l | ((uint16_t) sp_h << 8)); \
+               ao_cur_task->sp8 = (uint8_t *) ((uint16_t) sp_l | ((uint16_t) sp_h << 8)); \
        } while (0)
 
 #define ao_arch_isr_stack()    /* nothing */
 
-#define ao_arch_cpu_idle() do {                        \
-               if (!ao_cpu_sleep_disable)      \
+/* Idle the CPU (if possible) waiting for an interrupt. Enabling
+ * interrupts and sleeping the CPU must be adjacent to eliminate race
+ * conditions. In all cases, we execute a single nop with interrupts
+ * enabled
+ */
+#define ao_arch_wait_interrupt() do {          \
+               if (!ao_cpu_sleep_disable) {    \
+                       sleep_enable();         \
+                       sei();                  \
                        sleep_cpu();            \
+                       sleep_disable();        \
+               } else {                        \
+                       sei();                  \
+               }                               \
+               ao_arch_nop();                  \
+               cli();                          \
        } while (0)
 
 #define ao_arch_restore_stack() do { \
                uint8_t sp_l, sp_h;                                     \
-               sp_l = (uint16_t) ao_cur_task->sp;                      \
-               sp_h = ((uint16_t) ao_cur_task->sp) >> 8;               \
-               cli();                                                  \
+               sp_l = (uint16_t) ao_cur_task->sp8;                     \
+               sp_h = ((uint16_t) ao_cur_task->sp8) >> 8;              \
                asm("out __SP_H__,%0" : : "r" (sp_h) );                 \
                asm("out __SP_L__,%0" : : "r" (sp_l) );                 \
                asm("pop r0"    "\n\t"                                  \
@@ -143,16 +154,12 @@ extern uint8_t    ao_cpu_sleep_disable;
                asm("ret");                                             \
        } while(0)
 
-#define ao_arch_critical(b) do { cli(); b; sei(); } while (0)
-
-#define AO_TELESCIENCE_NUM_ADC 12
+#define ao_arch_critical(b) do { cli(); do { b } while (0); sei(); } while (0)
 
-struct ao_adc {
-       uint16_t        tick;           /* tick when the sample was read */
-       uint16_t        adc[AO_TELESCIENCE_NUM_ADC];    /* samples */
-};
+#define ao_arch_block_interrupts()     cli()
+#define ao_arch_release_interrupts()   sei()
 
-#define AO_ADC_RING    16
+#define AO_TELESCIENCE_NUM_ADC 12
 
 #endif /* _AO_ARCH_H_ */