uCOS-II源码详解
ucos-II中OS_CORE.C的函数结构
ucos-II中OS_CORE.C的函数结构声明:通过分析源代码,得到了如下的函数结构,如有错误,望大家指正,希望与有兴趣者共同交流进步。
//任务就绪列表,在求最高优先级时要用到这两个数组。
INT8U const OSMapTbl[]INT8U const OSUnMapTbl[]//前面是函数声明,后面还给出了函数的具体实现功能//初始化事件列表,开始时全是空值。
static void OS_InitEventList(void);//给全局变量赋值static void OS_InitMisc(void);//就绪列表的初始化static void OS_InitRdyList(void);//空闲任务的初始化static void OS_InitT askIdle(void);//初始化统计任务static void OS_InitT askStat(void);//任务控制块的初始化static void OS_InitTCBList(void);void OSInit (void){OSInitHookBegin();OS_InitMisc();OS_InitRdyList();OS_InitTCBList();OS_InitEventList();OS_FlagInit();OS_MemInit();OS_QInit();OS_InitTaskIdle();OS_InitTaskStat();OSInitHookEnd();}//开中断void OSIntEnter (void)//关中断void OSIntExit (void){OSIntCtxSw();}//调度器上锁void OSSchedLock (void)//调度器开锁void OSSchedUnlock (void)//通过这个函数,开始多任务void OSStart (void)//统计任务的初始化void OSStatInit (void)//时钟节拍void OSTimeTick (void)//版本函数INT16U OSVersion (void)//此函数什么也不做void OS_Dummy (void)//使一个正在等待任务进入就绪状态INT8U OS_EventT askRdy (OS_EVENT *pevent, void *msg, INT8U msk) //使一个任务进入等待状态void OS_EventTaskWait (OS_EVENT *pevent)//使一个等待超时的任务进入就绪状态void OS_EventTO (OS_EVENT *pevent)//初始化时间等待列表void OS_EventWaitListInit()//事件控制块的初始化函数static void OS_InitEventList (void)//调度器void OS_Sched (void)//空闲任务void OS_TaskIdle (void *pdata)//统计任务void OS_TaskStat (void *pdata)//控制块的初始化INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt)。
ucOS-II范例分析_01
分析一下OS_CPU.H文件,它涉及特定CPU 的实现。一般都被替换为一条或者几条嵌入 式汇编代码。其实,它就是关中断。 只要任务不主动放弃CPU使用权,别的任务 就没有占用CPU的机会,这个任务就是独占 了。进入临界区后,这个应宏尽量少用,它 会破坏系统的一些服务,尤其是时间服务。 并使系统对外界响应性能降低。
不依赖于编译的数据类型
可移植型数据类型的程序 Typedef unsigned char BOOLEAN; Typedef unsigned char INT8U; Typedef signed char INT8S; Typedef unsigned int INT16U; Typedef signed int INT16S; Typedef unsigned long INT32U; Typedef signed long INT32S; Typedef float FP32; Typedef double FP64; #define BYTE INT8S -----------| #define UBYTE INT8U -----------| #define WORD INT16S ------------| ucos->ucosII #define UWORD INT16U -----------| #define LONG INT32S -----------| #define ULONG INT32U -----------|
嵌入式操作系统ucOS-II分析
ucOS-II应用程序基本结构
void task ( void* pdata ) { INT8U err; InitTimer(); // 可选 For( ;; ) { // 你的应用程序代码 …….. OSTimeDly(1); // 可选 } }
[VIP专享]ucos-ii(源代码开放的确良嵌入式os)教程(2)
第2章实时系统概念 12.0 前后台系统(FOREGROUND/BACKGROUND SYSTEM) 1 2.1 代码的临界段 22.2 资源 22.3 共享资源 22.4 多任务 22.5 任务 22.6 任务切换(CONTEXT SWITCH OR TASK SWITCH) 32.7 内核(KERNEL) 32.8 调度(SCHEDULER) 42.9 不可剥夺型内核(NON-PREEMPTIVE KERNEL) 42.10 可剥夺型内核 52.11 可重入性(REENTRANCY) 52.12 时间片轮番调度法 72.13 任务优先级 72.14 2.14静态优先级 72.15 动态优先级 72.16 优先级反转 72.17 任务优先级分配 82.18 互斥条件 102.18.1 关中断和开中断 102.18.2 测试并置位 112.18.3 禁止,然后允许任务切换 112.18.4 信号量(Semaphores) 122.19 死锁(或抱死)(DEADLOCK (OR DEADLY EMBRACE)) 16 2.20 同步 162.21 事件标志(EVENT FLAGS) 182.22 任务间的通讯(INTERTASK COMMUNICATION) 182.23 消息邮箱(MESSAGE MAIL BOXES) 182.24 消息队列(MESSAGE QUEUE) 192.25 中断 202.26 中断延迟 202.27 中断响应 212.28 中断恢复时间(INTERRUPT RECOVERY) 212.29 中断延迟、响应和恢复 222.30 中断处理时间 222.31 非屏蔽中断(NMI) 232.32 时钟节拍(CLOCK TICK) 242.33 对存储器的需求 252.34 使用实时内核的优缺点 262.35 实时系统小结 26第2章实时系统概念实时系统的特点是,如果逻辑和时序出现偏差将会引起严重后果的系统。
uCOS-II源码分析
uC/OS-II源码分析(一)下载地址:/它的特点:1)开源,2)可移植性,绝大部分代码用C写,硬件相关部分用汇编写,3可固化,4)可剪裁,这通过条件编译实现,使用#define语句定义所需要的功能。
5)可剥夺性(总是运行就绪条件下优先级最高的任务),6)多任务(可以管理64个任务,其中保留8个给uC/OS-II,因此用户最多可有56个任务,每个任务优先级不同,也就意味着不支持时间片轮转调度法,因为这种方法适合于优先级平等的任务)。
7)可确定性。
函数调度和服务执行时间具有确定性,除了OSTimeTick()和某些事件标志服务,系统服务执行时间不依赖用户应用程序任务数目的多少。
8)任务栈。
允许每个任务自己单独的栈空间不同,可以使用栈空间检验函数确定所需要的栈空间大小。
9)系统服务。
提供信号量,互斥型信号量,事件标志,消息邮箱,消息队列,块大小固定的内存申请与释放,时间管理函数等服务。
10)中断管理。
中断嵌套层数最多可达到255层。
11)稳定性和可靠性。
OSInit()函数用来初始化内核,必须首先调用。
建立两个任务:空闲任务(其他任务都未就绪时运行),统计任务(计算CPU的利用率).****************************************************************** Description: This function is used to initialize the internals of uC/OS-II and MUST be called prior to creating any uC/OS-II object and, prior to calling OSStart().*****************************************************************void OSInit (void){OSInitHookBegin();/* 调用用户特定的初始化代码(通过一个接口函数实现用户要求的插件式进入系统中)*/OS_InitMisc();/* 初始化变量*/OS_InitRdyList();/* 初始化就绪列表*/OS_InitTCBList();/* 初始化OS_TCB空闲列表*/OS_InitEventList();/* 初始化OS_EVENT空闲列表*/#if(OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)//允许事件标志OS_FlagInit();/* 初始化事件标志结构*/#endif#if(OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)//允许内存管理OS_MemInit();/* 初始化内存管理器*/#endif#if(OS_Q_EN > 0) && (OS_MAX_QS > 0)//允许消息队列OS_QInit();/* 初始化消息队列结构*/#endifOS_InitTaskIdle();/*创建空闲任务*/#if OS_TASK_STAT_EN > 0OS_InitTaskStat();/* 创建统计任务*/#endif#if OS_TMR_EN > 0//允许时间管理OSTmr_Init();/* 初始化时间管理器*/#endifOSInitHookEnd();/*调用用户特定的初始化代码(参考OSInitHookBegin())*/#if OS_DEBUG_EN > 0//允许DebugOSDebugInit();//初始化调试器#endif}******************************************************************************************** * Description: This function is called by OSInit() to initialize miscellaneous variables.********************************************************************************************static void OS_InitMisc (void){#if OS_TIME_GET_SET_EN > 0OSTime = 0L; /* 32位的系统时钟清零*/#endifOSIntNesting = 0; /* 中断嵌套层数计数器清零*/OSLockNesting = 0; /* 调度器锁的嵌套层数计数器清零*/ OSTaskCtr = 0; /* 任务数清零*/OSRunning = OS_FALSE; /*指明多任务未开始*/OSCtxSwCtr = 0; /* 任务切换次数计数器清零*/OSIdleCtr = 0L; /*32位空闲计数器清零*/#if OS_TASK_STAT_EN > 0 /*运行统计任务*/OSIdleCtrRun = 0L;OSIdleCtrMax = 0L;OSStatRdy = OS_FALSE; /* 统计任务未就绪*/#endif}空闲任务和统计任务建立的代码基本一样,只是统计任务的优先级比空闲任务大1,******************************************************************************************** * Description: This function creates the Idle Task.********************************************************************************************static void OS_InitTaskIdle (void){#if OS_TASK_NAME_SIZE > 7 //INT8U err;#endif#if OS_TASK_CREATE_EXT_EN > 0 //使用扩展的OSTaskCreateExt来创建#if OS_STK_GROWTH == 1 //任务堆栈从底部向顶部增长的方向有两种:表示从大到小,表示从小到大(void)OSTaskCreateExt(OS_TaskIdle,(void *)0, /* 没有参数传给OS_TaskIdle() */&OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /*设置堆栈顶*/OS_TASK_IDLE_PRIO, /* 优先级设置为最低*/OS_TASK_IDLE_ID, //设置ID&OSTaskIdleStk[0], /* 设置栈底*/OS_TASK_IDLE_STK_SIZE, //设置栈大小(void *)0, /* 没有TCB扩展数据结构OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* 允许堆栈检测和清空堆栈*/#else(void)OSTaskCreateExt(OS_TaskIdle,(void *)0, /* No arguments passed to OS_TaskIdle() */&OSTaskIdleStk[0], /* Set Top-Of-StackOS_TASK_IDLE_PRIO, /* Lowest priority levelOS_TASK_IDLE_ID,&OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1], /* Set Bottom-Of-Stack */OS_TASK_IDLE_STK_SIZE,(void *)0, /* No TCB extensionOS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);/* Enable stack check ing + clear stack */#endif#else//使用不带扩展性的OSTaskCreate创建#if OS_STK_GROWTH == 1(void)OSTaskCreate(OS_TaskIdle,(void *)0,&OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1],OS_TASK_IDLE_PRIO);#else(void)OSTaskCreate(OS_TaskIdle,(void *)0,&OSTaskIdleStk[0],OS_TASK_IDLE_PRIO);#endif#endif//设置任务名称#if OS_TASK_NAME_SIZE > 14OSTaskNameSet(OS_TASK_IDLE_PRIO, (INT8U *)"uC/OS-II Idle", &err); #else#if OS_TASK_NAME_SIZE > 7OSTaskNameSet(OS_TASK_IDLE_PRIO, (INT8U *)"OS-Idle", &err);#endif#endif}uC/OS-II源码分析(二)在真正开始分析源代码前,先来看使用uC/OS-II的三个例子1)使用信号量#define TASK_STK_SIZE 512 /* 每个任务堆栈的大小(以字计算)*/ #define N_TASKS 10 /* 任务数*/OS_STK TaskStk[N_TASKS][TASK_STK_SIZE]; /*任务堆栈*/OS_STK TaskStartStk[TASK_STK_SIZE]; //开始任务的堆栈char TaskData[N_TASKS]; /*传给每个任务的数据*/OS_EVENT *RandomSem; //互斥型信号量void main (void){PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK); /*清空屏幕*/OSInit(); /* 初始化uC/OS-II*/PC_DOSSaveReturn(); /* 保存环境以便稍后可以返回DOS 环境*/PC_VectSet(uCOS, OSCtxSw); /*设置uC/OS-II的切换处理函数*/RandomSem = OSSemCreate(1); /* 建立一个信号量*/OSTaskCreate(TaskStart, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0);//创建第一个任务,优先级设置为最大值OSStart(); /* 开始多任务*/}void TaskStart (void *pdata){#if OS_CRITICAL_METHOD == 3 /* 为CPU的状态寄存器分配内存*/OS_CPU_SR cpu_sr;#endifchar s[100];INT16S key;pdata = pdata; /* 这步是为了防止编译错误*/TaskStartDispInit(); /* 初始化显示屏*/OS_ENTER_CRITICAL();PC_VectSet(0x08, OSTickISR); /*替换机器的时钟中断函数为uC/OS-II所需要的中断函数*/PC_SetTickRate(OS_TICKS_PER_SEC); /* 调整时钟频率*/OS_EXIT_CRITICAL();OSStatInit(); /* 初始化统计任务*/TaskStartCreateTasks(); /*创建其他任务*/ for (;;) {TaskStartDisp();if (PC_GetKey(&key) == TRUE) { /* 是否按键*/if (key == 0x1B) { /* ESCAPE按下了*/PC_DOSReturn(); /* 返回DOS*/}}OSCtxSwCtr = 0; /* 切换次数计数器清零*/OSTimeDlyHMSM(0, 0, 1, 0); /*挂起秒,让给其他任务运行*/ }}static void TaskStartCreateTasks (void){INT8U i;for (i = 0; i < N_TASKS; i++) { /* 创建N_TASKS个任务*/TaskData[i] = '0' + i; /* 每个任务显示其数据*/OSTaskCreate(Task, (void *)&TaskData[i], &TaskStk[i][TASK_STK_SIZE - 1 ], i + 1);}}void Task (void *pdata){INT8U x;INT8U y;INT8U err;for (;;) {OSSemPend(RandomSem, 0, &err); /* 获取信号量*/x = random(80); /* 计算X坐标*/y = random(16); /* 计算Y坐标*/OSSemPost(RandomSem); /* 释放信号量*//* Display the task number on the screen */PC_DispChar(x, y + 5, *(char *)pdata, DISP_FGND_BLACK + DISP_BGND_ LIGHT_GRAY);OSTimeDly(1); /* 挂起秒,让给其他任务运行*/}}2)使用消息邮箱#define TASK_STK_SIZE 512#define TASK_START_ID 0 /* 任务ID*/#define TASK_CLK_ID 1#define TASK_1_ID 2#define TASK_2_ID 3#define TASK_3_ID 4#define TASK_4_ID 5#define TASK_5_ID 6#define TASK_START_PRIO 10 /* 任务优先级*/#define TASK_CLK_PRIO 11#define TASK_1_PRIO 12#define TASK_2_PRIO 13#define TASK_3_PRIO 14#define TASK_4_PRIO 15#define TASK_5_PRIO 16OS_STK TaskStartStk[TASK_STK_SIZE];OS_STK TaskClkStk[TASK_STK_SIZE];OS_STK Task1Stk[TASK_STK_SIZE];OS_STK Task2Stk[TASK_STK_SIZE];OS_STK Task3Stk[TASK_STK_SIZE];OS_STK Task4Stk[TASK_STK_SIZE];OS_STK Task5Stk[TASK_STK_SIZE];OS_EVENT *AckMbox; /* 任务和使用的消息邮箱*/ OS_EVENT *TxMbox;void main (void){OS_STK *ptos;OS_STK *pbos;INT32U size;PC_DispClrScr(DISP_FGND_WHITE);OSInit();PC_DOSSaveReturn();PC_VectSet(uCOS, OSCtxSw);PC_ElapsedInit();ptos = &TaskStartStk[TASK_STK_SIZE - 1]; pbos = &TaskStartStk[0];size = TASK_STK_SIZE;OSTaskStkInit_FPE_x86(&ptos, &pbos, &size); OSTaskCreateExt(TaskStart,(void *)0,ptos,TASK_START_PRIO,TASK_START_ID,pbos,size,(void *)0,OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR); OSStart();}void TaskStart (void *pdata){#if OS_CRITICAL_METHOD == 3OS_CPU_SR cpu_sr;#endifINT16S key;pdata = pdata;TaskStartDispInit();OS_ENTER_CRITICAL();PC_VectSet(0x08, OSTickISR);PC_SetTickRate(OS_TICKS_PER_SEC);OS_EXIT_CRITICAL();OSStatInit();AckMbox = OSMboxCreate((void *)0); /* 创建两个消息邮箱*/ TxMbox = OSMboxCreate((void *)0);TaskStartCreateTasks();for (;;) {TaskStartDisp();if (PC_GetKey(&key)) {if (key == 0x1B) {PC_DOSReturn();}}OSCtxSwCtr = 0;OSTimeDly(OS_TICKS_PER_SEC);}}void Task1 (void *pdata){INT8U err;OS_STK_DATA data; /* 任务堆栈数据*/INT16U time;INT8U i;char s[80];pdata = pdata;for (;;) {for (i = 0; i < 7; i++) {PC_ElapsedStart();err = OSTaskStkChk(TASK_START_PRIO + i, &data);//执行堆栈检查time = PC_ElapsedStop();if (err == OS_NO_ERR) {sprintf(s, "%4ld %4ld %4ld %6d",data.OSFree + data.OSUsed,data.OSFree,data.OSUsed,time);PC_DispStr(19, 12 + i, s, DISP_FGND_BLACK + DISP_BGND_LIGHT_G RAY);}}OSTimeDlyHMSM(0, 0, 0, 100); /* 挂起mS*/}}void Task4 (void *data){char txmsg;INT8U err;data = data;txmsg = 'A';for (;;) {OSMboxPost(TxMbox, (void *)&txmsg); /* 发消息给Task #5*/OSMboxPend(AckMbox, 0, &err); /* 等待Task #5的应答消息*/txmsg++; /*下一个要发的消息数据*/if (txmsg == 'Z') {txmsg = 'A'; /* 循环发送A-Z*/}}}void Task5 (void *data){char *rxmsg;INT8U err;data = data;for (;;) {rxmsg = (char *)OSMboxPend(TxMbox, 0, &err); /* 等待来自Task #4的数据*/PC_DispChar(70, 18, *rxmsg, DISP_FGND_YELLOW + DISP_BGND_BLUE); OSTimeDlyHMSM(0, 0, 1, 0); /* 挂起秒,让给其他任务运行*/OSMboxPost(AckMbox, (void *)1); /*发送接收到数据的应答消息*/}}运行结果:3)使用消息队列#define TASK_STK_SIZE 512#define TASK_START_ID 0#define TASK_CLK_ID 1#define TASK_1_ID 2#define TASK_2_ID 3#define TASK_3_ID 4#define TASK_4_ID 5#define TASK_5_ID 6#define TASK_START_PRIO 10#define TASK_CLK_PRIO 11#define TASK_1_PRIO 12#define TASK_2_PRIO 13#define TASK_3_PRIO 14#define TASK_4_PRIO 15#define TASK_5_PRIO 16#define MSG_QUEUE_SIZE 20 /* 消息队列大小*/ typedef struct {char TaskName[30];INT16U TaskCtr;INT16U TaskExecTime;INT32U TaskTotExecTime;} TASK_USER_DATA;OS_STK TaskStartStk[TASK_STK_SIZE];OS_STK TaskClkStk[TASK_STK_SIZE];OS_STK Task1Stk[TASK_STK_SIZE];OS_STK Task2Stk[TASK_STK_SIZE];OS_STK Task3Stk[TASK_STK_SIZE];OS_STK Task4Stk[TASK_STK_SIZE];OS_STK Task5Stk[TASK_STK_SIZE];TASK_USER_DATA TaskUserData[7];OS_EVENT *MsgQueue; /*消息队列指针*/ void *MsgQueueTbl[20]; /*消息存储*/void main (void){PC_DispClrScr(DISP_BGND_BLACK);OSInit();PC_DOSSaveReturn();PC_VectSet(uCOS, OSCtxSw);PC_ElapsedInit();strcpy(TaskUserData[TASK_START_ID].TaskName, "StartTask"); OSTaskCreateExt(TaskStart,(void *)0,&TaskStartStk[TASK_STK_SIZE - 1],TASK_START_PRIO,TASK_START_ID,&TaskStartStk[0],TASK_STK_SIZE,&TaskUserData[TASK_START_ID],0);OSStart();}void TaskStart (void *pdata){#if OS_CRITICAL_METHOD == 3OS_CPU_SR cpu_sr;#endifINT16S key;pdata = pdata;TaskStartDispInit();OS_ENTER_CRITICAL();PC_VectSet(0x08, OSTickISR);PC_SetTickRate(OS_TICKS_PER_SEC);OS_EXIT_CRITICAL();OSStatInit();MsgQueue = OSQCreate(&MsgQueueTbl[0], MSG_QUEUE_SIZE); /*创建消息队列,大小为*/TaskStartCreateTasks();for (;;) {TaskStartDisp();if (PC_GetKey(&key)) {if (key == 0x1B) {PC_DOSReturn();}}OSCtxSwCtr = 0;OSTimeDly(OS_TICKS_PER_SEC);}}void Task1 (void *pdata){char *msg;INT8U err;pdata = pdata;for (;;) {msg = (char *)OSQPend(MsgQueue, 0, &err);//从消息队列中取消息PC_DispStr(70, 13, msg, DISP_FGND_YELLOW + DISP_BGND_BLUE);OSTimeDlyHMSM(0, 0, 0, 100);}}void Task2 (void *pdata)char msg[20];pdata = pdata;strcpy(&msg[0], "Task 2");for (;;) {OSQPost(MsgQueue, (void *)&msg[0]);//发送消息到队列中 OSTimeDlyHMSM(0, 0, 0, 500);}}void Task3 (void *pdata){char msg[20];pdata = pdata;strcpy(&msg[0], "Task 3");for (;;) {OSQPost(MsgQueue, (void *)&msg[0]);//发送消息到队列中 OSTimeDlyHMSM(0, 0, 0, 500);}}void Task4 (void *pdata){char msg[20];pdata = pdata;strcpy(&msg[0], "Task 4");for (;;) {OSQPost(MsgQueue, (void *)&msg[0]);//发送消息到队列中 OSTimeDlyHMSM(0, 0, 0, 500);}}void OSTaskStatHook (void)char s[80];INT8U i;INT32U total;INT8U pct;total = 0L; /* Totalize TOT. EXEC. TIME for each t askfor (i = 0; i < 7; i++) {total += TaskUserData[i].TaskTotExecTime;DispTaskStat(i); /* Display task data }if (total > 0) {for (i = 0; i < 7; i++) { /* Derive percentage of each task */pct = 100 * TaskUserData[i].TaskTotExecTime / total;sprintf(s, "%3d %%", pct);PC_DispStr(62, i + 11, s, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRA Y);}}if (total > 1000000000L) { /* Reset total time counters at 1 billionfor (i = 0; i < 7; i++) {TaskUserData[i].TaskTotExecTime = 0L;}}}void OSTaskSwHook (void){INT16U time;TASK_USER_DATA *puser;time = PC_ElapsedStop(); /* This task is donePC_ElapsedStart(); /* Start for next task puser = OSTCBCur->OSTCBExtPtr; /* Point to used dataif (puser != (TASK_USER_DATA *)0) {puser->TaskCtr++; /* Increment task counter puser->TaskExecTime = time; /* Update the task's execution timepuser->TaskTotExecTime += time; /* Update the task's total executi on time}}运行结果:uC/OS-II源码分析(三)首先来了解下实时系统的基本概念:1)临界区,共享资源,任务(类似于进程),任务切换,任务调度,可剥夺型内核,可重入函数,动态优先级调度,2)如何处理优先级反转问题。
ucos-ii大体框架
一.main.c#include <hidef.h>#include "includes.h"#define _MAIN //便于变量的定义#define EXT#include "Os_Application.h"#pragma LINK_INFO DERIV ATIVE "mc9s12dg128b"/****************************************************************************** ** 函数名称: main** 功能描述: c语言程序的入口地址,创建任务和信号量** 输入: 无** 输出: 无** 全局变量: 无** 调用模块: 无** 版本: V1.0** 作者: ZHOU** 日期: 2007年5月2日*****************************************************************************/ void main(void){INT8U Os_Err = 0;OSInit();TxSem = OSSemCreate(0);SpeedSem = OSSemCreate(0);EEPROMSem = OSSemCreate(0);Integral_Q = OSQCreate(&MsgGrp1[0],16);Recollection_Q = OSQCreate(&MsgGrp[0],16);Brake_Q = OSQCreate(&MsgGrp2[0],8);Os_Err = OSTaskCreate(TaskStart,(void *)0,(OS_STK *)&TaskStartStk[TASK_STK_SIZE-1],TASK_START_PRIO);Os_Err = OSTaskCreate(TxTask,(void *)0,(OS_STK *)&TxTaskStk[TASK_STK_SIZE-1],TxTask_PRIO);Os_Err = OSTaskCreate(BrakeTask,(void *)0,(OS_STK *)&BrakeTaskStk[TASK_STK_SIZE-1],BrakeTask_PRIO);Os_Err = OSTaskCreate(EEPROMTask,(void *)0,(OS_STK *)&EEPROMTaskStk[TASK_STK_SIZE-1],EEPROMTask_PRIO);Os_Err = OSTaskCreate(SpeedControl,(void *)0,(OS_STK *)&SpeedControlStk[TASKSpeedControl_STK_SIZE-1],SpeedControl_PRIO);Os_Err = OSTaskCreate(IntegralControl,(void *)0,(OS_STK *)&IntegralControlStk[TASK_STK_SIZE-1],IntegralControl_PRIO);Os_Err = OSTaskCreate(RoadRecollection,(void *)0,(OS_STK *)&RoadRecollectionStk[TASK_STK_SIZE-1],RoadRecollection_PRIO);OSStart();}void TaskStart(void *pdata){INT8U WhiteNum = 0;INT16U sensor = 0;INT16U eeread = 0;INT16U *EEadr = (unsigned int *)(0x800);SYSTEMTIMERINITIAL(); //系统时钟初始化程序RTIINITIAL(); //时钟中断初始化,每4.096MS采样一次传感器的值PC0INITIAL(); //输入捕捉通道0初始化PWMINITIAL(); //舵机转向和电机驱动PWM初始化RateStateNow = Mid; //小车开始运行,先给定路况和速度LoadState = V ertical;//CircleState = 0; //复位后小车驶过的圈数清零//Distance = 0; //复位后小车驶过的距离清零SpeedLevel = MAXSpeed; //小车起始速度约为2.65625M/S//EEPROMETASE(); //将EEPROM中的数据全部擦除//在EEPROM的起始地址处写入一个标志值//EEPROMWRITE((unsigned int *)(0x800),(unsigned int)0xFFFF);pdata = pdata;for(;;){sensor = PORTAB&0x1FF; //冲出赛道保护if(sensor == 0){WhiteNum ++;if(WhiteNum == 5){PWME &= (~PWME_PWME3_MASK); //传感器连续检测不到黑色引导线,可能已经冲出赛道} //关闭驱动电机,保护小车不被撞损}else{WhiteNum = 0;}//EEPROM调试模块,定时循环的将想要了解的小车参数发向单片机的串口/*eeread = *EEadr++;if(EEadr == (unsigned int*)(0xFD0)) EEadr = (unsigned int *)(0x800);TxData = eeread;TxChar = " "; //为了便于观察,每个参数之间用两个空格隔开OSSemPost(TxSem); */OSTimeDly(20); //200ms切换一次,用来检验系统工作是否正常,一次系统的时钟切换为10ms}}void TxTask(void *pdata) //串口调试任务void EEPROMTask(void *pdata) //写入EEPROM任务void SpeedControl(void *pdata)void IntegralControl(void *pdata)void BrakeTask(void *pdata)void RoadRecollection(void *pdata)二.datapage.c三.Os_cpu.h#ifndef OS_CPU_H#define OS_CPU_H/***************************************************************************** CONFIGURA TION CONSTANTS*****************************************************************************/ #defineCPU_FRT_FREQ 375000L /* Free Running Timer rate (Hz) *//* Number of FRT counts to produce an interrupt @tick rate */ #define OS_TICK_OC_CNTS (CPU_FRT_FREQ / OS_TICKS_PER_SEC)/* OS_TICK_OC_CNTS = CPU_FRT_FREQ / OS_TICKS_PER_SEC*//****************************************************************************** * DATA TYPES******************************************************************************/ typedef unsigned char BOOLEAN;typedef unsigned char INT8U; // Unsigned 8 bit quantitytypedef signed char INT8S; // Signed 8 bit quantitytypedef unsigned int INT16U; // Unsigned 16 bit quantitytypedef signed int INT16S; // Signed 16 bit quantitytypedef unsigned long INT32U; // Unsigned 32 bit quantitytypedef signed long INT32S; // Signed 32 bit quantitytypedef float FP32; // Single precision floating point typedef double FP64; // Double precision floating pointtypedef unsigned char OS_STK; // Each stack entry is 8-bit wide typedef unsigned char OS_CPU_SR; // Define size of CPU status register (PSW =8 bits)/****************************************************************************** * CONSTANTS*****************************************************************************/#ifndef FALSE#define FALSE 0#endif#ifndef TRUE#define TRUE 1#endif#define OS_CRITICAL_METHOD 3#if OS_CRITICAL_METHOD == 1#define OS_ENTER_CRITICAL() asm sei ;#define OS_EXIT_CRITICAL() asm cli ;#endif#if OS_CRITICAL_METHOD == 2#define OS_ENTER_CRITICAL() asm pshc; sei;#define OS_EXIT_CRITICAL() asm pulc;#endif#if OS_CRITICAL_METHOD == 3#define OS_ENTER_CRITICAL() (OSCPUSaveSR(cpu_sr)) // Disable interrupts#define OS_EXIT_CRITICAL() (OSCPURestoreSR(cpu_sr)) // Enable interrupts#endif#define OS_TASK_SW() asm swi;#define OS_STK_GROWTH 1 // Define stack growth: 1 = Down, 0 = Up #define CPU_INT_DIS() asm sei ; // Disable interrupts#define CPU_INT_EN() asm cli ; // Enable interrupts/* **************************************************************************** * PROTOTYPES******************************************************************************/ #if OS_CRITICAL_METHOD == 3void OSCPUSaveSR(OS_CPU_SR os_cpu_sr); // Set 'os_cpu_sr' register to CCR// ... disable interrupts via SEI instruction. void OSCPURestoreSR(OS_CPU_SR os_cpu_sr); // Set CCR register to 'os_cpu_sr'#endif#endif四.Include.h#include <stddef.h>#include <mc9s12dg128.h>#include "os_cpu.h"#include "os_cfg.h"#include "ucos_ii.h"五.Os_cfg.h#ifndef OS_CFG_H#define OS_CFG_H/* ---------------------- MISCELLANEOUS ----------------------- */#define OS_ARG_CHK_EN 1 /* Enable (1) or Disable (0) argument checking */#define OS_CPU_HOOKS_EN 1 /* uC/OS-II hooks are found in the processor port files*/#define OS_LOWEST_PRIO 23 /* Defines the lowest priority that can be assigned */.../* ... MUST NEVER be higher than 63! */#define OS_MAX_EVENTS 10 /* Max. number of event control blocks in your application*/ #define OS_MAX_FLAGS 2 /* Max. number of Event Flag Groups in your application*/ #define OS_MAX_MEM_PART 2 /* Max. number of memory partitions */#define OS_MAX_QS 8 /* Max. number of queue control blocks in your application*/ #define OS_MAX_TASKS 10 /* Max. number of tasks in your application, MUST be >= 2*/ #define OS_SCHED_LOCK_EN 0 /* Include code for OSSchedLock() and OSSchedUnlock()*/ #define OS_TASK_IDLE_STK_SIZE 200 /* Idle task stack size (# of OS_STK wide entries)*/#define OS_TASK_STA T_EN 0 /* Enable (1) or Disable(0) the statistics task */#define OS_TASK_STA T_STK_SIZE 64 /* Statistics task stack size (# of OS_STK wide entries) #define OS_TICKS_PER_SEC 100 /* Set the number of ticks in one second */ /* ----------------------- EVENT FLAGS ------------------------ */#define OS_FLAG_EN 0 /* Enable (1) or Disable (0) code generation for EVENT FLAGS*/ #define OS_FLAG_W AIT_CLR_EN 0 /* Include code for Wait on Clear EVENT FLAGS*/ #define OS_FLAG_ACCEPT_EN 0 /* Include code for OSFlagAccept()*/#define OS_FLAG_DEL_EN 0 /* Include code for OSFlagDel() */#define OS_FLAG_QUERY_EN 0 /* Include code for OSFlagQuery() *//* -------------------- MESSAGE MAILBOXES --------------------- */#define OS_MBOX_EN 0 /* Enable (1) or Disable (0) code generation for MAILBOXES*/ #define OS_MBOX_ACCEPT_EN 0 /* Include code for OSMboxAccept() */#define OS_MBOX_DEL_EN 0 /*Include code for OSMboxDel()*/#define OS_MBOX_POST_EN 0 /* Include code for OSMboxPost() */#define OS_MBOX_POST_OPT_EN 0 /* Include code for OSMboxPostOpt()*/#define OS_MBOX_QUERY_EN 0 /* Include code for OSMboxQuery()*/ /* --------------------- MEMORY MANAGEMENT -------------------- */#define OS_MEM_EN 0/* Enable (1) or Disable (0) code generation for MEMORY MANAGER* #define OS_MEM_QUERY_EN 0 /* Include code for OSMemQuery() */ /* ---------------- MUTUAL EXCLUSION SEMAPHORES --------------- */#define OS_MUTEX_EN 0 /* Enable (1) or Disable (0) code generation for MUTEX*/ #define OS_MUTEX_ACCEPT_EN 0 /* Include code for OSMutexAccept()*/#define OS_MUTEX_DEL_EN 0 /* Include code for OSMutexDel()*/#define OS_MUTEX_QUERY_EN 0 /* Include code for OSMutexQuery()*//* ---------------------- MESSAGE QUEUES ---------------------- */#define OS_Q_EN 1 /* Enable (1) or Disable (0) code generation for QUEUES*/#define OS_Q_ACCEPT_EN 0 /* Include code for OSQAccept() */#define OS_Q_DEL_EN 0 /* Include code for OSQDel() */#define OS_Q_FLUSH_EN 0 /*Include code for OSQFlush() */#define OS_Q_POST_EN 1 /* Include code for OSQPost() */#define OS_Q_POST_FRONT_EN 0 /* Include code for OSQPostFront()*/#define OS_Q_POST_OPT_EN 0 /* Include code for OSQPostOpt()*/#define OS_Q_QUERY_EN 0 /* Include code for OSQQuery() */ /*------------------------ SEMAPHORES ------------------------ */#define OS_SEM_EN 1 /* Enable (1) or Disable (0) code generation for SEMAPHORES*/ #define OS_SEM_ACCEPT_EN 0 /* Include code for OSSemAccept()*/#define OS_SEM_DEL_EN 0 /* Include code for OSSemDel() */#define OS_SEM_QUERY_EN 0 /* Include code for OSSemQuery() */ /* --------------------- TASK MANAGEMENT ---------------------- */#define OS_TASK_CHANGE_PRIO_EN 0 /* Include code for OSTaskChangePrio()*/ #define OS_TASK_CREATE_EN 1 /* Include code for OSTaskCreate()*/#define OS_TASK_CREATE_EXT_EN 0 /* Include code for OSTaskCreateExt()*/#define OS_TASK_DEL_EN 0 /* Include code for OSTaskDel()*/#define OS_TASK_QUERY_EN 0 /* Include code for OSTaskQuery()*/#define OS_TASK_SUSPEND_EN 0 /*Include code for OSTaskSuspend() and OSTaskResume() #define OS_TASK_SW_HOOK_EN 1 /* Include code for OSTaskSwHook()*/ /* --------------------- TIME MANAGEMENT ---------------------- */#define OS_TIME_DL Y_HMSM_EN 0 /* Include code for OSTimeDlyHMSM()*/#define OS_TIME_DL Y_RESUME_EN 0 /* Include code for OSTimeDlyResume() */ #define OS_TIME_GET_SET_EN 0 /* Include code for OSTimeGet() and OSTimeSet()*/ #define OS_TIME_TICK_HOOK_EN 1 /* Include code for OSTimeTickHook() */ typedef INT8U OS_FLAGS; /* Date type for event flag bits (8, 16 or 32 bits)*/#endif六.Ucos_ii.h七.Ucos_ii.c#define OS_GLOBALS /* Declare GLOBAL variables */#include "includes.h"#define OS_MASTER_FILE /* Prevent the following files from including includes.h */#include "os_core.c"//#include "os_flag.c"//#include "os_mbox.c"//#include "os_mem.c"//#include "os_mutex.c"#include "os_q.c"#include "os_sem.c"#include "os_task.c"#include "os_time.c"//#include "os_cpu_c.c"八.Os_cpu_c.c#include "includes.h"** 函数名称: OSTaskStkInit** 功能描述: 任务堆栈初始化函数,由建立任务的函数OSTaskCreate()或扩展的建立任务函数OSTaskCreateExt()调用** 输入: task 指向任务的指针pdata 该指针用于用户初次建立任务时用户需要使用的数据ptos 指向任务栈顶的指针opt 可选项**函数名称: OSInitHookBegin** 功能描述: 该函数在系统初始化时被OSInit()调用**函数名称: OSInitHookEnd** 功能描述: 该函数在系统初始化时被OSInit()调用** 函数名称: OSTaskDelHook** 功能描述: 该函数在删除任务时被调用** 输入: ptcb 指向任务控制块的指针** 函数名称: OSTaskStatHook** 功能描述: 该函数在统计任务被调用时使用** 函数名称: OSTaskSwHook** 功能描述: 该函数在任务被切换时调用** 函数名称: OSTCBInitHook** 功能描述: 该函数在任务控制块初始化时被OSTCBInit()调用** 输入: ptcb 指向任务控制块的指针** 函数名称: OSCPUSaveSR & OSCPURestoreSR** 功能描述: 该函数在OS_CRITICAL_METHOD=3时使用** 输入: OS_CPU_SR 用来存储CCR寄存器的内容** 函数名称: OSStartHighRdy** 功能描述: 该函数被OSStart()调用用来启动用户创建的具有最高优先级的任务OSTCBHighRdy->OSTCBStkPtr + 0 --> PPAGE; + 1 CCR; + 2 B; + 3 A; + 4 X (H); + 5 X (L); + 6 Y (H); + 7 Y (L); + 8 PC(H); + 9 PC(L)** 调用模块: OSTaskSwHook();** 功能描述: 任务级任务的切换函数,** 调用模块: OSTaskSwHook();** 函数名称: OSIntCtxSw** 功能描述: 中断级任务的切换函数,** 调用模块: OSTaskSwHook();** 函数名称: OSTickISR** 功能描述: 时钟节拍由输出比较通道7产生** 调用模块: OSTimeTick(),OSIntExit ();九.Sci_diver.c#include "includes.h"#define EXT extern#include "Os_Application.h"** 函数名称: SciCfgPort** 功能描述: 对SCI通信进行配置,为了简单采用最常见的模式,BAUD:115200,起始位:1,数据位:8,结束位:1** 函数名称: SciGetChar** 功能描述: 这个函数被应用程序所调用来从串行口获得一个字节的数据,如果串行口没有接收到数据,函数将在这里** 等待直到数据被接收到或者任务等待的时间溢出** 输入: 'to',任务等待的时间,如果为0,则表示如果没接收到数据,任务将在这里永远等待** 'err',返回函数错误信息的指针,如果数据被成功接收了则返回SCI_NO_ERR ** 如果时间溢出则返回SCI_TIMEOUT** 输出: 返回接收到的字符,或者NUL(如果时间溢出)** 函数名称: SciGetTxChar** 功能描述: 这个函数被应用程序所调用来从发送缓冲区获得一个字节的数据,如果缓冲区没有了要发送的数据,则函数** 返回出错信息** 输入: 'err',返回函数错误信息的指针,如果数据区至少还有一个字节可用,函数返回SCI_NO_ERR** 如果发送缓冲区为空则返回SCI_TX_EMPTY** 输出: 返回下一个要发的字符,或者NUL(如果发送缓冲区为空)** 函数名称: SciInit** 功能描述: 这个函数被应用程序所调用来初始化串行口通信,这个函数要在别的程序之前被调用** 函数名称: SciIsEmpty** 功能描述: 这个函数被应用程序所调用来从查看串行口上是否有可以利用的数据,如果至少有一个数据可用函数返回** false,否则返回ture** 输出: FALSE 如果接收缓冲区至少有一个字节可用** TURE 接收缓冲区为空** 功能描述: 这个函数被应用程序所调用来从查看发送缓冲区是否可以再放进去数据,如果发送缓冲区为满返回TURE,** 否则返回FALSE** 输出: FALSE 发送缓冲区为空** TURE 发送缓冲区为满** 函数名称: SciGetChar** 功能描述: 这个函数被应用程序所调用来发送一个字节的数据到通信口** 输入: 'c',要发送的字符** 输出: SCI_NO_ERR 字符成功的插入了缓冲区** SCI_TX_FULL 发送缓冲区满** 函数名称: SciPutRxChar** 功能描述: 这个函数被中断程序所调用来向接收缓冲区写入一个字节的数据** 输入: 'c',要向缓冲区写入的数据,如果缓冲区为满,则写入的数据将会丢失** 函数名称: PutCharToSci** 功能描述: 这个函数被用户程序来调用向串行口来发送字符** 输入: 'TxChar',发送字符的地址** 函数名称: PutDataToSci** 功能描述: 这个函数被用户程序来调用向串行口来发送十进制数** 输入: 'TxData',发送数据** 函数名称: PutBinaryToSci** 功能描述: 这个函数被用户程序来调用向串行口来发送二进制数据** 输入: 'TxBinary',发送的数据** 函数名称: SciTX_RXIsr** 功能描述: 串口中断服务子程序十.Hardware.c** 这个文件用来写所有的HCS12硬件相关的初始化代码,将这些初始化函数放在启动代码中,也可以放在** 相应任务的初始化部分。
含代码uC_OS-II实验指导书
µC_OS-II实验指导书µC/OS-II实验内容简介1 任务管理实验此实验的目的是让读者理解嵌入式操作系统中任务管理的基本原理,了解任务的各个基本状态及其变迁过程;掌握µC/OS-II中任务管理的基本方法(创建、启动、挂起和解挂任务);熟练使用µC/OS-II任务管理的基本系统调用。
2 优先级反转实验通过此实验读者可以了解在基于抢占式嵌入式实时操作系统并有共享资源的应用中,出现优先级反转现象的原理。
优先级反转发生在有多个任务共享资源的情况下,高优先级任务被低优先级任务阻塞,并等待低优先级任务执行的现象。
3 优先级继承实验通过此实验读者可以了解嵌入式实时操作系统µC/OS-II解决优先级反转的策略——优先级继承的原理,以此解决低优先级任务在占用了共享资源的情况下,被高优先级任务抢占了CPU 使用权而导致的优先级反转的问题。
4 哲学家就餐实验通过经典的哲学家就餐应用,读者可以了解如何利用嵌入式实时操作系统µC/OS-II的信号量机制来对共享资源进行互斥访问。
5 内存管理实验通过此实验读者可以了解嵌入式实时操作系统µC/OS-II中的内存管理的原理,包括对内存的分配和回收。
6 时钟中断实验通过此实验读者可以了解嵌入式实时操作系统µC/OS-II中,时钟中断的使用情况。
7 消息队列实验通过此实验读者可以了解嵌入式实时操作系统µC/OS-II中的消息队列机制。
读者可以了解一个应用中的任务是如何进行通信的,如何能使它们相互协调工作。
实验1 任务的基本管理1 实验目的✓理解任务管理的基本原理,了解任务的各个基本状态及其变迁过程;✓掌握µC/OS-II中任务管理的基本方法(创建、启动、挂起、解挂任务);✓熟练使用µC/OS-II任务管理的基本系统调用。
2 实验原理及程序结构2.1 实验设计为了展现任务的各种基本状态及其变迁过程,本实验设计了Task0、Task1两个任务:任务Task0不断地挂起自己,再被任务Task1解挂,两个任务不断地切换执行。
uCOS-II实时操作系统内核源代码注释
/*********************************************************************************************************** uC/OS-II* 实时操作内核* 内存管理** (c) 版权 1992-2002, Jean J. Labrosse, Weston, FL* All Rights Reserved** 文件名 : OS_MEM.C* 作者 : Jean J. Labrosse* 注释 : 彭森 2007/9/2**********************************************************************************************************/#ifndef OS_MASTER_FILE#include "includes.h"#endif#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)/*********************************************************************************************************** 创建一个内存分区** 说明 : 创建一个固定大小的内存分区,这个内存分区通过uC/OS-II管理。
** 参数 : addr 内存分区的起始地址** nblks 来自分区的内存块的数目.** blksize 每个内存分区中的内存块的大小.** err 指向一个变量包含错误的信息,这个信息通过这个函数或其他来设置:** OS_NO_ERR 内存分区创建正确返回值. * OS_MEM_INVALID_ADDR 指定的是无效地址作为分区的内存存储空间* OS_MEM_INVALID_PART 没有未使用的有用的分区* OS_MEM_INVALID_BLKS 使用者指定一个无效的内存块(必须 >= 2)* OS_MEM_INVALID_SIZE 使用者指定一个无效的内存空间值* (必须大于指针的空间大小) * 返回值 : != (OS_MEM *)0 分区被创建* == (OS_MEM *)0 分区没有被创建由于无效的参数,没有未使用的分区可用**********************************************************************************************************/OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err){#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register 为CPU状态寄存器分配存储空间 */OS_CPU_SR cpu_sr;#endifOS_MEM *pmem;INT8U *pblk;void **plink;INT32U i;#if OS_ARG_CHK_EN > 0if (addr == (void *)0) { /* Must pass a valid address for the memory part. 必须是一个有效的内存部分*/*err = OS_MEM_INVALID_ADDR;return ((OS_MEM *)0);}if (nblks < 2) { /* Must have at least 2 blocks per partition 每个分区至少有两个分区*/*err = OS_MEM_INVALID_BLKS;return ((OS_MEM *)0);}if (blksize < sizeof(void *)) { /* Must contain space for at least a pointer 必须包含空间至少有一个指针*/*err = OS_MEM_INVALID_SIZE;return ((OS_MEM *)0);}#endifOS_ENTER_CRITICAL();pmem = OSMemFreeList; /* Get next free memory partition 得到下一个未使用的内存分区*/if (OSMemFreeList != (OS_MEM *)0) { /* See if pool offree partitions was empty 查看是否有未使用的分区空间是空的*/OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;}OS_EXIT_CRITICAL();if (pmem == (OS_MEM *)0) { /* See if we have a memory partition 查看是否我们有一个内存分区*/*err = OS_MEM_INVALID_PART;return ((OS_MEM *)0);}plink = (void **)addr; /* Create linked list of free memory blocks 创建未使用的内存块的可连接的列表*/pblk = (INT8U *)addr + blksize;for (i = 0; i < (nblks - 1); i++) {*plink = (void *)pblk;plink = (void **)pblk;pblk = pblk + blksize;}*plink = (void *)0; /* Last memory block points to NULL 最后的内存块指针指向NULL*/pmem->OSMemAddr = addr; /* Store start address of memory partition 保存内存分区的起始地址*/pmem->OSMemFreeList = addr; /* Initialize pointer to pool of free blocks 为未使用的内存块初始化指针*/pmem->OSMemNFree = nblks; /* Store number of free blocks in MCB 在内存控制块中保存许多未使用的内存块*/pmem->OSMemNBlks = nblks;pmem->OSMemBlkSize = blksize; /* Store block size of each memory blocks 保存每个内存块的块大小*/*err = OS_NO_ERR;return (pmem);}/*$PAGE*//********************************************************************** ************************************* 得到一个内存控制块** 说明 : 从分区中得到一个内存块** 参数 : pmem 指针指向一个内存分区控制块** err 指向一个变量包含一个错误信息,这个错误信息通过这个函数或其他来设计** OS_NO_ERR 假如内存分区被正确的创建. * OS_MEM_NO_FREE_BLKS 假如没有更多的内存块被分配给调用者* OS_MEM_INVALID_PMEM 假如已经为'pmem'通过一个空指针** 返回值 : 一个指针指向一个内存控制块,假如没有察觉错误* 一个指针指向空指针,假如有错误被察觉到********************************************************************* *************************************/void *OSMemGet (OS_MEM *pmem, INT8U *err){#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register 为CPU状态寄存器分配存储空间 */OS_CPU_SR cpu_sr;#endifvoid *pblk;#if OS_ARG_CHK_EN > 0if (pmem == (OS_MEM *)0) { /* Must point to a valid memory partition 必须指向一个有效的内存分区 */*err = OS_MEM_INVALID_PMEM;return ((OS_MEM *)0);}#endifOS_ENTER_CRITICAL();if (pmem->OSMemNFree > 0) { /* See if there are any free memory blocks 查看是否有其他未使用的内存块*/pblk = pmem->OSMemFreeList; /* Yes, point to next free memory block 是的,指针指向下一个未使用的内存块*/ pmem->OSMemFreeList = *(void **)pblk; /* Adjust pointer to new free list 调整指针指向一个新的未使用的空间列表*/pmem->OSMemNFree--; /* Oneless memory block in this partition 在这个分区中减少一个内存块*/OS_EXIT_CRITICAL();*err = OS_NO_ERR; /* Noerror 没有错误*/return (pblk); /* Return memory block to caller 返回内存控制块给调用者*/}OS_EXIT_CRITICAL();*err = OS_MEM_NO_FREE_BLKS; /* No, Notify caller of empty memory partition 告知调用者是空的内存分区*/return ((void *)0); /* Return NULL pointer to caller 返回NULL个调用者*/}/*$PAGE*//********************************************************************** ************************************* 释放一个内存块** 说明 : 返回一个内存块给分区** 参数 : pmem 指针指向内存分区控制块** pblk 指针指向被保留的内存块.** 返回值 : OS_NO_ERR 假如内存块是被插入的分区* OS_MEM_FULL 假如返回一个已经全部内存分区的内存块* (你释放了更多你分配的内存块!)* OS_MEM_INVALID_PMEM 假如指针'pmem'指向NULL。
UCOSII 详解part3
/*检查优先级有效性*/
return (OS_ERR_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *)0) {
/*被挂起的任务必须存在*/
OS_EXIT_CRITICAL();
}
代码中(1)处为判断要恢复的任务是否为被OSTaskSuspend挂起。当然,如果对应优先
级的任务并没有被OSTaskSuspend挂起,就谈不上使用OSTaskResume恢复。将要恢复的任务
称为目标任务,目标任务的控制块称为目标TCB,那么,前面将目标任务的TCB的地址已经
赋值给了ptcb,目标TCB的OSTCBStat从低到高的第4位标志着任务是否被挂起。而宏OS_ST
在OSTaskSuspend挂起一个任务的时候,要修改就绪表和就绪组,取消任务的就绪标志 ;那么当恢复一个任务的时候,应该加上就绪标志。另外,对于挂起的标志,是在任务控制 块中的OSTCBStat从低到高的第4位,因此,如果恢复一个任务,应该看这一位是否已经被 置位,如果没有被置位,那么恢复操作也应该是无效的。最后,如果一切正常,再将该位进 行复位。
#define OS_STAT_RDY 0x00u #define OS_STAT_SEM 0x01u #define OS_STAT_MBOX 0x02u #define OS_STAT_Q 0x04u #define OS_STAT_SUSPEND 0x08u
/*未等待*/ /*等待信号量*/ /*等待邮箱*/
(1)
OS_ENTER_CRITICAL();
if (ptcb->OSTCBDly != 0u) { /*如果该任务设置了时间延时或事件等待延时*/
uCOSII的源代码
052 INT16U const OSFlagNameSize = OS_FLAG_NAME_SIZE; /* Size (in bytes) of flag names */
053
054 INT16U const OSLowestPrio = OS_LOWEST_PRIO;
069
070 INT16U const OSPtrSize = sizeof(void *); /* Size in Bytes of a pointer */
071
072 INT16U const OSQEn = OS_Q_EN;
022 */
023
024 INT16U const OSDebugEn = OS_DEBUG_EN; /* Debug constants are defined below */
025
026 #if OS_DEBUG_EN > 0
048 INT16U const OSFlagNodeSize = 0;
049 INT16U const OSFlagWidth = 0;
050 #endif
051 INT16U const OSFlagMax = OS_MAX_FLAGS;
083
084 INT16U const OSStkWidth = sizeof(OS_STK); /* Size in Bytes of a stack entry */
085
086 INT16U const OSTaskCreateEn = OS_TASK_CREATE_EN;
087 INT16U const OSTaskCreateExtEn = OS_TASK_CREATE_EXT_EN;
uCOS-II源码详解
uC/OS-II源码分析(总体思路一)首先从main函数开始,下面是uC/OS-II main函数的大致流程:main() {OSInit();TaskCreate(...);OSStart(); }首先是调用OSInit进行初始化,然后使用TaskCreate创建几个进程/Task,最后调用OSStart,操作系统就开始运行了。
OSInit最先看看OSInit完成哪些初始化:void OSInit (void){#if OS_VERSION >= 204OSInitHookBegin();#endifOS_InitMisc();OS_InitRdyList();OS_InitTCBList();OS_InitEventList();#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)OS_FlagInit();#endif#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)OS_MemInit();#endif#if (OS_Q_EN > 0) && (OS_MAX_QS > 0)OS_QInit();#endifOS_InitTaskIdle();#if OS_TASK_STAT_EN > 0OS_InitTaskStat();#endif#if OS_VERSION >= 204OSInitHookEnd();#endif#if OS_VERSION >= 270 && OS_DEBUG_EN > 0OSDebugInit();#endif}OS_InitMisc()完成的是一些其其他他的变量的初始化:OSIntNesting = 0;OSLockNesting = 0;OSTaskCtr = 0;OSRunning = FALSE;OSCtxSwCtr = 0;OSIdleCtr = 0L;其中包括:中断嵌套标志OSIntNesting,调度锁定标志OSLockNesting,OS标志OSRunning 等。
嵌入式系统教学课件:ucos-ii代码总结分析
/*任务的状态*/
INT8U OSTCBPrio;
/*任务的优先级*/
其他……
} OS_TCB;
21
栈指针
OSTCBStkPtr:指向当前任务栈顶的指针 ,每个任务可以有自己的栈,栈的容量可 以是任意的;
OS:栈的容量,用可容纳的指
统计任务OSTaskStat(),提供运行时间统计。每 秒钟运行一次,计算当前的CPU利用率。其优先级 是OS_LOWEST_PRIOR-1,可选。
19
任务控制块TCB
任务控制块 OS_TCB是描述一个任务的核 心数据结构,存放了它的各种管理信息 ,包括任务堆栈指针,任务的状态、优 先级,任务链表指针等;
OSTaskCreateExt() 提问:C/OS-II中的任务是进程还是线程?
15
任务主函数
一个任务通常是一个无限循环(返回值类型void)
void MyTask(void *pdata) {
while (1) {
do something; waiting; do something; } }
绝大部分 C/OS-II的源码是用移植性很强的ANSI C写的。和微处理器 硬件相关的那部分是用汇编语言写的。汇编语言写的部分已经压到最 低限度,使得 C/OS-II便于移植到其他微处理器上。 C/OS-II可以在 绝大多数8位、16位、32位以至64位微处理器、微控制器 、数字信号处 理器(DSP)上运行。
一旦任务建立了,任务控制块OS_TCB将 被赋值。
20
任务控制块TCB
typedef struct os_tcb
{
栈指针;
INT16U OSTCBId;
/*任务的ID*/
ucosII详解
第1章范例 - - - - - - - - - - - - - - - - - - - - - - - - - - 11.00 安装µC/OS-II- - - - - - - - - - - - - - - - - - - - - - - - - - -11.01 INCLUDES.H- - - - - - - - - - - - - - - - - - - - - - - - - - - - 21.02 不依赖于编译的数据类型- - - - - - - - - - - - - - - - - - - - - - 21.03 全局变量- - - - - - - - - - - - - - - - - - - - - - - - - - - - - 31.04 OS_ENTER_CRITICAL() 和 OS_EXIT_CRITICAL()- - - - - - - - - - - - -51.05 基于PC的服务- - - - - - - - - - - - - - - - - - - - - - - - - - -51.05.01 字符显示- - - - - - - - - - - - - - - - - - - - - - - - - - - - - 51.05.02 花费时间的测量- - - - - - - - - - - - - - - - - - - - - - - - - - 61.05.03 其他函数- - - - - - - - - - - - - - - - - - - - - - - - - - - - - 61.06 应用µC/OS-II 的范例- - - - - - - - - - - - - - - - - - - - - - - 71.07 例1- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -81.07.01 main()- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 81.07.02 TaskStart()- - - - - - - - - - - - - - - - - - - - - - - - - - - -111.07.03 TaskN()- - - - - - - - - - - - - - - - - - - - - - - - - - - - -121.08 例2- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 131.08.01 main()- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 141.08.02 TaskStart()- - - - - - - - - - - - - - - - - - - - - - - - - - - - 15 1.08.03 TaskN()- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16 1.09 例3 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 191.09.01 main() - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 20 1.09.02 任务 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 21 1.09.03 注意 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 24第2章实时系统概念- - - - - - - - - - - - - - - - - - - - - - - - - - 272.0 前后台系统(FOREGROUND/BACKGROUND SYSTEM) - - - - - - - - - - - - 27 2.1 代码的临界段- - - - - - - - - - - - - - - - - - - - - - - - - - - - 28 2.2 资源- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -28 2.3 共享资源- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -28 2.4 多任务- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -28 2.5 任务- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -29 2.6 任务切换(CONTEXT SWITCH OR TASK SWITCH) - - - - - - - - - - - - - - -30 2.7 内核(KERNEL)- - - - - - - - - - - - - - - - - - - - - - - - - - -302.8 调度(SCHEDULER)- - - - - - - - - - - - - - - - - - - - - - - - - 312.9 不可剥夺型内核(NON-PREEMPTIVE KERNEL)- - - - - - - - - - - - - - - 31 2.10 可剥夺型内核- - - - - - - - - - - - - - - - - - - - - - - - - - - - 32 2.11 可重入性(REENTRANCY)- - - - - - - - - - - - - - - - - - - - - - - 33 2.12 时间片轮番调度法- - - - - - - - - - - - - - - - - - - - - - - - - - 35 2.13 任务优先级- - - - - - - - - - - - - - - - - - - - - - - - - - - - -352.14 2.14静态优先级 - - - - - - - - - - - - - - - - - - - - - - - - - - 352.15 动态优先级 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 35 2.16 优先级反转 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 35 2.17 任务优先级分配 - - - - - - - - - - - - - - - - - - - - - - - - - - -37 2.18 互斥条件- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 39 2.18.1 关中断和开中断- - - - - - - - - - - - - - - - - - - - - - - - - - - 39 2.18.2 测试并置位- - - - - - - - - - - - - - - - - - - - - - - - - - - - - 40 2.18.3 禁止,然后允许任务切换- - - - - - - - - - - - - - - - - - - - - - - - 40 2.18.4 信号量(SEMAPHORES) - - - - - - - - - - - - - - - - - - - - - - - - - 41 2.19 死锁(或抱死)(DEADLOCK (OR DEADLY EMBRACE))- - - - - - - - - - - - -46 2.20 同步- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 462.21 事件标志(EVENT FLAGS) - - - - - - - - - - - - - - - - - - - - - - - 482.22 任务间的通讯(INTERTASK COMMUNICATION) - - - - - - - - - - - - - - - - 482.23 消息邮箱(MESSAGE MAIL BOXES) - - - - - - - - - - - - - - - - - - - -492.24 消息队列(Message Queue) - - - - - - - - - - - - - - - - - - - - - - 502.25 中断- - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - - - 512.26 中断延迟- - - - - - - - - - - - - - - - - - - - - - - - - -- - - - - 512.27 中断响应- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 52 2.28 中断恢复时间(Interrupt Recovery) - - - - - - - - - - - - - - - - - - 522.29 中断延迟、响应和恢复- - - - - - - - - - - - - - - - - - - - - - - - 532.30 中断处理时间- - - - - - - - - - - - - - - - - - - - - - - - - - - - 532.31 非屏蔽中断(NMI) - - - - - - - - - - - - - - - - - - - - - - - - - - 542.32 时钟节拍(Clock Tick) - - - - - - - - - - - - - - - - - - - - - - - - 562.33 对存储器的需求- - - - - - - - - - - - - - - - - - - - - - - - - - - 582.34 使用实时内核的优缺点- - - - - - - - - - - - - - - - - - - - - - - - 592.35 实时系统小结- - - - - - - - - - - - - - - - - - - - - - - - - - - - 60第3章内核结构- - - - - - - - - - - - - - - - - - - - - - - - - - - - - 623.0 临界段(Critical Sections) - - - - - - - - - - - - - - - - - - - - - 623.1 任务- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 623.2 任务状态- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 643.3 任务控制块(Task Control Blocks, OS_TCBs)- - - - - - - - - - - - - - 653.4 就绪表(Ready List)- - - - - - - - - - - - - - - - - - - - - - - - 683.5 任务调度(Task Scheduling)- - - - - - - - - - - - - - - - - - - - - 713.6 给调度器上锁和开锁(Locking and UnLocking the Scheduler) - - - - - - - 723.7 空闲任务(Idle Task) - - - - - - - - - - - - - - - - - - - - - - - - 733.8 统计任务- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 743.9 μC/OS中的中断处理- - - - - - - - - - - - - - - - - - - - - - - - - -783.10 时钟节拍- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 823.11 μC/OS-Ⅱ初始化- - - - - - - - - - - - - - - - - - - - - - - - - - 843.12 μC/OS-Ⅱ的启动- - - - - - - - - - - - - - - - - - - - - - - - - - 853.13 获取当前μC/OS-Ⅱ的版本号- - - - - - - - - - - - - - - - - - - - - - 883.14 OSEvent???()函数- - - - - - - - - - - - - - - - - - - - - - - - - - 89第4章任务管理4.0 建立任务,OSTaskCreate() - - - - - - - - - - - - - - - - - - - - - 914.1 建立任务,OSTASKCREATEEXT() - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 924.2 任务堆栈 94.3 堆栈检验,OSTASKSTKCHK() 114.4 删除任务,OSTASKDEL() 144.5 请求删除任务,OSTASKDELREQ() 174.6 改变任务的优先级,OSTASKCHANGEPRIO() 204.7 挂起任务,OSTASKSUSPEND() 234.8 恢复任务,OSTASKRESUME() 254.9 获得有关任务的信息,OSTASKQUERY() 26第5章时间管理5.0 任务延时函数,OSTIMEDLY() 15.1 按时分秒延时函数 OSTIMEDLYHMSM() 35.2 让处在延时期的任务结束延时,OSTIMEDLYRESUME() 45.3 系统时间,OSTIMEGET()和OSTIMESET() 6第6章任务之间的通讯与同步6.0 事件控制块ECB 26.1 初始化一个ECB块,OSEVENTWAITLISTINIT() 66.2 使一个任务进入就绪状态,OSEVENTTASKRDY() 76.3 使一个任务进入等待状态, OSEVENTTASKWAIT() 96.4 由于等待超时将一个任务置为就绪状态, OSEVENTTO() 96.5 信号量106.5.1 建立一个信号量, OSSemCreate() 116.5.2 等待一个信号量, OSSemPend() 126.5.3 发送一个信号量, OSSemPost() 146.5.4 无等待地请求一个信号量, OSSemAccept() 166.5.5 查询一个信号量的当前状态, OSSemQuery() 176.6 邮箱186.6.1 建立一个邮箱,OSMboxCreate() 196.6.2 等待一个邮箱中的消息,OSMboxPend() 206.6.3 发送一个消息到邮箱中,OSMboxPost() 226.6.4 无等待地从邮箱中得到一个消息, OSMboxAccept() 246.6.5 查询一个邮箱的状态, OSMboxQuery() 256.6.6 使用邮箱作为二值信号量266.6.7 使用邮箱实现延时,而不使用OSTimeDly() 276.7 消息队列286.7.1 建立一个消息队列,OSQCreate() 316.7.2 等待一个消息队列中的消息,OSQPend() 336.7.3 向消息队列发送一个消息(FIFO),OSQPost() 356.7.4 向消息队列发送一个消息(LIFO),OSQPostFront() 376.7.5 无等待地从一个消息队列中取得消息, OSQAccept() 396.7.6 清空一个消息队列, OSQFlush() 406.7.7 查询一个消息队列的状态,OSQQuery() 416.7.8 使用消息队列读取模拟量的值426.7.9 使用一个消息队列作为计数信号量43第7章内存管理7.0 内存控制块 17.1 建立一个内存分区,OSMEMCREATE() 37.2 分配一个内存块,OSMEMGET() 67.3 释放一个内存块,OSMEMPUT() 77.4 查询一个内存分区的状态,OSMEMQUERY() 87.5 USING MEMORY PARTITIONS 97.6 等待一个内存块 11第8章移植µC/OS-Ⅱ8.00 开发工具8.01 目录和文件8.02 INCLUDES.H8.03 OS_CPU.H8.03.01 与编译器相关的数据类型8.03.02 OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()8.03.03 OS_STK_GROWTH8.03.04 OS_TASK_SW()8.04 OS_CPU_A.ASM8.04.01 OSStartHighRdy()8.04.02 OSCtxSw()8.04.03 OSIntCtxSw()8.04.04 OSTickISR()8.05 OS_CPU_C.C8.05.01 OSTaskStkInt()8.05.02 OSTaskCreateHook()8.05.03 OSTaskDelHook()8.05.04 OSTaskSwHook()8.05.05 OSTaskStatHook()8.05.06 OSTimeTickHook()第9章µC/OS-II在Intel 80x86上的移植9.00 开发工具9.01 目录和文件9.02 INCLUDES.H文件9.03 OS_CPU.H文件9.03.01 数据类型9.0302 代码临界区第一章:范例在这一章里将提供三个范例来说明如何使用µC/OS-II。
UCOS-II编程要点讲解
OSTaskQuery( ) INT8U OSTaskQuery ( INT8U prio, OS_TCB *pdata);
3
UCOSII 编程要点 参数:prio 为指定要获取 TCB 内容的任务优先级,也可以指定参数 OS_PRIO_SELF,获取调用 任务的信息。pdata 指向一个 OS_TCB 类型的数据结构,容纳返回的任务 TCB 的一个拷贝 OSTimeGet():系统时间;
UCOSII 编程要点
OSStatInit():系统统计初始化;
OSStatInit ( )
void OSStatInit (void);
OSTaskStatHook():任务统计外界接入函数;
OSTaskSuspend(OS_PR1O_SELF):
OSTaskStkChk():任务堆栈检查;
OSTaskStkChk( ) INT8U OSTaskStkChk ( INT8U prio, OS_STK_DATA *pdata); 参数:prio 为指定要获取堆栈信息的任务优先级,也可以指定参数 OS_PRIO_SELF,获取调用 任务本身的信息。pdata 指向一个类型为 OS_STK_DATA 的数据结构。 OSSched():任务调度;
一、任务状态
UCOSII 编程要点
二、系统函数
OSIint():系统初始化函数,并建立空闲任务; OSTastCreat(void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio):任
务建立,进入就绪态准备运行; 参数:task 是指向任务代码的指针。Pdata 指向一个数据结构,该结构用来在建立任务时向 任务传递参数。ptos 为指向任务堆栈栈顶的指针。prio 为任务的优先级 OSTaskCreatExt(void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio, INT16U id, OS_STK *pbos, INT32U stk_size, void *pext, INT16U opt): 任务建立,进入就绪态准备运行; OSTaskChangePrio():改变任务的优先级; INT8U OSTaskChangePrio (INT8U oldprio, INT8U newprio); 参数:oldprio 是任务原先的优先级。newprio 是任务的新优先级。 OSTaskDel():任务睡眠; OSTaskDel() INT8U OSTaskDel (INT8U prio); 参数:prio 为指定要删除任务的优先级,也可以用参数 OS_PRIO_SELF 代替 OSStart():启动任务; OSTimeDly():任务延迟,进入等待状态; OSTimeDly( ) void OSTimeDly ( INT16U ticks); 参数:ticks 为要延时的时钟节拍数 OSTimeDlyHMSM():任务延迟,进入等待状态; OSTimeDlyHMSM( ) void OSTimeDlyHMSM( INT8U hours,INT8U minutes,INT8U seconds,INT8U milli);
uCOSII嵌入式的系统示例代码
实用标准文案/*包含与uC/OS-ll 相关的系统调用的头文件 *//*包含与中断控制器相关的头文件*//*包含与中断管理相关的头文件*//*用于时钟中断*/extern void OSStartTimeTick( void ); extern void OSTickISR( void );#defi ne STK_SIZE_TASK 256#defi ne PRIO_TASK3OS_STK StkTask[STK_SIZE_TASK];/*分配给任务的堆栈大小 *//*任务的优先级*//*为任务分配堆栈空间 *//*此函数定义了一个任务 */void YourTask( void *pdata ) {IRQ_Register( OSTickISR, TIMER1_INT ); 一个运行的任务里进行)*/OSStartTimeTick();建立一个任务*/OSTaskCreate( YourTask, 0, & StkTask[STK_SIZE_TASK-1], PRIO_TASK ); OSStart(); /* 开始调度 */return 0; }/*在下面添加任务内容 while( 1 ){ }}/*初始化后,从这里开始执行 int __main( void ) { MX1_AITC_I nit(); IRQ_I nit(); */C 代码*//*初始化中断控制器*/ /*初始化中断管理*/OSI nit();/*初始化uC/OS-ll 内核数据结构*/ //主函数模板 #i nclude "INCLUDES.H" #i nclude"mx1_aitc.h" #i nclude"IRQ.h"/*开启uC/OS-ll 的时钟中断(必须在第 /*//LED 闪烁 //led.c#i nclude "INCLUDES.H" /* 包含与uC/OS-ll 相关的系统调用的头文件*#i nclude "led.h" /* Led 驱动接口函数的说明头文件 */ #i nclude "mx1_gpio.h" /* 包含与通用IO 口相关的头文件 */ #i nclude "mx1_aitc.h" /*包含与中断控制器相关的头文件 */ #i nclude "mx1_uart.h" /*包含与串口相关的头文件 */#in clude "IRQ.h" /*包含与中断管理相关的头文件 */ /*用于时钟中断*/ extern void OSStartTimeTick( void ); extern void OSTickISR( void );#defi ne STK_SIZE_LEDDEMO 256 #define PRIO LEDDEMO 3 /*分配给任务的堆栈大小 */ /*任务的优先级*/ OS_STK StkLedDemo[STK_SIZE_LEDDEMO];/*为任务分配堆栈空间 */ /*此函数定义了一个任务 */ void LedDemo( void *pdata ) { IRQ_Register( OSTicklSR, TIMER1_INT ); 一个运行的任务里进行)*/ OSStartTimeTick(); /*开启uC/OS-ll 的时钟中断(必须在第 /*在下面添加任务内容 */ while( 1 ){ LED_ 0n( LED3 ); OSTimeDlyHMSM( 0, 0, 0, 500 ); LED_ 0n( LED4 );OSTimeDlyHMSM( 0, 0, 0, 500 ); LED_Off( LED4 ); OSTimeDlyHMSM( 0, 0, 0, 500 ); LED_Off( LED3 );OSTimeDlyHMSM( 0, 0, 0, 500 ); }} /*初始化后,从这里开始执行C 代码*//*依次点亮LED*/ /*延时500毫秒*//*依次熄灭LED*/MX1_GPIO_I nit(MX1_GPIO_PC); /* MX1_UART_I nit(COM1); /* IRQ_I nit(); /*LED 」nit( LED3 ); /*LED_ In it( LED4 );MX1_UART_PutStri ng(COM1,"\n\r\n\ruC/OS-ll is ini tializ in g...\n\r",33); OSInit();/*初始化uC/OS-ll 内核数据结构 *//* 建立一个任务 */OSTaskCreate( LedDemo, 0, & StkLedDemo[STK_SIZE_LEDDEMO-1], PRIO_LEDDEMO ); MX1_UART_PutStri ng(COM1,"Ru nnin g...\n\r",12); OSStart();/* 开始调度 */ return 0;int {main( void )MX1_AITC_I nit(); /*初始化中断控制器*/初始化通用IO 端口 C */ 初始化串口 1 */ 初始化中断管理*/ 初始化LED */实用标准文案/*包含与uC/OS-ll 相关的系统调用的头文件 *//*包含与中断控制器相关的头文件 *//*包含与中断管理相关的头文件 */ /* Led 驱动接口函数的说明头文件*//*用于时钟中断*/ extern void OSStartTimeTick( void );extern void OSTickISR( void );OS_STK StkTask[STK_SIZE_TASK];/*此函数定义了一个任务 */void YourTask( void *pdata ) {IRQ_Register( OSTickISR, TIMER1_INT ); /* 开启 uC/OS-ll 的时钟中断(必须在第一个运行的任务里进行)*/OSStartTimeTick(); /*在下面添加任务内容 */LED_Init( LED3 ); /* 初始化 */LED_I nit( LED5 ); LED_I nit( LED7 ); while( 1 ){LED_ On( LED3 );OSTimeDlyHMSM( 0, 0, 0, 500 ); LED_Off( LED3 );OSTimeDlyHMSM( 0, 0, 0, 500 ); LED_ On( LED5 );OSTimeDlyHMSM( 0, 0, 0, 500 ); LED_Off( LED5 );OSTimeDlyHMSM( 0, 0, 0, 500 ); LED_ On( LED7 );OSTimeDlyHMSM( 0, 0, 0, 500 ); LED_Off( LED7 );OSTimeDlyHMSM( 0, 0, 0, 500 );//LED 闪烁 #i nclude "INCLUDES.H" #in elude "mx1 aitc.h" #i nclude"IRQ.h" #i nclude"led.h"#in clude "mx1_gpio.h" #defi ne STK_SIZE_TASK 256 /*分配给任务的堆栈大小 */#defi ne PRIO_TASK 3 /*任务的优先级*//*为任务分配堆栈空间 */}}/*初始化后,从这里开始执行int __main( void ){MX1_AITC_I nit();IRQ」nit();C代码*//*初始化中断控制器*/ /*初始化中断管理*/OSI ni t(); /*初始化uC/OS-ll内核数据结构*//*建立一个任务*/OSTaskCreate( YourTask, 0, & StkTask[STK_SIZE_TASK-1], PRIO_TASK );OSStart(); /* 开始调度*/return 0;}/*包含与uC/OS-ll 相关的系统调用的头文件*//*包含与中断控制器相关的头文件*//*包含与中断管理相关的头文件*//*用于时钟中断*/extern void OSStartTimeTick( void ); extern void OSTickISR( void );256/*分配给任务的堆栈大小*/3/*任务的优先级*/OS_STK StkTask[STK_SIZE_TASK];/*此函数定义了一个任务 */void YourTask( void *pdata ) {IRQ_Register( OSTickISR, TIMER1_INT ); /* 开启 uC/OS-ll 的时钟中断(必须在第一个运行的任务里进行)*/OSStartTimeTick(); /*在下面添加任务内容 */ LED_I nit( LED3 ); LED_I nit( LED4 ); LED_I nit( LED5 ); LED_I nit( LED6 ); LED_I nit( LED7 ); LED_I nit( LED8 ); LED_I nit( LED9 ); LED_I nit( LED10 ); SWITCH 」nit( SW2 ); /* 初始化开关 */SWITCH 」n it( SW3 ); SWITCH 」n it( SW4 ); SWITCH 」n it( SW5 ); SWITCH 」n it( SW6 ); SWITCH 」n it( SW7 ); SWITCH 」n it( SW8 ); SWITCH 」n it( SW9 ); while( 1 ){if( SWITCH_IS_ON( SW2 ))//按钮开关 #i nclude #i nclude #i nclude #i nclude #in clude"INCLUDES.H" "mx1_aitc.h" "IRQ.h" "led.h" "switch.h"#defi ne STK_SIZE_TASK #defi ne PRIO_TASK/*为任务分配堆栈空间*/LED_ On( LED3 );elseLED_Off( LED3 );〃///////////////////////if( SWITCH_IS_ON( SW3 ))LED_ On( LED4 );elseLED_Off( LED4 );/////////////////////////if( SWITCH_IS_ON( SW4 ))LED_ On( LED5 );elseLED_Off( LED5 );//////////////////////////if( SWITCH_IS_ON( SW5 ))LED_ On( LED6 );elseLED_Off( LED6 );/**************************/if( SWITCH_IS_ON( SW6 ))LED_ On( LED7 );elseLED_Off( LED7 );/////////////////////////if( SWITCH_IS_ON( SW7 ))LED_ On( LED8 );elseLED_Off( LED8 );/////////////////////////if( SWITCH_IS_ON( SW8 ))LED_ On( LED9 );elseLED_Off( LED9 );/////////////////////////if( SWITCH_IS_ON( SW9 ))LED_ On( LED10 );elseLED_Off( LED10 );}}/*初始化后,从这里开始执行C代码*/int __main( void ){MX1_AITC_Init(); /*初始化中断控制器*/IRQ_I nit(); /*初始化中断管理*/OSI nit(); /*初始化uC/OS-ll内核数据结构*//*建立一个任务*/OSTaskCreate( YourTask, 0, & StkTask[STK_SIZE_TASK-1], PRIO_TASK );OSStart(); /*开始调度*/return 0;}/*包含与uC/OS-ll 相关的系统调用的头文件*//*包含与中断控制器相关的头文件*//*包含与中断管理相关的头文件 */OSTimeDlyHMSM( 0, 0, 0, 500 ); LED_Off( LED5 );// 主板 I/O LED #i nclude "INCLUDES.H" #i nclude "mx1_aitc.h" #i nclude "IRQ.h" #i nclude "mx1_gpio.h" #i nclude"led.h"/*用于时钟中断*/extern void OSStartTimeTick( void ); extern void OSTickISR( void );#defi ne STK_SIZE_TASK 256 #defi ne PRIO_TASK3OS_STK StkTask[STK_SIZE_TASK];/*分配给任务的堆栈大小 */ /*任务的优先级*//*为任务分配堆栈空间 *//*此函数定义了一个任务 */void YourTask( void *pdata ) {IRQ_Register( OSTickISR, TIMER1_INT ); 一个运行的任务里进行)*/OSStartTimeTick(); /*开启uC/OS-ll 的时钟中断(必须在第/*在下面添加任务内容 */ LED_Init( LED3 ); /* LED 的初始化,需要调用 GPIO 的接口设置函数 */LED_I nit( LED4 ); LED_I nit( LED5 ); LED_I nit( LED6 ); LED_I nit( LED7 ); LED_I nit( LED8 ); LED_I nit( LED9 ); LED_I nit( LED10 ); while( 1 ){LED_ 0n( LED3 );OSTimeDlyHMSM( 0, 0, 0, 500 ); LED_Off( LED3 );OSTimeDlyHMSM( 0, 0, 0, 500 ); LED_ On( LED4 );OSTimeDlyHMSM( 0, 0, 0, 500 ); LED_Off( LED4 );OSTimeDlyHMSM( 0, 0, 0, 500 ); LED_ On( LED5 );OSTimeDlyHMSM( 0, 0, 0, 500 );LED_ On( LED6 );OSTimeDlyHMSM( 0, 0, 0, 500 );LED_Off( LED6 );OSTimeDlyHMSM( 0, 0, 0, 500 );LED_ On( LED7 );OSTimeDlyHMSM( 0, 0, 0, 500 );LED_Off( LED7 );OSTimeDlyHMSM( 0, 0, 0, 500 );LED_ On( LED8 );OSTimeDlyHMSM( 0, 0, 0, 500 );LED_Off( LED8 );OSTimeDlyHMSM( 0, 0, 0, 500 );LED_ On( LED9 );OSTimeDlyHMSM( 0, 0, 0, 500 );LED_Off( LED9 );OSTimeDlyHMSM( 0, 0, 0, 500 );LED_ On( LED10 );OSTimeDlyHMSM( 0, 0, 0, 500 );LED_Off( LED10 );OSTimeDlyHMSM( 0, 0, 0, 500 );}}/*初始化后,从这里开始执行C代码*/int __main( void ){MX1_GPIO_I nit( MX1_GPIO_PC );MX1_AITC_Init(); /*初始化中断控制器*/IRQ_I ni t(); /*初始化中断管理*/OSInit(); /*初始化uC/OS-ll内核数据结构*//*建立一个任务*/OSTaskCreate( YourTask, 0, & StkTask[STK_SIZE_TASK-1], PRIO_TASK );OSStart(); /* 开始调度*/return 0;}//串口通信 #i nclude "INCLUDES.H" /* 包含与uC/OS-ll 相关的系统调用的头文件 */#i nclude "mx1_aitc.h" /*包含与中断控制器相关的头文件*/#i nclude "IRQ.h"/*包含与中断管理相关的头文件*/#i nclude "mx1_gpio.h"#i nclude"mx1_uart.h"#in clude<stri ng.h>/*用于时钟中断*/extern void OSStartTimeTick( void );extern void OSTickISR( void );#defi ne STK_SIZE_TASK 256 #defi ne PRIO_TASK3OS_STK StkTask[STK_SIZE_TASK]; /*分配给任务的堆栈大小 */ /*任务的优先级*//*为任务分配堆栈空间 *//*建立一个任务*/OSTaskCreate( YourTask, 0, & StkTask[STK_SIZE_TASK-1], PRIO_TASK ); OSStart(); /* 开始调度 */return 0; }/*此函数定义了一个任务 */void YourTask( void *pdata ) {char tmp;IRQ_Register( OSTicklSR, TIMER1_INT ); 一个运行的任务里进行)*/OSStartTimeTick(); /*在下面添加任务内容*/MX1_UART_I nit( COM1 );/*开启uC/OS-ll 的时钟中断(必须在第MX1_UART_PutStri ng( COM1, "In put a Char:", strle n("l nput a Char:")); while( 1 ){MX1_UART_GetChar( COM1, &tmp ); /* 显示输入的字符 */MX1_UART_PutChar( COM1, tmp ); }}/*初始化后,从这里开始执行 C 代码*/int __main( void ) {MX1_AITC_Init();IRQ_I nit(); /*初始化中断控制器*/ /*初始化中断管理*/OSI ni t();/*初始化uC/OS-ll 内核数据结构*///AD 转换//misc.c adc0809.c #i nclude "INCLUDES.H" /*包含与uC/OS-ll 相关的系统调用的头文件*/#include "mx1_aitc.h"/*包含与中断控制器相关的头文件 */#i nclude "IRQ.h" /*包含与中断管理相关的头文件 */#i nclude "mx1_gpio.h"#i nclude "mx1_uart.h"#include"adc0809.h"#include"misc.h"/*用于时钟中断*/extern void OSStartTimeTick( void );extern void OSTickISR( void );/*此函数定义了一个任务 */ void YourTask( void *pdata ) {char tmp[16];IRQ_Register( OSTicklSR, TIMER1_INT ); /* 开启 uC/OS-ll 的时钟中断(必须在第一个运行的任务里进行)*/OSStartTimeTick(); /*在下面添加任务内容 */ADC0809」ni t(); while( 1 ){/*将电压值放大10 0倍,通过串口显示 */MX1_UART_PutString( COM1,tmp, IntToStr(500*ADC0809_READ_CHANNEL( 4 )/256,tmp, 16));MX1_UART_PutChar( COM1,' ');OSTimeDlyHMSM( 0, 0, 1,0 ); }}/*初始化后,从这里开始执行 C 代码*/int __main( void ) {MX1_AITC_Init(); /*初始化中断控制器 */ IRQ_I ni t();/*初始化中断管理*/MX1_UART_I nit( COM1 );#defi ne STK_SIZE_TASK 256 #defi ne PRIO_TASK3OS_STK StkTask[STK_SIZE_TASK];/*分配给任务的堆栈大小 */ /*任务的优先级*//*为任务分配堆栈空间 */OSInit(); /*初始化uC/OS-ll内核数据结构*//*建立一个任务*/OSTaskCreate( YourTask, 0, & StkTask[STK_SIZE_TASK-1], PRIO_TASK );OSStart(); /* 开始调度*/return 0;}//LCD#i nclude "INCLUDES.H" /* 包含与uC/OS-ll相关的系统调用的头文件*/ #i nclude "mx1_aitc.h" /* 包含与中断控制器相关的头文件*/#i nclude "IRQ.h" /*包含与中断管理相关的头文件*/#i nclude "mx1_gpio.h"#i nclude "misc.h"#i nclude "mx1」cdc.h"/*用于时钟中断*/extern void OSStartTimeTick( void );extern void OSTickISR( void );#defi ne STK_SIZE_TASK 256 /*分配给任务的堆栈大小*/#define PRIO_TASK 3 /* 任务的优先级*/OS_STK StkTask[STK_SIZE_TASK]; /* 为任务分配堆栈空间*//*此函数定义了一个任务*/void YourTask( void *pdata ){int i;IRQ_Register( OSTicklSR, TIMER1_INT ); /* 开启uC/OS-ll 的时钟中断(必须在第一个运行的任务里进行)*/OSStartTimeTick();/*在下面添加任务内容*/MX1_LCDC_DrawRect( 0, 0, 319, 239, 50, 50, LS_SOLID, FS_SOLID );MX1_LCDC_DrawSquare( 0,0, 120, 15, 31, LS_SOLID, FS_SOLID );MX1_LCDC_DrawCircle( 60, 180,60, 15, 47, LS_SOLID, FS_DOTDOT );MX1_LCDC_DrawRect( 120, 120, 319, 239, 50, 47, LS_SOLID, FS_DOTDOT );MX1_LCDC_DrawEllipse( 120, 0, 319, 120, 31,47, LS_SOLID, FS_SOLID );i=0;while( 1 ){if( i++%2 )MX1_LCDC_DrawSquare( 0,0, 120, 15, 31, LS_SOLID, FS_SOLID );elseMX1_LCDC_DrawSquare( 0,0, 120, 31, 15, LS_SOLID, FS_SOLID );OSTimeDlyHMSM( 0, 0, 1,0 );}}/*初始化后,从这里开始执行C代码*/int __main( void ){un sig ned in t palette[LCDC_CMRAM_SIZE]; 〃#defi ne LCDC_CMRAM_SIZE 256int i;MX1_AITC_I nit(); IRQ_I nit();/*初始化中断控制器*/ /*初始化中断管理*/OSI nit(); /*初始化uC/OS-ll内核数据结构*///初始化LCDMX1_LCDC_I nit(LCDC_PANEL_WIDTH, //屏幕宽320LCDC_PANEL_HEIGHT, //屏幕咼240LCDC_INIT_STARTX, //显存帧X 0LCDC_INIT_STARTY, //显存帧Y 0LCDC_VPW, //虚拟页宽1024*3LCDC_PANEL_CONF, //显示屏参数LCDC_BPP ); //像素颜色位数8 //初始化调色板for( i=0; i<16; i++ ){palette[i] = RGB( i, 0, 0 );palette[i+16] = RGB( 0, i, 0 );palette[i+32] = RGB( 0, 0, i );palette[i+48] = RGB( i, i, i );}MX1_LCDC_CMRAM_Set( palette );/*建立一个任务*/OSTaskCreate( YourTask, 0, & StkTask[STK_SIZE_TASK-1], PRIO_TASK );OSStart(); /* 开始调度*/return 0;}/*包含与uC/OS-ll 相关的系统调用的头文件 *//*包含与中断控制器相关的头文件 */ /*包含与中断管理相关的头文件 */ /* Led 驱动接口函数的说明头文件 */#in clude "mx1_gpio.h"#i nclude"misc.h"#in clude "mx1」cdc.h" /*用于时钟中断*/ extern void OSStartTimeTick( void ); extern void OSTickISR( void );#defi ne STK_SIZE_TASK1 256/*分配给任务的堆栈大小*/#defi ne STK_SIZE_TASK2256#defi ne STK_SIZE_TASK3256#define PRIO TASK24 #defi ne PRIO_TASK35OS_STK StkTask1[STK_SIZE_TASK1]; OS_STK StkTask2[STK_SIZE_TASK2]; OS_STK StkTask3[STK_SIZE_TASK3];/*此函数定义了一个任务 */void YourTask1( void *pdata ) {IRQ_Register( OSTickISR, TIMER1_INT ); 一个运行的任务里进行)*/ OSStartTimeTick(); /*在下面添加任务内容 */ LED_Init( LED3 ); /* 初始化 */LED_I nit( LED4 ); LED_I nit( LED5 ); LED_I nit( LED6 ); while( 1 ){LED_ On( LED3 );OSTimeDlyHMSM( 0, 0, 0, 500 ); LED_Off( LED3 );OSTimeDlyHMSM( 0, 0, 0, 500 );//多任务 #i nclude "INCLUDES.H" #in elude "mx1 aitc.h" #i nclude "IRQ.h" #i nclude "led.h" #defi ne PRIO_TASK1/*任务的优先级*/ /*为任务分配堆栈空间*//*开启uC/OS-ll 的时钟中断(必须在第LED_ On( LED4 );OSTimeDlyHMSM( 0, 0, 0, 500 );LED_Off( LED4 );OSTimeDlyHMSM( 0, 0, 0, 500 );LED_ On( LED5 );OSTimeDlyHMSM( 0, 0, 0, 500 );LED_Off( LED5 );OSTimeDlyHMSM( 0, 0, 0, 500 );LED_ On( LED6 );OSTimeDlyHMSM( 0, 0, 0, 500 );LED_Off( LED6 ); OSTimeDlyHMSM( 0, 0, 0, 500 );}}/*此函数定义了一个任务*/void YourTask2( void *pdata ){/*在下面添加任务内容*/LED_Init( LED7 ); /* 初始化*/LED_I nit( LED8 );LED_I nit( LED9 );LED_I nit( LED10 );while( 1 ){LED_ On( LED7 );OSTimeDlyHMSM( 0, 0, 0, 200 );LED_ On( LED8 );OSTimeDlyHMSM( 0, 0, 0, 200 );LED_ On( LED9 );OSTimeDlyHMSM( 0, 0, 0, 200 );LED_ On( LED10 );OSTimeDlyHMSM( 0, 0, 0, 200 );LED_Off( LED10 );OSTimeDlyHMSM( 0, 0, 0, 200 );LED_Off( LED9 );OSTimeDlyHMSM( 0, 0, 0, 200 );LED_Off( LED8 );OSTimeDlyHMSM( 0, 0, 0, 200 );LED_Off( LED7 );OSTimeDlyHMSM( 0, 0, 0, 200 );}}/*此函数定义了一个任务*/void YourTask3( void *pdata ) {int i;IRQ_Register( OSTicklSR, TIMER1_INT ); /* 开启 uC/OS-ll 的时钟中断(必须在第一个运行的任务里进行)*/OSStartTimeTick(); /*在下面添加任务内容*/MX1_LCDC_DrawRect( 0, 0, 319, 239, 50, 50, LS_SOLID, FS_SOLID ); MX1_LCDC_DrawSquare( 0,0, 120, 15, 31, LS_SOLID, FS_SOLID ); MX1_LCDC_DrawCircle( 60, 180,60, 15, 47, LS_SOLID, FS_DOTDOT ); MX1_LCDC_DrawRect( 120, 120, 319, 239, 50, 47, LS_SOLID, FS_DOTDOT ); MX1_LCDC_DrawEllipse( 120, 0, 319, 120, 31,47, LS_SOLID, FS_SOLID ); i=0; while( 1 ){if( i++%2 )MX1_LCDC_DrawSquare( 0,0, 120, 15, 31, LS_SOLID, FS_SOLID ); elseMX1_LCDC_DrawSquare( 0,0, 120, 31, 15, LS_SOLID, FS_SOLID ); OSTimeDlyHMSM( 0, 0, 1,0 ); }}/*初始化后,从这里开始执行 C 代码*/int __main( void ) {int i;un sig ned in t palette[LCDC_CMRAM_SIZE];MX1_LCDC_I nit(LCDC_PANEL_WIDTH, LCDC_PANEL_HEIGHT,LCDC_INIT_STARTX, LCDC_INIT_STARTY, LCDC_VPW, LCDC_PANEL_CONF,LCDC_BPP );//初始化调色板 for( i=0; i<16; i++ ){palette[i] = RGB( i, 0, 0 ); palette[i+16] = RGB( 0, i, 0 ); palette[i+32] = RGB( 0, 0, i ); palette[i+48]= RGB( i, i, i );MX1_AITC_I nit(); IRQ_I nit();//初始化LCD /*初始化中断控制器*/ /*初始化中断管理*/}MX1_LCDC_CMRAM_Set( palette );OSI nit(); /*初始化uC/OS-ll内核数据结构*//*建立任务*/OSTaskCreate( YourTaskl, 0, & StkTask1[STK_SIZE_TASK1-1], PRIO_TASK1 );OSTaskCreate( YourTask2, 0, & StkTask2[STK_SIZE_TASK2-1], PRIO_TASK2 );OSTaskCreate( YourTask3, 0, & StkTask3[STK_SIZE_TASK3-1], PRIO_TASK3 );OSStart(); /*开始调度*/return 0;}//信号量 #i nclude "INCLUDES.H" /* 包含与uC/OS-ll 相关的系统调用的头文件 */#i nclude "mx1_aitc.h" /*包含与中断控制器相关的头文件*/#i nclude "IRQ.h"/*包含与中断管理相关的头文件*/#i nclude "mx1_gpio.h"#i nclude "misc.h"#i nclude"mx1」cdc.h"/*用于时钟中断*/extern void OSStartTimeTick( void ); extern void OSTickISR( void );#defi ne STK_SIZE_TASK1#defi ne STK_SIZE_TASK2 #defi ne PRIO_TASK2 4 OS_STK StkTask1[STK_SIZE_TASK1]; OS_STK StkTask2[STK_SIZE_TASK2];OS_EVENT *pLCDSem; /* 用于 LCD 的信号量 *//*此函数定义了一个任务*/void YourTask1( void *pdata ) {INT8U err;IRQ_Register( OSTickISR, TIMER1_INT ); /* 开启 uC/OS-ll 的时钟中断(必须在第一个运行的任务里进行)*/OSStartTimeTick(); /*在下面添加任务内容 */ MX1_LCDC_DrawRect( 0, 0, LCDC_PANEL_WIDTH-1 ,LCDC_PANEL_HEIGHT-1,48, 48,LS_SOLID, FS_SOLID );while( 1 ){OSSemPe nd( pLCDSem, 0, &err );MX1_LCDC_DrawRect(20, 20, LCDC_PANEL_WIDTH-20L CDC_PANEL_HEIGHT-2015,15, LS_SOLID, FS_TRANS );MX1_LCDC_DrawRect(40, 40, LCDC_PANEL_WIDTH-40L CDC_PANEL_HEIGHT-4031,31, LS_SOLID, FS_TRANS );MX1_LCDC_DrawRect(50, 60, LCDC_PANEL_WIDTH-60L CDC_PANEL_HEIGHT-6047,256 /*分配给任务的堆栈大小 */256#defi ne PRIO_TASK13 /*任务的优先级*//*为任务分配堆栈空间 */47, LS_SOLID, FS_SOLID );OSTimeDlyHMSM( 0, 0, 4, 0 );MX1_LCDC_DrawRect(20, 20, LCDC_PANEL_WIDTH-20L CDC_PANEL_HEIGHT-2048,48, LS_SOLID, FS_TRANS );MX1_LCDC_DrawRect(40, 40, LCDC_PANEL_WIDTH-40L CDC_PANEL_HEIGHT-4048,48, LS_SOLID, FS_TRANS );MX1_LCDC_DrawRect(60, 60, LCDC_PANEL_WIDTH-60L CDC_PANEL_HEIGHT-6048,48, LS_SOLID, FS_SOLID );OSSemPost( pLCDSem ); }}/*此函数定义了一个任务 */ void YourTask2( void *pdata ) {INT8U err;/*在下面添加任务内容 */ while( 1 ){OSSemPe nd( pLCDSem, 0, &err ); MX1_LCDC_DrawEllipse( 20, 20,15, 15, LS_SOLID, FS_TRANS );MX1_LCDC_DrawEllipse( 40, 40,31, 31, LS_SOLID, FS_TRANS );MX1_LCDC_DrawEllipse( 60, 60,47, 47, LS_SOLID, FS_SOLID );OSTimeDlyHMSM( 0, 0, 4, 0 ); MX1_LCDC_DrawEllipse( 20, 20,48, 48, LS_SOLID, FS_TRANS );MX1_LCDC_DrawEllipse( 40, 40,48, 48, LS_SOLID, FS_TRANS );MX1_LCDC_DrawEllipse( 60, 60,48, 48, LS_SOLID, FS_SOLID );OSSemPost( pLCDSem ); }}/*初始化后,从这里开始执行 C 代码*/int __main( void ) {un sig ned in t palette[LCDC_CMRAM_SIZE]; int i;LCDC_PANEL_WIDTH-20, LCDC_PANEL_HEIGHT-20,LCDC_PANEL_WIDTH-40, LCDC_PANEL_HEIGHT-40, LCDC_PANEL_WIDTH-60, LCDC_PANEL_HEIGHT-60, LCDC_PANEL_WIDTH-20, LCDC_PANEL_HEIGHT-20, LCDC_PANEL_WIDTH-40, LCDC_PANEL_HEIGHT-40, LCDC_PANEL_WIDTH-60, LCDC_PANEL_HEIGHT-60,MX1_LCDC_I nit(LCDC_PANEL_WIDTH, LCDC_PANEL_HEIGHT,LCDC_INIT_STARTX, LCDC_INIT_STARTY, LCDC_VPW, LCDC_PANEL_CONF,LCDC_BPP );//初始化调色板 for( i=0; i<16; i++ ){palette[i] = RGB( i, 0, 0 ); palette[i+16] = RGB( 0, i, 0 ); palette[i+32] = RGB( 0, 0, i ); palette[i+48]= RGB( i, i, i );}MX1_LCDC_CMRAM_Set( palette ); OSInit();/*初始化uC/OS-ll 内核数据结构 *//*初始化信号量,必须在 OSInit()之后*/ pLCDSem = OSSemCreate( 1 );/*建立任务*/OSTaskCreate( YourTaskl, 0, & StkTask1[STK_SIZE_TASK1-1], PRIO_TASK1 ); OSTaskCreate( YourTask2, 0, & StkTask2[STK_SIZE_TASK2-1], PRIO_TASK2 ); OSStart(); /* 开始调度 */return 0; }MX1_AITC_I nit(); IRQ_I nit();〃初始化LCD/*初始化中断控制器*/ /*初始化中断管理*///消息邮箱//misc.c#i nclude "INCLUDES.H" /*包含与uC/OS-ll相关的系统调用的头文件#i nclude "mx1_aitc.h" /*包含与中断控制器相关的头文件*/ #in clude "IRQ.h" /*包含与中断管理相关的头文件*/#i nclude "mx1_gpio.h"#in elude "mx1_uart.h" /*用于时钟中断*/extern void OSStartTimeTick( void );extern void OSTickISR( void );#defi neSTK_SIZE_TASK1 256 /*分配给任务的堆栈大小#defi neSTK_SIZE_TASK2256#defi ne PRIO_TASK1 3 /* 任务的优先级*/#define PRIO TASK2 4OS_STK StkTask1[STK_SIZE_TASK1]; /* 为任务分配堆栈空间*/OS_STK StkTask2[STK_SIZE_TASK2];OS_EVENT *pMbox;char msg[11];/*此函数定义了一个任务*/void YourTask1( void *pdata ){INT8U err;char *str=(char*)O;IRQ_Register( OSTicklSR, TIMER1_INT ); /* 开启uC/OS-ll 的时钟中断(必须在第一个运行的任务里进行)*/OSStartTimeTick();/*在下面添加任务内容*/while( 1 ){str = OSMboxPe nd( pMbox, 0, &err );if( str!=0 ){MX1_UART_PutStri ng( COM1, "Message: ", 9 );MX1_UART_PutStri ng( COM1, str, 10 );MX1_UART_PutStri ng( COM1, "\r\n", 2 );}}/*创建消息油箱,必须在 OSInit()之后*/pMbox = OSMboxCreate( 0 );/*建立任务*/OSTaskCreate( YourTaskl, 0, & StkTask1[STK_SIZE_TASK1-1], PRIO_TASK1 );OSTaskCreate( YourTask2, 0, & StkTask2[STK_SIZE_TASK2-1], PRIO_TASK2 ); OSStart(); /* 开始调度 */ return 0;}}/*此函数定义了一个任务*/void YourTask2( void *pdata ) {/*在下面添加任务内容while( 1 ){*/MX1_UART_GetStri ng( C0M1, msg, 10 );msg[10]=0;OSMboxPost( pMbox, (void*)msg ); }}/*初始化后,从这里开始执行 int __main( void ) {MX1_AITC_I nit(); IRQ 」nit();C 代码*//*初始化中断控制器*/ /*初始化中断管理*/MX1_UART_I nit( COM1 ); OSI ni t();/*初始化uC/OS-ll 内核数据结构*///实验代码/****************** * A Sample Module* ******************/ #include "INCLUDES.H" /* 包含与uC/OS-ll 相关的系统调用的头文件 */#include "mx1_aitc.h" /*包含与中断控制器相关的头文件*/#include "IRQ.h"/*包含与中断管理相关的头文件*/#include "mx1_gpio.h"#include "misc.h"#i nclude "mx1」cdc.h"#include "switch.h"#in clude"led.h"/*用于时钟中断*/extern void OSStartTimeTick( void );extern void OSTickISR( void );OS_EVENT *pLCDSem; /* 用于 LCD 的信号量 */int speed;/*此函数定义了一个任务*/void YourTask1( void *pdata ) {INT8U err; int x,y; int directX; int directY; speed=50; x=20; y=20; directX=2; directY=1;#defi neSTK_SIZE_TASK1256 /*分配给任务的堆栈大小#defi neSTK_SIZE_TASK2256#defi ne PRIO_TASK1 3 /*任务的优先级*/#define PRIO TASK24/*为任务分配堆栈空间*/OS_STK StkTask1[STK_SIZE_TASK1];OS_STK StkTask2[STK_SIZE_TASK2];IRQ_Register( OSTicklSR, TIMER1_INT ); /* 开启uC/OS-ll 的时钟中断(必须在第一个运行的任务里进行)*/OSStartTimeTick();/*在下面添加任务内容*/MX1_LCDC_DrawRect( 0, 0, LCDC_PANEL_WIDTH-1 ,LCDC_PANEL_HEIGHT-1,48, 48,LS_SOLID, FS_SOLID );while( 1 ){OSSemPe nd( pLCDSem, 0, &err );MX1_LCDC_DrawRect(x,y,x+20,y+20,0,0, LS_SOLID, FS_SOLID );if(x<=1 || x>=299)directX=-directX;if(y==0 || y==220)directY=-directY;x+=directX;y+=directY;MX1_LCDC_DrawRect(x,y,x+20,y+20,15,15, LS_SOLID, FS_SOLID ); OSTimeDlyHMSM( 0, 0, 0, speed );OSSemPost( pLCDSem );}}/*此函数定义了一个任务*/void YourTask2( void *pdata ){INT8U err;int i;SWITCH」nit( SW6 ); /* 初始化开关*/SWITCH」n it( SW7 );LED_I nit( LED3 );LED_I nit( LED4 );LED_I nit( LED5 );LED_I nit( LED6 );LED_I nit( LED7 );LED_I nit( LED8);〃un sig ned int t;/*在下面添加任务内容*/while( 1 ){OSSemPe nd( pLCDSem, 0, &err );if( SWITCH_IS_ON( SW6 ) && speed>=35 )speed-=5;if( SWITCH_IS_ON( SW7 ) && speed<=70) speed+=5;switch(speed/10){case3:LED_0 n(LED3);LED_Off(LED4);LED_Off(LED5);LED_Off(LED6);break; case4:LED_O n( LED4);LED_Off(LED3);LED_Off(LED5);LED_Off(LED6);break; case5:LED_O n(LED5);LED_Off(LED3);LED_Off(LED4);LED_Off(LED6);break; case6:LED_O n(LED6);LED_Off(LED4);LED_Off(LED5);LED_Off(LED3);break;default:LED_Off(LED6);LED_Off(LED4);LED_Off(LED5);LED_Off(LED3);break;}OSSemPost( pLCDSem );}}/*初始化后,从这里开始执行C代码*/int __main( void ){un sig ned in t palette[LCDC_CMRAM_SIZE];int i;MX1_AITC_Init(); /*初始化中断控制器*/IRQ_I ni t(); /*初始化中断管理*///初始化LCDMX1_LCDC_I nit(LCDC_PANEL_WIDTH, LCDC_PANEL_HEIGHT,LCDC_INIT_STARTX, LCDC_INIT_STARTY, LCDC_VPW, LCDC_PANEL_CONF, LCDC_BPP );//初始化调色板for( i=0; i<16; i++ ){palette[i] = RGB( i, 0, 0 );palette[i+16] = RGB( 0, i, 0 );palette[i+32] = RGB( 0, 0, i );palette[i+48] = RGB( i, i, i );}OSI ni t(); /*初始化uC/OS-ll内核数据结构*/MX1_LCDC_CMRAM_Set( palette );/*初始化信号量,必须在OSInit()之后*/pLCDSem = OSSemCreate( 1 );/*建立任务*/OSTaskCreate( YourTaskl, 0, & StkTask1[STK_SIZE_TASK1-1], PRIO_TASK1 );OSTaskCreate( YourTask2, 0, & StkTask2[STK_SIZE_TASK2-1], PRIO_TASK2 );OSStart(); /* 开始调度*/return 0;}任务调度发生于:1)开启多任务,OSStart();2)新建一个任务,OSTaskCreate 或OSTaskCreateEx3)中断返回,OSI ntExit4)时间延迟,OSTimeDly 或OSTimeDlyHMSM5)任务请求事件而未得到,OSSemPe nd OSMboxPe nd OSFlagPe nd OSMutexPe nd OSQPe nd OSEbe ntPe ndMulti6)任务释放事件且有任务正在请求,OSSe nPost OSMboxPost OSMboxPostOpt OSMutexPost OSQPost OSQPostFro nt OSQPostOpt OSFlagPost7)任务被挂起或恢复,OSTaskSuspe nd OSTaskResume8)任务被删除,OSTaskDel9)任务延时被取消,OSTimeDlyResume10)调用系统时钟节拍函数,OSTimeTick。
uCOSII系统分析
与CPU的接口部分
应用范例
一个PC机上的基于uC/OS-II的应用范例
13个任务
空闲任务和统计任务(OSInit产生) TaskStart任务 10个任务在屏幕随机的位置显示0-9的数字,每 个任务只显示同一个数字
内容
uC/OS-II概述
源代码文件结构 任务、任务控制块、任务间通信、共享与互斥、中 断 从boot到操作系统,操作系统初始化,任务创建, 启动多任务,任务调度,任务切换,任务定时等 待…
源代码开放 微内核 内核与应用软件没有明确区分
共享同一个地址空间,一个映像,一个 main()入口函数
易移植
Application Software
uC/OS-II (Processor Independent Code)
OS_MBOX.C OS_MEM.C OS_Q.C OS_SEM.C OS_FLAG.C OS_MUTEX.C OS_CORE.C uCOS_II.C uCOS_II.H OS_TASK.C OS_TIME.C
SetTickIn5MS()
IRQ_Handler()
OSTaskStkInit() OSStartHighRdy()
IntTaskSwitch()
任务控制块
OS_TCB (in uCOS_II.h)
typedef struct os_tcb { OS_STK *OSTCBStkPtr; #if OS_TASK_CREATE_EXT_EN > 0 … #endif struct os_tcb *OSTCBNext; struct os_tcb *OSTCBPrev;
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
uC/OS-II源码分析(总体思路一)首先从main函数开始,下面是uC/OS-II main函数的大致流程:main() {OSInit();TaskCreate(...);OSStart(); }首先是调用OSInit进行初始化,然后使用TaskCreate创建几个进程/Task,最后调用OSStart,操作系统就开始运行了。
OSInit最先看看OSInit完成哪些初始化:void OSInit (void){#if OS_VERSION >= 204OSInitHookBegin();#endifOS_InitMisc();OS_InitRdyList();OS_InitTCBList();OS_InitEventList();#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)OS_FlagInit();#endif#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)OS_MemInit();#endif#if (OS_Q_EN > 0) && (OS_MAX_QS > 0)OS_QInit();#endifOS_InitTaskIdle();#if OS_TASK_STAT_EN > 0OS_InitTaskStat();#endif#if OS_VERSION >= 204OSInitHookEnd();#endif#if OS_VERSION >= 270 && OS_DEBUG_EN > 0OSDebugInit();#endif}OS_InitMisc()完成的是一些其其他他的变量的初始化:OSIntNesting = 0;OSLockNesting = 0;OSTaskCtr = 0;OSRunning = FALSE;OSCtxSwCtr = 0;OSIdleCtr = 0L;其中包括:中断嵌套标志OSIntNesting,调度锁定标志OSLockNesting,OS 标志OSRunning等。
OSRunning在这里设置为FALSE,在后面OSStartHighRdy 中会被设置为TRUE表示OS开始工作。
OS_InitRdyList()初始化就绪Task列表:static void OS_InitRdyList (void){INT8U i;INT8U *prdytbl;OSRdyGrp = 0x00;prdytbl = &OSRdyTbl[0];for (i = 0; i < OS_RDY_TBL_SIZE; i++) {*prdytbl++ = 0x00;}OSPrioCur = 0;OSPrioHighRdy = 0;OSTCBHighRdy = (OS_TCB *)0;OSTCBCur = (OS_TCB *)0;}首先将OSRdyTbl[]数组中全部初始化0,同时将OSPrioCur/OSTCBCur初始化为0,OSPrioHighRdy/OSTCBHighRdy也初始化为0,这几个变量将在第一个OSSchedule中被赋予正确的值。
OS_InitTCBList()这个函数看名称我们就知道是初始化TCB列表。
static void OS_InitTCBList (void){INT8U i;OS_TCB *ptcb1;OS_TCB *ptcb2;OS_MemClr((INT8U *)&OSTCBTbl[0], sizeof(OSTCBTbl));OS_MemClr((INT8U *)&OSTCBPrioTbl[0], sizeof(OSTCBPrioTbl));ptcb1 = &OSTCBTbl[0];ptcb2 = &OSTCBTbl[1];for (i = 0; i < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1); i++) {ptcb1->OSTCBNext = ptcb2;#if OS_TASK_NAME_SIZE > 1ptcb1->OSTCBTaskName[0] = '?';ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL;#endifptcb1++;ptcb2++;}ptcb1->OSTCBNext = (OS_TCB *)0;#if OS_TASK_NAME_SIZE > 1ptcb1->OSTCBTaskName[0] = '?';ptcb1->OSTCBTaskName[1] = OS_ASCII_NUL;#endifOSTCBList = (OS_TCB *)0;OSTCBFreeList = &OSTCBTbl[0];}这里完成的工作很简单,首先把整个数组使用OSTCBNext指针连接成链表链起来,然后将OSTCBList初始化为0,也就是还没有TCB,因为还没有Task产生,OSTCBFreeList指向OSTCBTbl[]数组的第一个表示所有TCB都处于Free 状态。
OS_InitEventList()初始化Event列表。
static void OS_InitEventList (void){#if OS_EVENT_EN && (OS_MAX_EVENTS > 0)#if (OS_MAX_EVENTS > 1)INT16U i;OS_EVENT *pevent1;OS_EVENT *pevent2;OS_MemClr((INT8U *)&OSEventTbl[0], sizeof(OSEventTbl)); pevent1 = &OSEventTbl[0];pevent2 = &OSEventTbl[1];for (i = 0; i < (OS_MAX_EVENTS - 1); i++) {pevent1->OSEventType = OS_EVENT_TYPE_UNUSED;pevent1->OSEventPtr = pevent2;#if OS_EVENT_NAME_SIZE > 1pevent1->OSEventName[0] = '?';pevent1->OSEventName[1] = OS_ASCII_NUL;#endifpevent1++;pevent2++;}pevent1->OSEventType = OS_EVENT_TYPE_UNUSED;pevent1->OSEventPtr = (OS_EVENT *)0;#if OS_EVENT_NAME_SIZE > 1pevent1->OSEventName[0] = '?';pevent1->OSEventName[1] = OS_ASCII_NUL;#endifOSEventFreeList = &OSEventTbl[0];#elseOSEventFreeList = &OSEventTbl[0];OSEventFreeList->OSEventType = OS_EVENT_TYPE_UNUSED; OSEventFreeList->OSEventPtr = (OS_EVENT *)0;#if OS_EVENT_NAME_SIZE > 1OSEventFreeList->OSEventName[0] = '?';OSEventFreeList->OSEventName[1] = OS_ASCII_NUL;#endif#endif#endif}同样将EventTbl[]数组中的OSEventType都初始化为OS_EVENT_TYPE_UNUSED。
OS_InitTaskIdle(),中间我们跳过其他的如Mem等的初始化,看看Idle Task 的初始化。
(void)OSTaskCreateExt(OS_TaskIdle,(void *)0,&OSTaskIdleStk[OS_TASK_IDLE_STK_SIZE - 1],OS_IDLE_PRIO,OS_TASK_IDLE_ID,&OSTaskIdleStk[0],OS_TASK_IDLE_STK_SIZE,(void *)0,OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);其实Idle Task的初始化很简单就是调用OSTaskCrete系列的函数创建一个Task, OSTaskCreate我们后面再做进一步分析。
初始化State Task也是类似调用OSTaskCreate系列函数创建Stat Task。
这里只是创建了该Task的各个结构还没有真正运行该Task,直到OSStart中才依据优先级调度运行。
OK,到这里OSInit算高一个段落了,我们接着回到main往下看uC/OS-II源码分析(总体思路二)OSTaskCreate负责创建Task所需的数据结构,该函数原形如下所示:INT8U OSTaskCreate (void (*task)(void *pd), void *p_arg, OS_STK *ptos, INT8U prio)其中task是一个函数指针,指向该Task所开始的函数,当这个Task第一次被调度运行时将会从task处开始运行。
p_arg是传给task的参数指针;ptos是堆栈指针,指向栈顶(堆栈从上往下)或栈底(堆栈从下往上);prio是进程的优先级,uC/OS-II共支持最大64个优先级,其中最低的两个优先级给Idle和Stat进程,并且各个Task的优先级必须不同。
接下来,我们看看这个函数的执行流程:#if OS_ARG_CHK_EN > 0if (prio > OS_LOWEST_PRIO) {return (OS_PRIO_INVALID);}#endifOS_ENTER_CRITICAL();if (OSIntNesting > 0) {OS_EXIT_CRITICAL();return (OS_ERR_TASK_CREATE_ISR);}if (OSTCBPrioTbl[prio] == (OS_TCB *)0) {OSTCBPrioTbl[prio] = (OS_TCB *)1;OS_EXIT_CRITICAL();psp = (OS_STK *)OSTaskStkInit(task, p_arg, ptos, 0);err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0); if (err == OS_NO_ERR) {if (OSRunning == TRUE) {OS_Sched();}} else {OS_ENTER_CRITICAL();OSTCBPrioTbl[prio] = (OS_TCB *)0;OS_EXIT_CRITICAL();}return (err);}OS_EXIT_CRITICAL();return (OS_PRIO_EXIST);OS_LOWEST_PRIO在ucos-ii.h中被定义为63,表示Task的优先级从0到63,共64级。