⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os.c

📁 MINI-os code,you can download !
💻 C
📖 第 1 页 / 共 3 页
字号:
/*********************************************************************************************************
**												   Mini OS
**                                   The Real-Time Kernel For Avr Atmega8/16 CPU
**
**                                  (c) Copyright 2004-2004, wanghong
**                                           All Rights Reserved
**
**                                                  V1.20
**
**
** Filename: os.c
** Created by: wanghong
** Date: 2004.09.05
** Description: Mini OS for Avr Atmega8/16 CPU
**
**------------------------------------------------------------------------------------------------------
** Modified by:
** Date:
** Description:
**
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
#include "os_config.h"
#include "os.h"
#include <string.h>



OS_TASK_STATUS			os_task_stat[OS_MAX_TASK_N];		// task's state
OS_MSG	OS_MSG_MEM_TYP	os_msg_q[OS_MAX_MSG_N];				// message pool
unsigned char			os_msg_total;						// total number of messages in message pool
unsigned char			os_msg_cnt[OS_MAX_TASK_N];			// message counter of each task
SIGNAL_TYPE				os_signal[OS_MAX_TASK_N];			// bit-mapped signal of each task
unsigned char			os_task_rdy[(OS_MAX_TASK_N+7)/8];	// ready table of task list
unsigned char			os_timer[OS_MAX_TASK_N];			// task's timer
unsigned int			os_stkptr[OS_MAX_TASK_N+1];			// task's stack pointer(added 1 to fast the task switch process)
unsigned int			os_stkptr_sw[OS_MAX_TASK_N];		// task's sw stack pointer
unsigned char			os_task_curr;						// id of the current task(0~MAX_TASK_N-1)
unsigned char			os_task_next;						// id of the next task to run
unsigned char			os_isr_sig;							// flag indicates there is(are) a task(s) has been set ready by an interrupt service routine.
unsigned char			os_task_switching;					// task switching is in process

unsigned long			os_time;							// os free run timer

#if OS_TASK_STAT_EN
unsigned long			os_idle_ctr;
unsigned long			os_idle_ctr_max;
signed char				os_cpu_usage;
#endif

#if OS_STK_CHK_EN
signed char				os_stk_usage;
signed char				os_stk_usage_max;
#endif

static const unsigned char task_rdy_table[32]=
{
	0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
	0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
	0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80,
	0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80
};
#define SET_TASK_READY(task_id)	do{os_task_rdy[(task_id>>3)] |= task_rdy_table[task_id];}while(0)
#define CLR_TASK_READY(task_id)	do{os_task_rdy[(task_id>>3)] &= ~task_rdy_table[task_id];}while(0)



/**********************************************************
 *  os_create_task: starts the defined task function using
 *		the task number specified by task_id. The task is
 *		marked as ready and is ready to execute
 *
 *  @param task_id: task id
 *  @param ptask_entry: task's entry address
 *  @return 0: task create successfully,
 *			0xff: task could not be started or if no task
 *				was defined using the specified task number
 **********************************************************/
static unsigned char	*p1;
static unsigned char	*p2;
unsigned char os_create_task (unsigned char task_id, void (*task_entry)(void))
{
	unsigned char	i;
	
	
	/* judge no err with the task to create */
	if (task_id >= OS_MAX_TASK_N	||	// id err
		task_entry == NULL			||	// task not defined
		task_id == os_task_curr		||	// task already exist
		os_task_stat[task_id].active
	)
	{
		return (0xff);
	}
	
	
	/* move task entry address on the stack */
	if (os_task_curr < task_id)
	{
		i	= os_task_curr;

		while (i < task_id)
		{
			i++;
			
			p1 = (unsigned char *)os_stkptr[i];			// add stack base address
			p2	= (unsigned char *)os_stkptr[i+1];
			
			while (p1 != p2)
			{
				*(p1+2) = *p1;
				p1--;
			}

			os_stkptr[i] += 2;
		}
	}
	else if (os_task_curr > task_id)
	{
		/* adjust stack pointer, p1 = sp; sp -= 2; */
		OS_ENTER_CRITICAL();
		{
			asm("push R0");			/* save r0/r1 */
			asm("push R1");
			asm("in r0, 0x3d");		/* stack pointer(N) */
			asm("in r1, 0x3e");
			asm("sts _p1,R0");
			asm("sts _p1+1,R1");
			asm("pop R1");			/* restore r0/r1 */
			asm("pop R0");
			
			asm("push R0");			/* sp -= 2(N-2) */
			asm("push R0");
		}
		OS_EXIT_CRITICAL();
		p1	+= 2;					/* p1 = sp(N) */
		
		i	= os_task_curr;

		while (i > task_id)
		{
			p2 = (unsigned char *)os_stkptr[i] + 1;		// task stack pointer 2

			while (p1 < p2)								// move 2 bytes data down on the stack
			{
				*(p1 - 2) = *(p1);
				p1++;
			}
			p1 = (unsigned char *)os_stkptr[i] + 1;		// task stack pointer 1
			os_stkptr[i] -= 2;							// the stack pointer of task -2 for moving down 2 bytes data
			i--;
		}
	}
	
	
	/*-- task timer init, copy the entry point address
		of the task onto the stack, make task active/ready --*/
	OS_ENTER_CRITICAL();
	os_timer[task_id]	= 0;
	OS_EXIT_CRITICAL();
	*((unsigned char *)((unsigned int)(os_stkptr[task_id] - 1)))	= (unsigned char)((*(const unsigned int *)task_entry)>>8);
	*((unsigned char *)((unsigned int)(os_stkptr[task_id])))		= (unsigned char)*(const unsigned int *)task_entry;
	
	
	os_task_stat[task_id].active	= 1;
	os_task_stat[task_id].ready		= 1;
	SET_TASK_READY(task_id);
	
	return (0);
}

