diff options
Diffstat (limited to 'src/ao_task.c')
| -rw-r--r-- | src/ao_task.c | 224 | 
1 files changed, 0 insertions, 224 deletions
| diff --git a/src/ao_task.c b/src/ao_task.c deleted file mode 100644 index 12b73943..00000000 --- a/src/ao_task.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright © 2009 Keith Packard <keithp@keithp.com> - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -#define AO_NO_TASK_INDEX	0xff - -__xdata struct ao_task * __xdata ao_tasks[AO_NUM_TASKS]; -__data uint8_t ao_num_tasks; -__data uint8_t ao_cur_task_index; -__xdata struct ao_task *__data ao_cur_task; - -void -ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant -{ -	uint8_t	__xdata *stack; -	if (ao_num_tasks == AO_NUM_TASKS) -		ao_panic(AO_PANIC_NO_TASK); -	ao_tasks[ao_num_tasks++] = task; -	task->task_id = ao_num_tasks; -	task->name = name; -	/* -	 * Construct a stack frame so that it will 'return' -	 * to the start of the task -	 */ -	stack = task->stack; - -	*stack++ = ((uint16_t) start); -	*stack++ = ((uint16_t) start) >> 8; - -	/* 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; -	task->wchan = NULL; -} - -/* Task switching function. This must not use any stack variables */ -void -ao_yield(void) _naked -{ - -	/* Save current context */ -	_asm -		/* Push ACC first, as when restoring the context it must be restored -		 * last (it is used to set the IE register). */ -		push	ACC -		/* Store the IE register then enable interrupts. */ -		push	_IEN0 -		setb	_EA -		push	DPL -		push	DPH -		push	b -		push	ar2 -		push	ar3 -		push	ar4 -		push	ar5 -		push	ar6 -		push	ar7 -		push	ar0 -		push	ar1 -		push	PSW -	_endasm; -	PSW = 0; -	_asm -		push	_bp -	_endasm; - -	if (ao_cur_task_index != AO_NO_TASK_INDEX) -	{ -		uint8_t stack_len; -		__data uint8_t *stack_ptr; -		__xdata uint8_t *save_ptr; -		/* Save the current stack */ -		stack_len = SP - (AO_STACK_START - 1); -		ao_cur_task->stack_count = stack_len; -		stack_ptr = (uint8_t __data *) AO_STACK_START; -		save_ptr = (uint8_t __xdata *) ao_cur_task->stack; -		do -			*save_ptr++ = *stack_ptr++; -		while (--stack_len); -	} - -	/* Empty the stack; might as well let interrupts have the whole thing */ -	SP = AO_STACK_START - 1; - -	/* 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; -		for (;;) { -			++ao_next_task_index; -			if (ao_next_task_index == ao_num_tasks) -				ao_next_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; -				break; -			} - -			/* Enter lower power mode when there isn't anything to do */ -			if (ao_next_task_index == ao_cur_task_index) -				PCON = PCON_IDLE; -		} -	} - -	{ -		uint8_t stack_len; -		__data uint8_t *stack_ptr; -		__xdata uint8_t *save_ptr; - -		/* Restore the old stack */ -		stack_len = ao_cur_task->stack_count; -		SP = AO_STACK_START - 1 + stack_len; - -		stack_ptr = (uint8_t __data *) AO_STACK_START; -		save_ptr = (uint8_t __xdata *) ao_cur_task->stack; -		do -			*stack_ptr++ = *save_ptr++; -		while (--stack_len); -	} - -	_asm -		pop		_bp -		pop		PSW -		pop		ar1 -		pop		ar0 -		pop		ar7 -		pop		ar6 -		pop		ar5 -		pop		ar4 -		pop		ar3 -		pop		ar2 -		pop		b -		pop		DPH -		pop		DPL -		/* The next byte of the stack is the IE register.  Only the global -		enable bit forms part of the task context.  Pop off the IE then set -		the global enable bit to match that of the stored IE register. */ -		pop		ACC -		JB		ACC.7,0098$ -		CLR		_EA -		LJMP	0099$ -	0098$: -		SETB		_EA -	0099$: -		/* Finally pop off the ACC, which was the first register saved. */ -		pop		ACC -		ret -	_endasm; -} - -void -ao_sleep(__xdata void *wchan) -{ -	__critical { -		ao_cur_task->wchan = wchan; -	} -	ao_yield(); -} - -void -ao_wakeup(__xdata void *wchan) -{ -	uint8_t	i; - -	for (i = 0; i < ao_num_tasks; i++) -		if (ao_tasks[i]->wchan == wchan) -			ao_tasks[i]->wchan = NULL; -} - -void -ao_task_info(void) -{ -	uint8_t	i; -	uint8_t pc_loc; -	__xdata struct ao_task *task; - -	for (i = 0; i < ao_num_tasks; i++) { -		task = ao_tasks[i]; -		pc_loc = task->stack_count - 17; -		printf("%12s: wchan %04x pc %04x\n", -		       task->name, -		       (int16_t) task->wchan, -		       (task->stack[pc_loc]) | (task->stack[pc_loc+1] << 8)); -	} -} - -void -ao_start_scheduler(void) -{ -	ao_cur_task_index = AO_NO_TASK_INDEX; -	ao_cur_task = NULL; -	ao_yield(); -} | 
