操作系统最原始的功能在于对上层应用提供统一的硬件资源管理,这里的硬件资源包括CPU、内存、存储(文件系统)、外设(驱动管理)等等。
理解linux内核,代码庞大,功能复杂,可以通过ucos系统来窥探嵌入式操作系统工作原理。
分析ucos-ii源于,以及工程案例:
例子:
//可用keil直接仿真
//可用proteus仿真观察串口输出 ,晶振11.0592M,波特9600
#include "../ucos2/includes.h"
#include<stdio.h>
void TaskStartyya(void *yydata) reentrant;
void TaskStartyyb(void *yydata) reentrant;
void com_init(INT16U baud);
OS_STK TaskStartStkyya[MaxStkSize];//任务a堆栈空间
OS_STK TaskStartStkyyb[MaxStkSize];//任务b堆栈空间
void main(void)
{
OSInit(); //操作系统初始化
InitTimer0(); //定时器初始化
com_init(9600);//串口初始化
OSTaskCreate(TaskStartyya, (void *)0, &TaskStartStkyya[0],2);//创建第一个任务
OSTaskCreate(TaskStartyyb, (void *)0, &TaskStartStkyyb[0],3);//创建第二个任务
puts("There are 2 tasks");//输出提示信息
OSStart();//多任务启动
}
void TaskStartyya(void *yydata) reentrant
{
yydata=yydata;
printf("task1 begin\n");
for(;;){
OSTimeDly(OS_TICKS_PER_SEC); //延2s
printf(" task1 is running\n");
}
}
void TaskStartyyb(void *yydata) reentrant
{
yydata=yydata;
printf("task2 begin\n");
for(;;){
OSTimeDly(OS_TICKS_PER_SEC);
printf(" TASK2 IS RUNNING\n");
}
}
void com_init(INT16U baud)
{
#define fosc 11059200
SCON = 0x50; //串口工作方式为1,串行允许接受
TMOD&=0x0f;
TMOD|=0x20; //定时器1工作在方式2
if(baud<=9600) TH1=256-fosc/32/12/baud;
else
{PCON = 0x80; //SMOD = 1; 波特率加倍
TH1=256-fosc/32/12/(baud/2);
}
TR1 = 1; //允许定时器1工作
// ES = 1; //开串口中断,必须注释掉该句puts才能输出
EA = 1; //开总中断
TI=1;//要加上此句,才能用puts输出
}
这个程序的功能很简单,就是创建两个任务,两个任务每隔一段时间向屏幕输出字符串。这个程序本身也会很简单,通过分析main函数,分为操作系统初始化、相关硬件初始化、创建任务、多任务运行与调度四步。
转入ucos-ii源码,分析系统初始化,在os_core.c文件中定义了初始化函数OSInit :
void OSInit (void)
{
#if OS_VERSION >= 204
OSInitHookBegin();/* Call port specific initialization code*/
#endif
OS_InitMisc(); /* Initialize miscellaneous variables */
OS_InitRdyList(); /*Initialize the Ready List */
OS_InitTCBList(); /* Initialize the free list of OS_TCBs */
OS_InitEventList();/* Initialize the free list of OS_EVENTs */
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
OS_FlagInit(); /* Initialize the event flag structures */
#endif
#if (OS_MEM_EN > 0u) && (OS_MAX_MEM_PART > 0u)
OS_MemInit(); /* Initialize the memory manager */
#endif
#if (OS_Q_EN > 0u) && (OS_MAX_QS > 0u)
OS_QInit(); /* Initialize the message queue structures */
#endif
OS_InitTaskIdle(); /* Create the Idle Task */
#if OS_TASK_STAT_EN > 0u
OS_InitTaskStat(); /* Create the Statistic Task */
#endif
#if OS_TMR_EN > 0u
OSTmr_Init(); /* Initialize the Timer Manager */
#endif
#if OS_VERSION >= 204
OSInitHookEnd(); /* Call port specific init. code */
#endif
#if OS_DEBUG_EN > 0u
OSDebugInit();
#endif
}
OS_InitMisc()完成的是一些其他变量的初始化:
static void OS_InitMisc (void)
{
#if OS_TIME_GET_SET_EN > 0u
OSTime = 0uL;/* Clear the 32-bit system clock */
#endif
OSIntNesting = 0u;/* Clear the interrupt nesting counter */
OSLockNesting = 0u;/* Clear the scheduling lock counter */
OSTaskCtr = 0u; /* Clear the number of tasks */
OSRunning = OS_FALSE;/* Indicate that multitasking not started */
OSCtxSwCtr = 0u; /* Clear the context switch counter */
OSIdleCtr = 0uL; /* Clear the 32-bit idle counter */
#if OS_TASK_STAT_EN > 0u
OSIdleCtrRun = 0uL;
OSIdleCtrMax = 0uL;
OSStatRdy = OS_FALSE; /* Statistic task is not ready */
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
OSSafetyCriticalStartFlag = OS_FALSE;/* Still allow creation of objects */
#endif
}
其中包括:中断嵌套标志OSIntNesting,调度锁定标志OSLockNesting,OS标志OSRunning等。OSRunning在这里设置为FALSE,在后面OSStartHighRdy中会被设置为TRUE表示OS开始工作。
OS_InitRdyList()
初始化就绪Task列表:
static void OS_InitRdyList (void)
{
INT8U i;
OSRdyGrp = 0u; /* Clear the ready list */
for (i = 0u; i < OS_RDY_TBL_SIZE; i++) {
OSRdyTbl[i] = 0u;
}
OSPrioCur = 0u;
OSPrioHighRdy = 0u;
OSTCBHighRdy = (OS_TCB *)0;
OSTCBCur = (OS_TCB *)0;
}
首先将OSRdyTbl[]
数组中全部初始化0,同时将OSPrioCur
/OSTCBCur
初