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

📄 test.c

📁 改程序是ucos-ii在meg16上的移植
💻 C
📖 第 1 页 / 共 2 页
字号:
/************************************************************************************************************************
*										test.c
*
*
*
************************************************************************************************************************/
#include "RTOS.h"



/************************************************************************************************************************
函数名称:	OSTaskCreate
函数原型:	void OSTaskCreate(void (*Task)(void),Uint_8bit *Stack,Uint_8bit TaskID)
函数功能:	建立任务 
入口参数:	*Task:任务函数地址;*Stack:任务堆栈指针;TaskID:任务优先级
出口参数:	无
有关说明:	
创建时间:	2007年3月3日
修改时间:	
************************************************************************************************************************/
void OSTaskCreate(void (*Task)(void),Uint_8bit *Stack,Uint_8bit TaskID)
{
	Uint_8bit i;
	*Stack--=(Uint_16bit)Task;				/*将任务的地址低位压入堆栈		*/
	*Stack--=(Uint_16bit)Task>>8;			/*将任务的地址高位压入堆栈		*/

	*Stack--=0x00;							/*R1 __zero_reg__				*/
	*Stack--=0x00;							/*R0 __tmp_reg__				*/
	*Stack--=0x80;							/*SREG 在任务中,开启全局中断	*/
	for(i=0;i<14;i++)
    *Stack--=i;
	/*
		在 avr-libc 中的 FAQ中的 What registers are used by the C compiler?
		描述了寄存器的作用
	*/
	TCB[TaskID].OSTaskStackTop = (Uint_16bit)Stack;
	/*
		将人工堆栈的栈顶,保存到堆栈的数组中
	*/
	OSRdyTbl |= 0x01<<TaskID;      			/*任务就绪表已经准备好			*/
}

/************************************************************************************************************************
函数名称:	OSStartTask
函数原型:	void OSStartTask(void)
函数功能:	开始任务调度,从空闲任务开始运行 
入口参数:	无
出口参数:	无
有关说明:	执行"reti"指令之后打开全局中断
创建时间:	2007年3月3日
修改时间:	
************************************************************************************************************************/
void OSStartTask(void)
{
	OSPrioCur = OS_TASKS;
	OSPrioHighRdy = OS_TASKS;
	SP=TCB[OS_TASKS].OSTaskStackTop+17;
	__asm__ __volatile__(    "reti"       "\n\t"  );
}

/************************************************************************************************************************
函数名称:	OS_TASK_SW
函数原型:	void OS_TASK_SW(void)
函数功能:	进行任务调度 
入口参数:	无
出口参数:	无
有关说明:	中断和任务都可以调用这个任务调度函数
创建时间:	2007年3月3日
修改时间:	
************************************************************************************************************************/
void OS_TASK_SW(void)
{

	__asm__ __volatile__("LDI  R16,0x01             \n\t");
	/*
		清除中断要求任务切换的标志位,设置正在任务切换标志位
	*/
	__asm__ __volatile__("SEI                       \n\t");
	/*
		开中断,因为如果因中断在任务调度中进行,要重新进行调度时,已经关中断
	*/
	/*  根据中断时保存寄存器的次序入栈,模拟一次中断后,入栈的情况*/
	__asm__ __volatile__("PUSH __zero_reg__         \n\t");	/*R1 					*/
	__asm__ __volatile__("PUSH __tmp_reg__          \n\t");	/*R0					*/
	__asm__ __volatile__("IN   __tmp_reg__,__SREG__ \n\t");	/*保存状态寄存器SREG	*/
	__asm__ __volatile__("PUSH __tmp_reg__          \n\t"); 
	__asm__ __volatile__("CLR  __zero_reg__         \n\t");	/*R0重新清零			*/
	__asm__ __volatile__("PUSH R18                  \n\t");
	__asm__ __volatile__("PUSH R19                  \n\t");
	__asm__ __volatile__("PUSH R20                  \n\t");
	__asm__ __volatile__("PUSH R21                  \n\t");
	__asm__ __volatile__("PUSH R22                  \n\t");
	__asm__ __volatile__("PUSH R23                  \n\t");
	__asm__ __volatile__("PUSH R24                  \n\t");
	__asm__ __volatile__("PUSH R25                  \n\t");
	__asm__ __volatile__("PUSH R26                  \n\t");
	__asm__ __volatile__("PUSH R27                  \n\t");
	__asm__ __volatile__("PUSH R30                  \n\t");  
	__asm__ __volatile__("PUSH R31                  \n\t");
	
	__asm__ __volatile__("Int_OSSched:              \n\t");	/*当中断要求调度,直接进入这里		*/ 
	__asm__ __volatile__("SEI                       \n\t");
	/*
		开中断,因为如果因中断在任务调度中进行,已经关中断
	*/
	__asm__ __volatile__("PUSH R28                  \n\t");	/*R28与R29用于建立在堆栈上的指针	*/
	__asm__ __volatile__("PUSH R29                  \n\t");	/*入栈完成							*/
	
	TCB[OSPrioCur].OSTaskStackTop=SP;					/*将正在运行的任务的堆栈底保存		*/
	
	OSPrioCur = OSPrioHighRdy ;							/*运行当前就绪表中的最高优先级任务	*/
	
	cli();												/*保护堆栈转换,属于临界代码,要保护	*/
	SP=TCB[OSPrioCur].OSTaskStackTop;
	sei();
	
	/*根据中断时的出栈次序*/
	__asm__ __volatile__("POP  R29                  \n\t");
	__asm__ __volatile__("POP  R28                  \n\t");
	__asm__ __volatile__("POP  R31                  \n\t");
	__asm__ __volatile__("POP  R30                  \n\t");
	__asm__ __volatile__("POP  R27                  \n\t");
	__asm__ __volatile__("POP  R26                  \n\t");
	__asm__ __volatile__("POP  R25                  \n\t");
	__asm__ __volatile__("POP  R24                  \n\t");
	__asm__ __volatile__("POP  R23                  \n\t");
	__asm__ __volatile__("POP  R22                  \n\t");
	__asm__ __volatile__("POP  R21                  \n\t");
	__asm__ __volatile__("POP  R20                  \n\t");
	__asm__ __volatile__("POP  R19                  \n\t");
	__asm__ __volatile__("POP  R18                  \n\t");
	__asm__ __volatile__("POP  __tmp_reg__          \n\t");		/*SERG 出栈并恢复	*/
	__asm__ __volatile__("OUT  __SREG__,__tmp_reg__ \n\t");
	__asm__ __volatile__("POP  __tmp_reg__          \n\t");		/*R0 出栈			*/
	__asm__ __volatile__("POP  __zero_reg__         \n\t");		/*R1 出栈			*/
	/*中断时出栈完成*/
	__asm__ __volatile__("CLI                       \n\t");		/*关中断			*/
	__asm__ __volatile__("SBRC R16,1                \n\t");
	/*
		SBRC当寄存器位为0则跳过下一条指令
		检查系统正在进行任务调度时,是否有中断发生并进行要求任务调度,
		如果中断要求调度则重新进行一次任务调度。
		0x02是中断要求调度的标志位
	*/
	__asm__ __volatile__("RJMP OSSched              \n\t");		/*重新调度			*/
	__asm__ __volatile__("LDI  R16,0x00             \n\t");
	/*
		清除中断要求任务切换的标志位,清除正在任务切换标志位,
		表示任务切换已经完成。
	*/
	__asm__ __volatile__("RETI                      \n\t");     /*返回并开中断		*/
}

/************************************************************************************************************************
函数名称:	IntSwitch
函数原型:	void IntSwitch(void)
函数功能:	从中断退出并进行调度
入口参数:	无
出口参数:	无
有关说明:	当无中断嵌套并且中断中要求进行任务切换时才进行任务切换。
*			因为从中断到运行下一个任务共调用了两次子函数,所以要弹出四个入栈的PC
创建时间:	2007年3月3日
修改时间:	
************************************************************************************************************************/
void IntSwitch(void)
{
	if((OSCoreState == 0x02) && (OSIntNesting == 0))
	{
		/*
			进入中断时,已经保存了SREG和R0,R1,R18~R27,R30,R31,
			所以没有必要再保存一次了,直接跳转到Int_OSSched进行下一个调度
		*/
		__asm__ __volatile__("POP  R31                  \n\t");	/*去除因调用子程序而入栈的PC*/
		__asm__ __volatile__("POP  R31                  \n\t");
		__asm__ __volatile__("POP  R31                  \n\t");
		__asm__ __volatile__("POP  R31                  \n\t");
		__asm__ __volatile__("LDI  R16,0x01             \n\t");
		/*
			清除中断要求任务切换的标志位,设置正在任务切换标志位 
		*/
		__asm__ __volatile__("RJMP Int_OSSched          \n\t");	/*重新调度					*/
	}
}

/************************************************************************************************************************
函数名称:	OSSched
函数原型:	void OSSched(void)
函数功能:	任务调度器,进行任务调度
入口参数:	无
出口参数:	无
有关说明:	只有有更高优先级的任务就绪时才进行一次任务切换,否则不做切换
创建时间:	2007年3月7日
修改时间:	
************************************************************************************************************************/
void OSSched (void)
{
	OSFindPrioHighRdy();						/*找出就绪表中优先级最高的任务*/
	if(OSPrioHighRdy != OSPrioCur)				/*如果不是当前运行的任务,进行任务调度*/
	{
		OS_TASK_SW();							/*调度任务*/
	}
}
/************************************************************************************************************************
函数名称:	OSTaskSuspend
函数原型:	void OSTaskSuspend(Uint_8bit prio)
函数功能:	挂起任务 
入口参数:	prio:任务优先级
出口参数:	无
有关说明:	一个任务可以挂起本身也可以挂起其他任务
创建时间:	2007年3月3日
修改时间:	
************************************************************************************************************************/
void OSTaskSuspend(Uint_8bit prio)
{
	OS_ENTER_CRITICAL();
	TCB[prio].OSWaitTick=0;
	OSRdyTbl &= ~(0x01<<prio);		/*从任务就绪表上去除标志位	*/
	if(OSPrioCur == prio)			/*当要挂起的任务为当前任务	*/
	{
		OS_EXIT_CRITICAL();
		OSSched();					/*重新调度					*/
		return;
	}
	OS_EXIT_CRITICAL();
}