/**********************************************************
 *  os_wait: halts the current task and waits for one or
 *		several events such as a time interval, a time-out, a message,
 *		or a bit-mapped signal from another task or interrupt.
 *
 *  @param typ: event or events to wait for and can be any
 *				combination of the following manifest constants:
 *				(K_TMO, K_SIG, K_MSG).
 *	@param timeout: the number of timer ticks to wait for an
 *				interval event (K_IVL) or a time-out event (K_TMO).
 *	@param dummy: not used.
 *
 *  @return EVENT_SIG: A signal was received.
 *			EVENT_MSG: A message was received.
 *			EVENT_TMO: A time-out has completed or an interval
 *						has expired.
 *			NOT_OK: The value of the typ argument is invalid.
 **********************************************************/
#pragma ctask	os_wait
unsigned char os_wait (unsigned char typ, unsigned char timeout, unsigned int dummy)
{
	unsigned char	event;
	
	
	dummy	= dummy;			// prevent compiler warning.
	
	if ((typ & (K_TMO|K_IVL|K_SIG|K_MSG)) == 0)
	{
		return NOT_OK;
	}
	
	event	= 0;
	OS_ENTER_CRITICAL();
	
	/*-- 1. see if we wait for message --*/
	if (typ & K_MSG)
	{
		os_task_stat[os_task_curr].waitmsg	= 1;
	}
	else
	{
		os_task_stat[os_task_curr].waitmsg	= 0;
	}

	/*-- 2. see if we wait for bit-mapped signal --*/
	if (typ & K_SIG)
	{
		os_task_stat[os_task_curr].waitsig	= 1;
	}
	else
	{
		os_task_stat[os_task_curr].waitsig	= 0;
	}

	/*-- 3. see if we wait for a interval or time out --*/
	if ((typ & K_IVL) || (typ & K_TMO))
	{
		os_task_stat[os_task_curr].waitto	= 1;
	}
	else
	{
		os_task_stat[os_task_curr].waitto	= 0;
	}

	/*-- 4.1 see if we wait for interval timer out --*/
	if (typ & K_IVL)
	{
		unsigned char	t_sum;

		if (os_timer[os_task_curr] == 0)
		{
			goto	normal_wait_a_timeout;			// normal wait time out
		}
		
		/* if a time out happened, set a time-out event */
		t_sum	= os_timer[os_task_curr] + timeout;
		if (t_sum == 0 || (t_sum >= os_timer[os_task_curr] && t_sum >= timeout))
		{
			os_timer[os_task_curr]	= t_sum;
			event = EVENT_TMO;
		}
		/* else wait for a time-out */
		else
		{
			os_timer[os_task_curr]	= t_sum;
		}
	}
	/*-- 4.2 else see if we wait for time out --*/
	else if (typ & K_TMO)
	{
normal_wait_a_timeout:
		/* see if we really want to wait for a time out */
		os_timer[os_task_curr]	= timeout;
		if (timeout == 0)
		{
			event 		= EVENT_TMO;				// no, set time-out event
		}
	}
	
	/*-- 4.3 see if we get a time out event, return without task switch, user can reset
		the task timer by "K_TMO" with timeout=0.
		--*/
	if (event == EVENT_TMO)
	{
		/* clear wait time-out, and time-out flag */
		os_task_stat[os_task_curr].waitto	= 0;
		os_task_stat[os_task_curr].toflag	= 0;
		OS_EXIT_CRITICAL();
		
		return EVENT_TMO;
	}


	/*-- 5. clear the ready bit if we have no message and no signal waitting --*/
	if ((!os_task_stat[os_task_curr].waitmsg || os_msg_cnt[os_task_curr] == 0)	&&
		(!os_task_stat[os_task_curr].waitsig || os_signal[os_task_curr] == 0)
	)
	{
		os_task_stat[os_task_curr].ready	= 0;
		CLR_TASK_READY(os_task_curr);
	}


	OS_EXIT_CRITICAL();

	/*-- 6. perform a task switch --*/
	asm("rjmp _os_switch_task");
}

