Skip to content

Instantly share code, notes, and snippets.

@iskl
Created February 11, 2012 12:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iskl/1799295 to your computer and use it in GitHub Desktop.
Save iskl/1799295 to your computer and use it in GitHub Desktop.
ARM9上运行的微型操作系统
//-------------------------------------------------------------------------
// 文件名: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