/************************************************************************************************************************
函数名称:	OSTaskResume
函数原型:	void OSTaskResume(Uint_8bit prio)
函数功能:	恢复任务 可以让被OSTaskSuspend或 OSTimeDly暂停的任务恢复 
入口参数:	prio:任务优先级
出口参数:	无
有关说明:	
创建时间:	2007年3月3日
修改时间:	
************************************************************************************************************************/
void OSTaskResume(Uint_8bit prio)
{
	OS_ENTER_CRITICAL();
	OSRdyTbl |= 0x01<<prio;			/*从任务就绪表上重置标志位	*/
    TCB[prio].OSWaitTick=0;			/*将时间计时设为0,到时		*/
	if(OSPrioCur > prio)			/*当要当前任务的优先级低于重置位的任务的优先级	*/
	{
		OS_EXIT_CRITICAL();
		OSSched();					/*重新调度					*/
		return;
	}
	OS_EXIT_CRITICAL();
}

/************************************************************************************************************************
函数名称:	OSTimeDly
函数原型:	void OSTimeDly(Uint_16bit ticks)
函数功能:	任务延时 
入口参数:	延时的时间,任务时钟的个数
出口参数:	无
有关说明:	如果延时65535(0xffff)则为无限延时
创建时间:	2007年3月3日
修改时间:	
************************************************************************************************************************/
void OSTimeDly(Uint_16bit ticks)
{
	if(ticks)                             	/*当延时有效 */
	{
		OS_ENTER_CRITICAL();
		OSRdyTbl &= ~(0x01<<OSPrioCur);	/*把任务从就绪表中去掉*/
		TCB[OSPrioCur].OSWaitTick=ticks;
		OS_EXIT_CRITICAL();
		OSSched();                          /*重新调度	*/
	}
}

/************************************************************************************************************************
函数名称:	OSSemCreat
函数原型:	void OSSemCreat(Uint_8bit Index,Uint_8bit Type)
函数功能:	初始化信号量 
入口参数:	Index:信号量的序号;Type:信号量类型
出口参数:	无
有关说明:	Type为 0 信号量独占型;1 信号量共享型
创建时间:	2007年3月3日
修改时间:	
************************************************************************************************************************/
void OSSemCreat(Uint_8bit Index,Uint_8bit Type)
{
	Sem[Index].OSEventType=Type;
	Sem[Index].OSTaskPendTbl=0;				/*初始化时任务等待列表为空*/
	Sem[Index].OSEventState=0;				/*信号量无效*/
}

/************************************************************************************************************************
函数名称:	OSTaskSemPend
函数原型:	Uint_8bit OSTaskSemPend(Uint_8bit Index,Uint_16bit Timeout) 
函数功能:	任务等待信号量,挂起 
入口参数:	Index:信号量序号;Timeout:等待时间
出口参数:	无
有关说明:	当Timeout==0xffff时,为无限等待
创建时间:	2007年3月3日
修改时间:	
************************************************************************************************************************/
Uint_8bit OSTaskSemPend(Uint_8bit Index,Uint_16bit Timeout)
{
	if(Sem[Index].OSEventState)							/*信号量有效	*/
	{
		if(Sem[Index].OSEventType == 0)				/*如果为独占型	*/
		{
			Sem[Index].OSEventState = 0x00;				/*信号量被独占,不可用*/
		}
	}
	else
	{                              						/*加入信号的任务等待表*/
		OS_ENTER_CRITICAL();
		Sem[Index].OSTaskPendTbl |= 0x01<<OSPrioCur;
		TCB[OSPrioCur].OSWaitTick = Timeout;			/*定义等待超时			*/
		OSRdyTbl &= ~(0x01<<OSPrioCur);				/*从任务就绪表中去除	*/
		OS_EXIT_CRITICAL();
		OSSched();   									/*重新调度				*/
		if(TCB[OSPrioCur].OSWaitTick==0 )				/*超时,未能拿到资源	*/
		{
			return 0;
		}
	}
	return 1;
}

/************************************************************************************************************************
函数名称:	OSSemPost
函数原型:	void OSSemPost(Uint_8bit Index) 
函数功能:	发送一个信号量,可以从任务或中断发送,
*			发送完了信号量之后不进行任务调度,推荐在中断中调用
入口参数:	Index:信号量的序号
出口参数:	无
有关说明:	如果有任务在等待该信号量则将该任务就绪,没有任务等待则仅仅是把信号量置为有效
创建时间:	2007年3月3日

⌨️ 快捷键说明

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