*
* 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
*/
+#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)
#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, sp, start) \
+ do { \
+ 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"); \
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"); \
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" \
#define ao_arch_critical(b) do { cli(); do { b } while (0); sei(); } while (0)
+#define ao_arch_block_interrupts() cli()
+#define ao_arch_release_interrupts() sei()
+
#define AO_TELESCIENCE_NUM_ADC 12
#endif /* _AO_ARCH_H_ */