/**********************************************************
 *  isr_send_signal: sends a bit-mapped signal to task task_id. If the
 *		specified task is already waiting for a signal,	this
 *		function call readies the task for execution. Otherwise,
 *		the signal is stored in the signal flag of the task.
 *		The isr_send_signal function may be called only from interrupt service routine.
 *
 *  @param task_id: task id
 *  @param signal: bit-mapped signal
 *  @return 0: if successful,
 *			0xff: signal invalid or the specified task does not exist.
 **********************************************************/
unsigned char isr_send_signal (unsigned char task_id, SIGNAL_TYPE signal)
{
	if (OS_MAX_TASK_N <= task_id	||
		0x0000 == signal
	)
	{
		return 0xff;
	}
	
	
	os_signal[task_id]	|= signal;
	os_task_stat[task_id].sigflag	= 1;
	if (os_task_stat[task_id].waitsig)
	{
		os_task_stat[task_id].ready	= 1;
		SET_TASK_READY(task_id);
		os_isr_sig	= 1;
	}


	return 0;
}

/**********************************************************
 *  os_send_signal: sends a bit-mapped signal to task task_id. If the
 *		specified task is already waiting for a signal,	this
 *		function call readies the task for execution. Otherwise,
 *		the signal is stored in the signal flag of the task.
 *		The os_send_signal function may be called only from task functions.
 *
 *  @param task_id: task id
 *  @param signal: bit-mapped signal
 *  @return 0: if successful,
 *			0xff: signal invalid or the specified task does not exist.
 **********************************************************/
unsigned char os_send_signal (unsigned char task_id, SIGNAL_TYPE signal)
{
	if (OS_MAX_TASK_N <= task_id	||
		0x0000 == signal
	)
	{
		return 0xff;
	}


	OS_ENTER_CRITICAL();
	os_signal[task_id]	|= signal;
	os_task_stat[task_id].sigflag	= 1;
	if (os_task_stat[task_id].waitsig)
	{
		os_task_stat[task_id].ready	= 1;
		SET_TASK_READY(task_id);
	}
	OS_EXIT_CRITICAL();


	return 0;
}

/**********************************************************
 *  os_get_signal: get a bit-mapped signal of the current task.
 *		This function may be called only from task functions.
 *
 *  @param none
 *  @return: bit-mapped signal
 *			0: no signal or the specified task does not exist.
 **********************************************************/
SIGNAL_TYPE os_get_signal (void)
{
	SIGNAL_TYPE	signal;


	OS_ENTER_CRITICAL();
	signal	= os_signal[os_task_curr];				// task get itself's signal
	OS_EXIT_CRITICAL();


	return signal;
}

/**********************************************************
 *  os_clear_signal: clear a bit-mapped signal of the current task.
 *		This function may be called only from task functions.
 *
 *  @param signal: bit-mapped signal
 *  @return 0: if successful,
 *			0xff: the specified task does not exist.
 **********************************************************/
unsigned char os_clear_signal (SIGNAL_TYPE signal)
{
	OS_ENTER_CRITICAL();
	os_signal[os_task_curr]	&= ~signal;				// clear bit-mapped signal
	if (os_signal[os_task_curr] == 0x0000)
	{
		os_task_stat[os_task_curr].sigflag	= 0;	// clear task signal flag
	}
	OS_EXIT_CRITICAL();


	return 0;
}

/**********************************************************
 *  isr_send_message: send a message to a specific task.
 *		This function may be called only from interrupt service routine.
 *
 *  @param task_id: the specified task to receive the message.
 *  @param msg_data: data to be sent. msg_data lenght must be 3  bytes.
 *  @return 0: if successful,
 *			!0: error code.
 **********************************************************/
unsigned char isr_send_message (unsigned char task_id, unsigned char *msg_data)
{
	if (OS_MAX_TASK_N <= task_id	||
		os_task_stat[task_id].active == 0
	)
	{
		return ERR_MSG_GENERAL;
	}
	
	if (OS_MAX_MSG_N <= os_msg_total)
	{
		return ERR_MSG_OVF;
	}
	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -