Created
February 11, 2012 12:57
-
-
Save iskl/1799295 to your computer and use it in GitHub Desktop.
ARM9上运行的微型操作系统
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//------------------------------------------------------------------------- | |
// 文件名:RTOS.C | |
// 功能: ARM9上运行的微型操作系统 | |
// 备注: 抢占式任务调度,运行时间可预测,提供延时,挂起,恢复任务操作 | |
// 未加入信号量邮箱等同步通信机制 | |
// | |
// By Lisuwei | |
//------------------------------------------------------------------------- | |
#define CPP_GLOBALS | |
#include "Includes.h" | |
/************************************************************************************************************************ | |
函数名称: OSTaskCreate | |
函数原型: void OSTaskCreate(void (*Task)(void),INT32U *Stack,INT8U TaskID) | |
函数功能: 建立任务 | |
入口参数: *Task:任务函数地址;*Stack:任务栈顶指针;TaskID:任务优先级 | |
出口参数: 无 | |
有关说明: 初始化任务堆栈,任务控制块TCB和在置位表上登记就绪 | |
************************************************************************************************************************/ | |
void OSTaskCreate(void (*Task)(void),INT32U *p_Stack,INT8U TaskID) | |
{ | |
if(TaskID <= OS_TASKS) | |
{ | |
*(p_Stack) = (INT32U)Task; /* 将任务的地址压入堆栈,满栈减,先减再赋值 !! */ | |
*(--p_Stack) = (INT32U)13; /* lr */ | |
*(--p_Stack) = (INT32U)12; /* r12 */ | |
*(--p_Stack) = (INT32U)11; /* r11 */ | |
*(--p_Stack) = (INT32U)10; /* r10 */ | |
*(--p_Stack) = (INT32U)9; /* r9 */ | |
*(--p_Stack) = (INT32U)8; /* r8 */ | |
*(--p_Stack) = (INT32U)7; /* r7 */ | |
*(--p_Stack) = (INT32U)6; /* r6 */ | |
*(--p_Stack) = (INT32U)5; /* r5 */ | |
*(--p_Stack) = (INT32U)4; /* r4 */ | |
*(--p_Stack) = (INT32U)3; /* r3 */ | |
*(--p_Stack) = (INT32U)2; /* r2 */ | |
*(--p_Stack) = (INT32U)1; /* r1 */ | |
*(--p_Stack) = (INT32U)0; /* r0 */ | |
*(--p_Stack) = (INT32U)(SVCMODE|0x0); /* SREG 保存在任务栈中 */ | |
TCB[TaskID].OSTCBStkPtr = (INT32U)p_Stack; /* 将人工堆栈的栈顶,保存到堆栈的数组中*/ | |
TCB[TaskID].OSTCBDly = 0; /* 初始化任务延时 */ | |
OSSetPrioRdy(TaskID); /* 在任务就绪表中登记 */ | |
} | |
else | |
{ | |
Uart_Printf("TaskID Error\n"); | |
while(1); | |
} | |
} | |
/************************************************************************************************************************ | |
函数名称: OSStart | |
函数原型: void OSStart(void) | |
函数功能: 开始任务调度,从最高优先级任务开始运行 | |
入口参数: 无 | |
出口参数: 无 | |
有关说明: 找出优先级最高的就绪任务运行 | |
************************************************************************************************************************/ | |
void OSStart(void) | |
{ | |
OSGetHighRdy(); | |
p_OSTCBHighRdy = &TCB[OSPrioHighRdy]; /* 在汇编中需引用任务的TCB地址取得栈顶指针,所以在任务切换前,OSTCBHighRdy必须指向优先级最高的那个任务控制块TCB */ | |
OSPrioCur = OSPrioHighRdy; /* 在就绪表中查找最高级的就绪任务 */ | |
OSStartHighRdy(); /* 系统第一个运行的任务出栈 */ | |
} | |
/************************************************************************************************************************ | |
函数名称: OSSched | |
函数原型: void OSSched(void) | |
函数功能: 任务调度器,进行任务调度 | |
入口参数: 无 | |
出口参数: 无 | |
有关说明: 只有有更高优先级的任务就绪时才进行一次任务切换,否则不做切换 | |
************************************************************************************************************************/ | |
void OSSched (void) | |
{ | |
OS_ENTER_CRITICAL(); | |
OSGetHighRdy(); /* 找出就绪表中优先级最高的任务 */ | |
if(OSPrioHighRdy != OSPrioCur) /* 如果不是当前运行的任务,进行任务调度 */ | |
{ | |
p_OSTCBCur = &TCB[OSPrioCur]; /* 目的是在汇编中引用任务的TCB地址取得栈顶指针 */ | |
p_OSTCBHighRdy = &TCB[OSPrioHighRdy]; | |
OSPrioCur = OSPrioHighRdy; /* 更新OSPrioCur */ | |
OS_TASK_SW(); /* 调度任务 */ | |
} | |
OS_EXIT_CRITICAL(); | |
} | |
/************************************************************************************************************************ | |
函数名称: OSTaskSuspend | |
函数原型: void OSTaskSuspend(INT8U prio) | |
函数功能: 挂起任务 | |
入口参数: prio:任务的优先级 | |
出口参数: 无 | |
有关说明: 一个任务可以挂起本身也可以挂起其他任务 | |
************************************************************************************************************************/ | |
void OSTaskSuspend(INT8U prio) | |
{ | |
OS_ENTER_CRITICAL(); | |
TCB[prio].OSTCBDly = 0; | |
OSDelPrioRdy(prio); /* 从任务就绪表上去除标志位 */ | |
OS_EXIT_CRITICAL(); | |
if(OSPrioCur == prio) /* 当要挂起的任务为当前任务 */ | |
{ | |
OSSched(); /* 重新调度 */ | |
} | |
} | |
/************************************************************************************************************************ | |
函数名称: OSTaskResume | |
函数原型: void OSTaskResume(INT8U prio) | |
函数功能: 恢复任务 可以让被OSTaskSuspend 或 OSTimeDly挂起的任务恢复 | |
入口参数: prio:任务的优先级 | |
出口参数: 无 | |
有关说明: | |
************************************************************************************************************************/ | |
void OSTaskResume(INT8U prio) | |
{ | |
OS_ENTER_CRITICAL(); | |
OSSetPrioRdy(prio); /* 从任务就绪表上重置标志位 */ | |
TCB[prio].OSTCBDly = 0; /* 将时间计时设为0,延时到 */ | |
OS_EXIT_CRITICAL(); | |
if(OSPrioCur > prio) /* 当前任务的优先级低于重置位的任务的优先级 */ | |
{ | |
OSSched(); /* 重新调度 */ | |
} | |
} | |
/************************************************************************************************************************ | |
函数名称: OSTimeDly | |
函数原型: void OSTimeDly(INT32U ticks) | |
函数功能: 挂起任务延时 | |
入口参数: 延时的时间,任务等待时钟节拍的个数 | |
出口参数: 无 | |
有关说明: 延时数不得超出INT32U的范围 | |
************************************************************************************************************************/ | |
void OSTimeDly(INT32U ticks) | |
{ | |
if(ticks > 0) /* 当延时有效 */ | |
{ | |
OS_ENTER_CRITICAL(); | |
OSDelPrioRdy(OSPrioCur); /* 把任务从就绪表中删去 */ | |
TCB[OSPrioCur].OSTCBDly = ticks; /* 设置任务延时节拍数 */ | |
OS_EXIT_CRITICAL(); | |
OSSched(); /* 重新调度 */ | |
} | |
} | |
/************************************************************************************************************************ | |
函数名称: OSIntExit | |
函数原型: void OSIntExit(void) | |
函数功能: 从中断中退出时调用此函数,如果中断让更高优先级的任务就绪就进行任务调度 | |
入口参数: 无 | |
出口参数: 无 | |
有关说明: 若中断后需要切换任务,通过置位OSIntCtxSwFlag变量来标记 | |
************************************************************************************************************************/ | |
void OSIntExit(void) | |
{ | |
OSGetHighRdy(); /* 找出就绪表中优先级最高的任务 */ | |
if(OSPrioHighRdy != OSPrioCur) | |
{ | |
p_OSTCBCur = &TCB[OSPrioCur]; /* 目的是在汇编中引用任务的TCB地址取得栈顶指针 */ | |
p_OSTCBHighRdy = &TCB[OSPrioHighRdy]; | |
OSPrioCur = OSPrioHighRdy; /* 更新OSPrioCur */ | |
OSIntCtxSwFlag = TRUE; /* 进行中断级任务调度 */ | |
} | |
} | |
/************************************************************************************************************************ | |
函数名称: TickInterrupt | |
函数原型: void TickInterrupt(void) | |
函数功能: T0中断服务程序(时钟节拍中断服务程序) | |
入口参数: 无 | |
出口参数: 无 | |
有关说明: 用来为需要延时的任务进行计时 | |
************************************************************************************************************************/ | |
void TickInterrupt(void) | |
{ | |
static INT8U i; | |
OSTime ++; | |
//Uart_SendByte('I'); | |
for(i = 0; i < OS_TASKS; i++) /* 刷新各任务时钟 */ | |
{ | |
if(TCB[i].OSTCBDly ) | |
{ | |
TCB[i].OSTCBDly --; | |
if(TCB[i].OSTCBDly == 0) /* 当任务时钟到时,必须是由定时器减时的才行*/ | |
{ | |
OSSetPrioRdy(i); /* 使任务可以重新运行 */ | |
} | |
} | |
} | |
rSRCPND |= BIT_TIMER0; | |
rINTPND |= BIT_TIMER0; | |
} | |
/************************************************************************************************************************ | |
函数名称: IdleTask | |
函数原型: void IdleTask(void) | |
函数功能: 空闲任务,当其他任务没有就绪的时候运行 | |
入口参数: 无 | |
出口参数: 无 | |
有关说明: 空闲任务必须永远处于就绪状态 | |
************************************************************************************************************************/ | |
void IdleTask(void) | |
{ | |
IdleCount = 0; | |
while(1) | |
{ | |
IdleCount++; | |
//Uart_Printf("IdleCount %d\n",IdleCount); | |
} | |
} | |
/************************************************************************************************************************ | |
函数名称: OSInit | |
函数原型: void OSInit (void) | |
函数功能: 初始化系统全局变量,建立空闲任务 | |
入口参数: 无 | |
出口参数: 无 | |
有关说明: 初始化系统变量,建立空闲任务 | |
************************************************************************************************************************/ | |
void OSInit (void) | |
{ | |
OSTime = 0; | |
OSRdyTbl = 0; | |
OSIntCtxSwFlag = 0; | |
OSPrioCur = OSPrioHighRdy = OS_TASKS; | |
OSTaskCreate(IdleTask,&StackIdle[StackSizeIdle - 1],OS_TASKS); | |
} | |
/************************************************************************************************************************ | |
函数名称: C_IRQHandler | |
函数原型: void C_IRQHandler(void) | |
函数功能: C语言中断入口程序 | |
入口参数: 无 | |
出口参数: 无 | |
有关说明: 跳转到相应的中断服务函数 | |
************************************************************************************************************************/ | |
void C_IRQHandler(void) | |
{ | |
(* ((void(*)()) (*((U32 *)((int)&pISR_EINT0 + (rINTOFFSET<<2)))))) (); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment