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

📄 os.c

📁 MINI-os code,you can download !
💻 C
📖 第 1 页 / 共 3 页
字号:
		os_stkptr[os_task_curr] = stkptr + limit;
		os_task_curr--;
		if (limit)
		{
			++temp;
			++stkptr;
			asm("lds R30,_stkptr");			// Z register
			asm("lds R31, _stkptr+1");
		}
		
		while (limit--)
		{
			asm("pop r0");					// sp += 1; stack pointer move up
			asm("st Z+, r0");
		}
	}
	/*-- method 2 end --*/
	
	
	/*-- deal with task wake up event(time out, signal...) --*/
lable_task_sw_end:
	os_task_switching	= 0;

	if (os_task_stat[os_task_next].sigflag && os_task_stat[os_task_next].waitsig)
	{
		event	= EVENT_SIG;
	}
	else if (os_task_stat[os_task_next].toflag && os_task_stat[os_task_next].waitto)
	{
		OS_ENTER_CRITICAL();
		os_task_stat[os_task_next].waitto	= 0;
		os_task_stat[os_task_next].toflag	= 0;
		OS_EXIT_CRITICAL();

		event	= EVENT_TMO;
	}
	else if (os_msg_cnt[os_task_next] && os_task_stat[os_task_next].waitmsg)
	{
		event	= EVENT_MSG;
	}
	else
	{
		event	= EVENT_NONE;
	}
	/*-- deal with task wake up event end --*/
	
	
	/* restore sw stack pointer */
	temp	= os_stkptr_sw[os_task_curr];
	OS_ENTER_CRITICAL();
	asm("lds R28, _temp");
	asm("lds R29, _temp+1");
	OS_EXIT_CRITICAL();
	
	
	return event;
}

/*********************************************************************************************************
*                                            STATISTICS TASK
*
*	os_task_stat: This task is internal to Mini OS and is used to compute some statistics about the
*					multitasking environment.  Specifically, OSTaskStat() computes the CPU usage.
*					CPU usage is determined by:
*
*                                  					os_idle_ctr
*					CPU Usage (%)	= 100 * (1 - -----------------)     (units are in %)
*                                         		  os_idle_ctr_max
*
*	@param:	pdata     this pointer is not used at this time.
*
*	@return	none
*
*	Notes:	1) This task runs at a priority level higher than the idle task.  In fact, it runs at the
*				next higher priority, OS_IDLE_PRIO-1.
*			2) You can disable this task by setting the configuration #define OS_TASK_STAT_EN to 0.
*			3) We delay for 2 seconds in the beginning to allow the system to reach steady state and
*				have all other tasks created before we do statistics.  You MUST have at least a delay
*				of 2 seconds to allow for the system to establish the maximum value for the idle
*				counter.
*********************************************************************************************************/
#if OS_TASK_STAT_EN
static void os_task_statistics (void)
{
	os_wait(K_IVL, 2, 0);					// Synchronize with clock tick
	OS_ENTER_CRITICAL();
	os_idle_ctr		= 0L;					// Clear idle counter
	os_cpu_usage		= 0;
	OS_EXIT_CRITICAL();

	os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);	// Wait idle task run for 1s
	os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
	OS_ENTER_CRITICAL();
	os_idle_ctr_max	= os_idle_ctr;			// Store maximum idle counter count in 1 second
	os_idle_ctr		= 0L;
	OS_EXIT_CRITICAL();

	os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
	os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
	OS_ENTER_CRITICAL();
	os_idle_ctr		= 0L;					// Clear idle counter
	OS_EXIT_CRITICAL();

	os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
	os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
	
	while(1)
	{
		unsigned long	run;
		signed char		usage;

		OS_ENTER_CRITICAL();
		run          = os_idle_ctr;
		os_idle_ctr    = 0L;					// Reset the idle counter for the next second
		OS_EXIT_CRITICAL();

		if (os_idle_ctr_max > 0L)
		{
			usage	= (unsigned char)(100L - 100L*run/os_idle_ctr_max);
			if (usage > 100)
			{
				os_cpu_usage	= 100;
			}
			else if (usage < 0)
			{
				os_cpu_usage	= 0;
			}
			else
			{
				os_cpu_usage	= usage;
			}
		}
		else
		{
			os_cpu_usage	= 0;
		}

		os_task_stat_hook();					// Invoke user definable hook
		os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
		os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
	}
}
#endif

/*********************************************************************************************************
*                                        STATISTICS INITIALIZATION
*
*	os_statistics_init:	This function is called by your application to establish CPU usage by first determining
*					how high a 32-bit counter would count to in 1 second if no other tasks were to execute
*					during that time.  CPU usage is then determined by a low priority task which keeps track
*					of this 32-bit counter every second but this time, with other tasks running.  CPU usage is
*					determined by:
*
*												 os_idle_ctr
*					CPU Usage (%) = 100 * (1 - -----------------)
*												os_idle_ctr_max
*
*	@param: none
*
*	@return: none
*********************************************************************************************************/
#if OS_TASK_STAT_EN
static void os_statistics_init (void)
{
	os_create_task (OS_LOWEST_PRIO, os_task_statistics);	// create the 'statistics task' to calculate the CPU usage
	os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);					// delay 2s to make statistics task get 'os_idle_ctr_max'
	os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
	os_wait(K_IVL, 5, 0);
	
	os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
	os_wait(K_IVL, OS_TICKS_PER_SEC/2, 0);
}
#endif

#if 0
/*********************************************************************************************************
*                                              IDLE TASK
*
*	os_task_idle: This task is internal to Mini OS and executes whenever no other higher priority tasks
*					executes because they are waiting for event(s) to occur.
*
*	@param: none
*
*	@return: none
*********************************************************************************************************/
static void os_task_idle (void)
{
	static unsigned char	i;

	i	= 0;
	while(1)
	{
		if (os_task_stat[i].ready)
		{
			os_switch_task();	// if other higher task ready, we shall switch task
		}
		if (++i >= OS_LOWEST_PRIO)
		{
			i	= 0;
		}

		OS_ENTER_CRITICAL();
		os_idle_ctr++;
		OS_EXIT_CRITICAL();
	}
}
#endif

/**********************************************************
 *  os_init: OS startup routine, init for Mini OS. After init end, it will start with task0(main)
 *
 *  @param none
 *  @return none
 **********************************************************/
#pragma ctask	os_start
void os_start (void)
{
	extern void main(void);
	unsigned char	i;
	
	
	OS_ENTER_CRITICAL();				// interrupt disable
	
	asm("ldi R30,<_os_stack_bottom");	// initialize hw stack pointer:
	asm("ldi R31,>_os_stack_bottom");
	asm("lpm R0,Z+");
	asm("lpm R1,Z");
	asm("OUT 0x3D,R0");
	asm("OUT 0x3E,R1");
	
	asm("ldi R30,<_os_stack_top");		// initialize hw stack pointer:
	asm("ldi R31,>_os_stack_top");
	asm("lpm R28,Z+");
	asm("lpm R29,Z");
	
	asm("ldi R30,<PL_main");			// push task 0: main to hw stack
	asm("ldi R31, >PL_main");
	asm("lpm R0,Z+");
	asm("lpm R1,Z");
	asm("PUSH R0");
	asm("PUSH R1");
	if (main);							// avoid compiler err: undefined symbol 'PL_main'
	
	
	/*-- start real-time kernel --*/
	memset (os_timer, 0x00, sizeof(os_timer));
	
	memset (os_msg_cnt, 0x00, sizeof(os_msg_cnt));
	os_msg_total	= 0x00;
	
	memset (os_signal, 0x00, sizeof(os_signal));
	
	for (i = 0; i < sizeof(os_stkptr_sw)/sizeof(os_stkptr_sw[0]); i++)
	{
		os_stkptr_sw[i]	= OS_STACK_TOP-2;		// sw stack
	}
	for (i = 0; i < sizeof(os_stkptr)/sizeof(os_stkptr[0]); i++)
	{
		os_stkptr[i]	= OS_STACK_TOP;			// hw stack
	}
	os_stkptr[0]	= OS_STACK_BOTTOM;
	
	memset (os_task_stat, 0x00, sizeof(os_task_stat));
	os_task_stat[0].active	= 1;
	os_task_stat[0].ready	= 1;
	
	memset (os_task_rdy, 0x00, sizeof(os_task_rdy));
	SET_TASK_READY(0);
	
	os_task_curr		= 0x00;
	os_task_next		= 0x00;
	os_isr_sig			= 0;
	os_task_switching	= 0;
	os_time				= 0L;
	
	/* start os timer */
	//TIMER2 initialize - prescale:64
	// WGM: CTC
	// desired value: 4mSec
	// actual value:  4.016mSec (0.4%)TCCR2 = 0x00; //stop
	ASSR  = 0x00; //set async mode
	TCNT2 = 0x06; //setup
	OCR2  = OS_TICK_TIMER_VALUE;
	TCCR2 = 0x0C; //start
	
	MCUCR = 0x00;
	GICR  = 0x00;
	TIMSK = 0x80; //timer interrupt sources
	/*-- end --*/
	
	OS_EXIT_CRITICAL();
	
#if OS_TASK_STAT_EN
	os_statistics_init();
#endif
	
	asm("ret");
}

/**********************************************************
 *  os_tick: os interval timer interrupt service routine
 *
 *	@param none
 *  @return none
 **********************************************************/
static void os_tick (void)
{
	unsigned char	i;


	os_time++;

	/*-- deal with task timer out --*/
	for (i = 0; i < sizeof(os_timer)/sizeof(os_timer[0]); i++)
	{
		if (--os_timer[i] == 0)
		{
			if (os_task_stat[i].waitto)
			{
				os_isr_sig	= 1;

				os_task_stat[i].toflag	= 1;
				os_task_stat[i].ready	= 1;
				SET_TASK_READY(i);
			}
		}
	}
}

/**********************************************************
 *  os_time_isr: os timer interrupt service routine(timer A1 is used as os timer)
 *
 *  @param none
 *  @return none
 **********************************************************/
#pragma interrupt_handler os_time_isr:4
void os_time_isr(void)
{
	os_tick();

#if OS_CPU_HOOKS_EN
	{
	extern void os_time_tick_hook(void);
	os_time_tick_hook();
	}
#endif

#if OS_STK_CHK_EN
	if (!os_task_switching)
	{
		unsigned char	use;

		/* get current stack pointer value to calculate the stack usage */
		asm ld a,s;
		asm ld use,a;	// use = stack pointer;
		use	= OS_STACK_TOTAL_SZ - (use - (unsigned char)os_stkptr[os_task_curr+1]);
		os_stk_usage	= (unsigned char)(100*(unsigned int)use/(unsigned int)OS_STACK_TOTAL_SZ);
		if (os_stk_usage_max < os_stk_usage)
		{
			os_stk_usage_max	= os_stk_usage;
		}
		if (os_stk_usage_max < 0)
		{
			os_stk_usage_max	= 0;
		}
	}
#endif
}

#if OS_CPU_HOOKS_EN
/*********************************************************************************************************
*                                           TASK SWITCH HOOK
*
*	os_task_sw_hook: This function is called when a task switch is performed.  This allows you to perform other
*						operations during a context switch.
*
*	@param: none
*	@return: none
*
*********************************************************************************************************/
void os_task_sw_hook (void)
{
}

/*********************************************************************************************************
*                                           STATISTIC TASK HOOK
*
*	os_task_stat_hook: This function is called every second by Mini OS's statistics task.  This allows your
*						application to add functionality to the statistics task.
*
*	@param: none
*	@return: none
*********************************************************************************************************/
void os_task_stat_hook (void)
{
}

/*********************************************************************************************************
*                                               TICK HOOK
*
*	os_time_tick_hook: This function is called every tick.
*
*	@param: none
*	@return: none
*
*	Note(s): 1) Interrupts may or may not be ENABLED during this call.
*********************************************************************************************************/
void os_time_tick_hook (void)
{
}
#endif




/************************************************
 * @ os.c v1.0 log @
 *
 * Revision 1.0.0.0     Wanghong    2004/09/05
 * create file
 *
 * Revision 1.2.0.0     Wanghong    2005/12/17
 * added bit-mapped signal,
 * added os message,
 * added interface function for user in os_tick(),
 * optimize some code in os_task_switch().
 *
 * Revision 1.2.0.1     Wanghong    2005/12/19
 * added task timer init in os_create_task().
 *
 * Revision 1.2.0.2     Wanghong    2006/9/10
 * modified os kernel from st7 mcu to avr mega8/16 cpu
 *
 ***********************************************/

⌨️ 快捷键说明

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