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

📄 ggt_cpu_c.c

📁 ARM下的多任务操作系统源码:GogotoOS
💻 C
字号:
/****************************************************************************************************
**                                        Gogoto OS
**                           (c) Copyright 2007-2008, luyigui(卢益贵)
**                                     All Rights Reserved
**                                         V1.00.0
**
**	                           狗狗兔嵌入式多任务系统(基于消息机制)    
**    					 绿城代码、GGT-OS、Gogoto OS、狗狗兔嵌入式、狗狗兔系统
**						    		 	QQ:48092788
**
**------------------文件信息------------------------------------------------------------------------
**  文件名: GGT_CPU_c.c
**  创建人: 卢益贵
**  日 期: 2007年12月8日
**  版  本: V1.00.0
**  描  述: Gogoto OS 与CPU相关的C核心代码部分,将所有移植可能与CPU和编译器相关的部分放置与此,
			方便移植。
**

**------------------修改记录------------------------------------------------------------------------
**  修改人:	卢益贵
**  版  本:	V1.00.1
**  日 期: 2008年1月5日
**  描 述: 增加OSIsrBegin和OSIsrEnd函数,考虑到CPU允许中断嵌套的可能,特为此增加这个两个函数,如果
			CPU允许中断嵌套,将GGT_CPU.h头文件的OS_INT_COUNT 定义为1即可
**
****************************************************************************************************/
																			 
#include		"GGT_OS.h"
#include		"GGT_CPU.h"
#include		"GGT_Func.h"
#include		"GGT_SysType.h"
#include		"GGT_Kernel.h"

#define T0IR           (*((volatile unsigned long *) 0xE0004000))
#define T0TCR          (*((volatile unsigned long *) 0xE0004004))
#define T0TC           (*((volatile unsigned long *) 0xE0004008))
#define T0MCR          (*((volatile unsigned long *) 0xE0004014))
#define T0MR0          (*((volatile unsigned long *) 0xE0004018))

#define VICVectAddr0   (*((volatile unsigned long *) 0xFFFFF100))
#define VICVectCntl0   (*((volatile unsigned long *) 0xFFFFF200))
#define VICIntEnable   (*((volatile unsigned long *) 0xFFFFF010))

#define VICVectAddr    (*((volatile unsigned long *) 0xFFFFF030))

#if(OS_INT_COUNT)
INT32 OSIrqCount = 0;
#endif

/****************************************************************************************************
**  函数名: OSClockIRQ
**  描  述: 系统时钟中断函数。系统时钟启动后,第一次节拍发生时,pOSTskNow等于pOSTskMain,
			从而达到把main函数设置为main任务的目的。

**  输 入: 无
**  输 出: 无
**  创建人: 卢益贵
**  日 期: 2007年12月12日

**------------------修改记录------------------------------------------------------------------------
**  修改人:	
**  版  本:	
**  日 期: 
**  描 述: 
**
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/
/*
void DelayNS(int Time) __arm
{
	// 以每个时钟周期为一个指令周期,主频为11059200 * 5:(1000000000 / (11059200 * 5)) = 18 
	// 在调用本函数时消耗两个指令:
	//__asm
	//{
	// 	Mov R0,#Time 
	// 	B   DelayNS
	//}	
	Time = (Time - 18 * 5) / (18 * 3); // 消耗两个指令,因此Time< (18 * 5 + 18 * 3 = 144)的画,都是一样的;
	while(Time--);   // 消耗三个指令(至少一个CMP指令才能退出函数,因此Time 先减少五个指令(18*5)才能进入循环)。
}
*/

void OSClockInt(void) __arm __task
{
	// 如果CPU或OS允许中断嵌套,应该在此判断是否是嵌套,是就退出
	#if(OS_INT_COUNT)
	__asm
	{
		LDR		R8, =OSIrqCount
		LDR		R8,[R8]
		CMP		R8,#0
		BEQ		SaverTaskData
	}
	T0IR = 0x01;
	VICVectAddr = 0;
	return;
	#endif
	// 保存当前任务环境
	__asm
	{
	SaverTaskData:
		STMDB	SP!,{R0-R1}
		STMDB	SP,{SP}^ 
		LDMDB	SP,{R0}
		SUB		LR,LR,#4
		STMDB	R0!,{LR}
		STMDB	R0!,{R2-R12,LR}^
		MRS		R1,SPSR
		LDMIA	SP!,{R2-R3}
		STMDB	R0!,{R1-R3}
		
		LDR     R1,=pOSTskNow
		LDR     R1,[R1]
		STR     R0,[R1,#4]
	}

	/*
	__asm
	{
	//SaverTaskData:
		STMDB	SP,{SP}^
		LDMDB	SP,{R8}
		MOV		R9,R8
		SUB		LR,LR,#4
		STMDB	R8!,{LR}
		STMDB	R8!,{LR}^
		STMDB	R8!,{R9}
		STMDB	R8!,{R0-R12}^
		MRS		R9,SPSR
		STMDB	R8!,{R9}
		
		LDR     R1,=pOSTskNow
		LDR     R1,[R1]
		STR     R0,[R1,#4]
	}
	*/

	//进行任务调度
	OSTaskDispatch();

	//定时器计数
	OSTimerCheck();

	//中断结束
	T0IR = 0x01;
	VICVectAddr = 0;

	//就绪任务出列,并加载执行
	__asm
	{
		LDR		R4,=pOSTskNow		;当前任务变量地址
		LDR		R3,=pOSTskReady		;就绪任务变量地址
		MOV		R5, R3				;保存就绪任务变量地址
		LDR		R3,[R3]				;R3=就绪任务数据区地址
		STR		R3,[R4]				;pOSTskNow = pOSTskReady
		LDR		R3,[R3]				;R3=pOSTskReady-pNext
		STR		R3,[R5]				;pOSTskReady = pOSTskReady-pNext

		LDR     R4,[R4]
		LDR     LR,[R4,#4]
		LDMIA	LR!,{R2}
		MSR		SPSR_cxsf,R2
		ADD		R0,LR,#60
		STMDB	SP,{R0}
		LDMDB	SP,{SP}^
		LDMIA	LR!,{R0-R12,LR}^
		LDMIA	LR!,{LR}
		MOVS	PC, LR
	}

	/*
	__asm
	{
		LDR		R8,=pOSTskNow		;当前任务变量地址
		LDR		R9,=pOSTskReady		;就绪任务变量地址
		MOV		R10, R9				;保存就绪任务变量地址
		LDR		R9,[R9]				;R3=就绪任务数据区地址
		STR		R9,[R8]				;pOSTskNow = pOSTskReady
		LDR		R9,[R9]				;R3=pOSTskReady-pNext
		STR		R9,[R10]			;pOSTskReady = pOSTskReady-pNext

		LDR     R8,[R8]
		LDR     R8,[R8,#4]
		LDMIA	R8!,{R9}
		MSR		SPSR_cxsf,R9
		LDMIA	R8!,{R0-R12,SP,LR,PC}^
	}
	*/
}

/****************************************************************************************************
**  函数名: OSClockInit
**  描  述: 打开系统节拍时钟
**  输 入: 无
**  输 出: 无
**  创建人: 卢益贵
**  日 期: 2007年12月8日

**------------------修改记录------------------------------------------------------------------------
**  修改人: 
**  日 期:
**  说  明:
**  原代码:
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/
void OSClockInit(void)
{
	T0IR = 1;
    T0TC = 0;
	T0TCR = 0x01;
	T0MCR = 0x03;
	T0MR0 = OSGetFPCLK() / OSGetTick();
	VICVectAddr0  = (UINT32)OSClockInt;
	VICVectCntl0  = 0x20 | 4;
	VICIntEnable  |= (1 << 4);
}

/****************************************************************************************************
**  函数名: OSStackAlloc
**  描  述: 分配任务堆栈的函数
**  输 入: 无
**  输 出: 返回堆栈地址
**  创建人: 卢益贵
**  日 期: 2007年12月8日

**------------------修改记录------------------------------------------------------------------------
**  修改人: 
**  日 期:
**  说  明:
**  原代码:
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/
UINT32* OSStackAlloc(void)
{
	// 满降序堆栈
	return((UINT32*)(((UINT32)BoxAlloc(OSGetBoxStack())) + OSGetSizeStack()));
}

/****************************************************************************************************
**  函数名: OSStackInit
**  描  述: 初始化任务堆栈
**  输 入: 无
**  输 出: 返回堆栈地址
**  创建人: 卢益贵
**  日 期: 2007年12月8日

**------------------修改记录------------------------------------------------------------------------
**  修改人: 
**  日 期:
**  说  明:
**  原代码:
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/
UINT32* OSStackInit(void *pTaskBody, UINT32 *pStack, UINT32 Mode, UINT32 TaskParam)
{
	// 满降序堆栈
	*--pStack = (UINT32 *)pTaskBody;           /*  pc  */
	*--pStack = (UINT32 *)pTaskBody; 		   /*  lr  */
    *--pStack = 0;                             /*  r12  */
    *--pStack = 0;                             /*  r11  */
    *--pStack = 0;                             /*  r10  */
    *--pStack = 0;                             /*  r9   */
    *--pStack = 0;                             /*  r8   */
    *--pStack = 0;                             /*  r7   */
    *--pStack = 0;                             /*  r6   */
    *--pStack = 0;                             /*  r5   */
    *--pStack = 0;                             /*  r4   */
    *--pStack = 0;                             /*  r3   */
    *--pStack = 0;                             /*  r2   */
	*--pStack = 0;       						/*  r1   */
	*--pStack = TaskParam;        				/*  r0   */
	*--pStack = Mode;
    return(pStack);
}

/****************************************************************************************************
**  函数名: main
**  描  述: C语言函数入口,
**  输 入: 无
**  输 出: 无
**  创建人: 卢益贵
**  日 期: 2007年12月8日

**------------------修改记录------------------------------------------------------------------------
**  修改人: 卢益贵
**  日 期: 2008年1月10日
**  说  明:
**  原代码:
void main(void)	 __arm __task
{
	// 初始化任务系统
	OSTaskInit();

	// 设置main函数为当前任务,移植时应注意修改这个部分
	pOSTskMain->pTskStack -= 10;       // 指向空栈
	__asm
	{
		LDR     R4,=pOSTskMain		// mian任务变量地址
		LDR     R4,[R4, #0]			// main任务数据区地址
        LDR     R4,[R4, #4]			// R4=堆栈指针
		MOV		SP, R4			    // 把SP指向main任务堆栈区,
	}
	

	// 打开系统节拍时钟
	OSClockInit();	

	// 调用用户主函数,初始化用户系统
	umain();

	// 把main任务权限设置为无穷大,将进行永久等待
	pOSTskMain->PrioTick = 1000 * 90000;
	while(1)
	{
		// 把main任务设置为永远延时任务
		pOSTskMain->StateValue = 1000 * 90000;
		// CPU休眠
		(PCON = PCON | 0x01);
	}
}
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/

//用户主任务
extern void TaskUasrMain(void) __task;

#define PCON           (*((volatile unsigned char *) 0xE01FC0C0))
#define IOPIN          (*((volatile unsigned long *) 0xE0028000))

void main(void)	 __arm __task
{
	// 初始化任务系统
	OSInit();

	// 设置main函数为当前任务,移植时应注意修改这个部分
	pOSTskMain->pTskStack -= 10;       // 指向空栈
	__asm
	{
		LDR     R4,=pOSTskMain		// mian任务变量地址
		LDR     R4,[R4, #0]			// main任务数据区地址
        LDR     R4,[R4, #4]			// R4=堆栈指针
		STR		SP, [R4]		    // 把SP指向main任务堆栈区,
	}

	// 如果不想

	// 打开系统节拍时钟
	OSClockInit();

	// 创建用户主任务(必须等系统初始化完了以后才能创建)
	OSTaskCreate(TaskUasrMain, 0, 255);

	// 把main任务权限设置为无穷大,将进行永久等待
	pOSTskMain->PrioTick = 1000 * 90000;
	while(1)
	{
		// 把main任务设置为永远延时任务
		pOSTskMain->StateValue = 1000 * 90000;
		// CPU休眠
		(PCON = PCON | 0x01);
	}
}

/****************************************************************************************************
**  函数名: OSTaskCreate
**  描  述: 创建默认模式的用户任务
**  输 入: 无
**  输 出: 无
**  创建人: 卢益贵
**  日 期: 2007年12月8日

**------------------修改记录------------------------------------------------------------------------
**  修改人: 
**  日 期:
**  说  明:
**  原代码:
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/
UINT32 OSTaskCreate(void *pTaskBody, const UINT32 Prio, const UINT32 TaskParam)
{
	return(OSTaskUserCreate(pTaskBody, Prio, USR32MODE, TaskParam));
}

/****************************************************************************************************
**  函数名: OSIsrBegin
**  描  述: 中断服务开始,对中断嵌套计数,中断函数第一条语句为调用该函数。
**  输 入: 无
**  输 出: 无
**  创建人: 卢益贵
**  日 期: 2008年1月5日

**------------------修改记录------------------------------------------------------------------------
**  修改人: 
**  日 期:
**  说  明:
**  原代码:
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/
void OSIsrBegin(void)
{
	#if(OS_INT_COUNT)
	OSIrqCount++;
	#endif
}

/****************************************************************************************************
**  函数名: OSIsrEnd
**  描  述: 中断服务结束,对中断嵌套计数,如果有任务要处理中断数据,中断函数的最后语句为调用本函数,
			系统立即切换任务,本函数在CPU未允许中断嵌套的情况,OS_INT_COUNT定义为0时,
			只执行任务切换功能。
**  输 入: IsSW:1为立即切换任务,其他未定义
**  输 出: 无
**  创建人: 卢益贵
**  日 期: 2008年1月5日

**------------------修改记录------------------------------------------------------------------------
**  修改人: 
**  日 期:
**  说  明:
**  原代码:
**--------------------------------------------------------------------------------------------------
****************************************************************************************************/
void OSIsrEnd(BOOL DoSW)
{
	#if(OS_INT_COUNT)
	if(OSIrqCount)
		OSIrqCount++;
	#endif

	//立即切换任务
	if(DoSW)
	{
		OSTaskIsNULLLoadDef();
		OSTaskSW();
	}
}

⌨️ 快捷键说明

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