我看UCOSII

来源:互联网 发布:我的淘宝旺旺号怎么看 编辑:程序博客网 时间:2024/05/22 13:59

前段时间看了看任哲老师的UCOSII书籍,有些感悟便想着写点东西要不过两天就全忘了

关于UCOSII的代码详解和使用网络上有很多资料和书籍在这就不说了

(比如UCOSII源码详解,

代码中文注释

各函数使用方法解释

UCOSII参考手册,

介绍UCOSII的书籍都有pdf或其他电子档

(原著,任哲的,邵贝贝的http://wenku.baidu.com/view/1949346f011ca300a6c39087.html


百度文库和搜索引擎能找到各种单片机和ARM上的移植博文,课件和源代码

另外芯片提供商和开发板提供商都会提供移植好的demo,很多人也是在别人demo基础上写的博客

官网http://micrium.com/page/products

这里主要用自己最简单的话来理解UCOSII的常用功能,不去探讨内核实现

主要分为以下部分

1,UCOSII概述

2,UCOSII移植和配置(概述)

3,UCOSII使用

4,UCOSII剪裁和优化



一,ucosii概述

主要功能有:

1, 多任务管理

2, 任务间通信

3, 中断和时间管理

4, 内存管理

特点:

最多支持56个任务,8个系统占用的

属于可剥夺型内核,总是执行优先级最高的任务。

必须使用空闲任务

版本:2.52    2.80  2.86等

附带功能

µC/OS-II(Kernel)       µC/OS-III (Kernel)

µC/TimeSpaceOS       RTOS Add-ons

µC/TCP-IP            µC/GUI

µC/File System         µC/USB

µC/USB Host          µC/USB Device

µC/CAN              µC/Modbus

µC/FL                  µC/Building Blocks



二,ucosii移植和配置(简单描述)

操作系统移植概念
所谓操作系统的移植,是指使一个实时操作系统能够在某个特定的微处理器平台上运行。
mCOS-II的主要代码都是由标准的C语言写成的,移植方便。但仍需要用汇编语言写一些与处理器相关的代码,这是因为µC/OS-Ⅱ在读写处理器寄存器时只能通过汇编语言来实现。 
移植的主要工作是修改部分与处理器硬件相关的代码。
处理器需要满足的条件
处理器的C编译器能产生可重入代码。 
在程序中可以打开或者关闭中断。 
处理器支持中断,并且能产生定时中断(通常在10-100Hz之间)。 
处理器支持能够容纳一定量数据的硬件堆栈(可能达几KB) 
处理器有将堆栈指针和其他CPU寄存器存储和读出到堆栈(或者内存)的指令
了解处理器的特点
大小端
增长方向
定时器使用和中断的管理

移植主要是三个和cpu相关文件的修改

uC/OS-II的全部源代码量大约是6000-7000行,共15个文件。将 uC/OS-II 移植到ARM处理器上,需要修改三个与ARM体系结构相关的文件,代码量大约是500行。

OS_CPU.H                 OS_CPU_A.ASM              OS_CPU_C.C
配置

文件OS_CFG.H是与应用程序有关的配置文件,主要是对操作系统进行设置。包括:
设置系统的最多任务数OS_MAX_TASKS;
最多事件控制块设置 OS_MAX_EVENTS;
堆栈方向的设置OS_STK_GROWTH(1为递减、0为递增);
是否支持堆栈检验OS_TASK_CREATE_EXT;
是否支持任务统计OS_ASK_STAT_EN;
是否支持事件标志组OS_FLG_EN…



三,ucosii使用(具体的函数使用可参考

UCOSII  常用函数查询  http://wenku.baidu.com/view/02f11f6c011ca300a6c390c2.html

               函数参考手册 http://www.doc88.com/p-361144437527.html

UCOSII API函数     http://blog.chinaunix.net/uid-20766895-id-219986.html

UCOSII功能函数大全   http://wenku.baidu.com/view/1b56d219fad6195f312ba6a3.html)

获取版本号:

应用程序调用OSVersion()可以得到当前μC/OS-Ⅱ的版本号。 OSVersion()
函数返回版本号值乘以 100。换言之,200 表示版本号 2.00。

任务模型

void YourTask (void *pdata)  
{  
    for (;;) {  
        /* 用户代码 */  
        调用µC/OS-Ⅱ的服务例程之一: 
            OSMboxPend(); 
            OSQPend(); 
            OSSemPend(); 
            OSTaskDel(OS_PRIO_SELF); 
            OSTaskSuspend(OS_PRIO_SELF);  
            OSTimeDly(); 
            OSTimeDlyHMSM(); 
        /* 用户代码 */ 
    }  
}


先上一个在pc上测试的demo程序

/******************************Test*******************************/#include "includes.h"#define  TASK_STK_SIZE   512//任务堆栈长度OS_STK   MyTaskStk[TASK_STK_SIZE];//定义任务堆栈区OS_STK   YouTaskStk[TASK_STK_SIZE];//定义任务堆栈区INT16S   key;//用于退出uCOS_II的键INT8U x=0,y=0,time=0;//字符显示位置void  MyTask(void *data);//声明任务void  YouTask(void *data);//声明任务/************************主函数*********************************/void  main (void){    char* s_M="M";//定义要显示的字符    OSInit( );//初始化uCOS_II    PC_DOSSaveReturn( );//保存Dos环境    PC_VectSet(uCOS, OSCtxSw);//安装uCOS_II中断    OSTaskCreate(MyTask,//创建任务MyTasks_M,//给任务传递参数&MyTaskStk[TASK_STK_SIZE - 1],//设置任务堆栈栈顶指针0//任务的优先级别为0);    OSStart( );//启动多任务管理}/*******************任务MyTask**********************************/void  MyTask (void *pdata){    char* s_Y="Y";//定义要显示的字符#if OS_CRITICAL_METHOD == 3    OS_CPU_SR  cpu_sr;#endif    pdata = pdata;     OS_ENTER_CRITICAL( );    PC_VectSet(0x08, OSTickISR);//安装时钟中断向量    PC_SetTickRate(OS_TICKS_PER_SEC);//设置时钟频率    OS_EXIT_CRITICAL( );    OSStatInit( );//初始化统计任务    OSTaskCreate(YouTask,//创建任务MyTasks_Y,//给任务传递参数&YouTaskStk[TASK_STK_SIZE - 1],//设置任务堆栈栈顶指针2// MyTask的优先级别为2);    for (;;)     {        if (x>50) {   x=0;   y+=2;         }                                                         PC_DispChar(x, y,//字符的显示位置*(char*)pdata, DISP_BGND_BLACK+DISP_FGND_WHITE );       x += 1;   //如果按下Esc键则退出uCOS_IIif (PC_GetKey(&key) == TRUE) {        if (key == 0x1B)     {            PC_DOSReturn( );//恢复Dos环境        }    }    OSTimeDlyHMSM(0, 0, 3, 0);//等待3秒}}/************************任务YouTask******************************/void  YouTask (void *pdata){#if OS_CRITICAL_METHOD == 3    OS_CPU_SR  cpu_sr;#endif    pdata = pdata; for (;;)     {   if(time==20)OSTaskSuspend(0);if(time==40)OSTaskResume(0);        time++;        if (x>50) {   x=0;   y+=2; }                                                         PC_DispChar(x, y,//字符的显示位置*(char*)pdata, DISP_BGND_BLACK+DISP_FGND_WHITE );       x += 1;        OSTimeDlyHMSM(0, 0, 1, 0);//等待1秒    }}/************************End************************************/


1, 多任务管理

首先每个任务都需要创建任务堆栈,来保存任务切换时的数据

#define  TASK_STK_SIZE   512 //任务堆栈长度
OS_STK   MyTaskStk[TASK_STK_SIZE]; //定义任务堆栈区

任务函数主要包括:

创建任务两个函数后者更灵活但会增加开销

INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)    //任务函数指针,参数,任务堆栈栈顶指针,优先级

INT8U OSTaskCreateExt (void   (*task)(void *pd), 
                       void    *pdata, 
                       OS_STK  *ptos, 
                       INT8U    prio, 
                       INT16U   id, 
                       OS_STK  *pbos, 
                       INT32U   stk_size, 
                       void    *pext, 
                       INT16U   opt) 

删除任务

INT8U OSTaskDel (INT8U prio) 
void RequestorTask (void *pdata)  //删除别的任务
void TaskToBeDeleted (void *pdata)  //删除自己

改变优先级 INT8U OSTaskChangePrio (INT8U oldprio, INT8U newprio) 

挂起任务INT8U OSTaskSuspend (INT8U prio) 

恢复任务INT8U OSTaskResume(INT8U prio) 

查询任务

OS_TCB MyTaskData; 
 
void MyTask (void *pdata) 

    pdata = pdata; 
    for (;;) { 
        /*  用户代码                   */ 
        err = OSTaskQuery(10, &MyTaskData); 
        /* Examine error code ..        */ 
        /*  用户代码                    */ 
    } 
}

使用流程

创建任务堆栈

OSinit()

创建任务

OSStart()


2, 任务间通信

OS_EventWaitListInit:事件控制块初始化

使一个任务进入就绪状态OS_EventTaskRdy:

使一个正在等待的任务进入就绪状态OS_EventTaskWait:

使一个等待超时的任务进入就绪状态OS_EventTO:


信号量(其实就是一个全局变量,添加了管理机制)

就是一个标志来标示公共资源现在是否可用,不可用就排队等待一定时限或者直接返回

应用场合:多个任务需要访问同一个资源,为了避免各任务竞争资源导致数据资源中的混乱,就需要信号量来管理

各任务对公共资源的访问

相关函数:创建,请求(等待和不等待),释放,删除,查询

使用流程:

声明一个信号量 OS_Event *Fun_semp;

创建信号量(注册刚才声明的那个信号量)

请求/释放信号量


互斥信号量(添加了优先级功能的信号量)

比信号量多了个功能为了避免优先级的翻转现象。

应用场合:多个任务需要访问公共资源,且对任务优先级要求很严格,不允许出现优先级反转现象的场合。

相关函数:创建,请求,释放,删除,查询

使用流程:

同信号量的操作流程


信号量集(含有状态组的信号量)

应用场合:假如任务4需要任务1,2,3同时执行完后才能执行,那么就用信号量集来完成这个功能

任务一完成后改变信号量集的第一位

任务二完成后改变信号量集的第二位

任务三完成后改变信号量集的第三位

那么任务四就看这个信号量集的1,,2,3位是否都改变了,如果是就执行

相关函数:创建信号量集,请求/查询信号量集,发送/修改信号量集,删除信号量集,查询信号量集

使用流程:

声明一个信号量集 OS_FLAG_GRP  *sem_f;

创建信号量集(注册刚才声明的那个信号量集)

发送/修改信号量集

请求/查询信号量集

消息邮箱(其实就是一个全局指针,不同的任务来通过这个指针传递数据)

功能是提供任务间的数据传递,但是是单向的传递两个任务间要互相传递数据,就需要连个邮箱。

不同任务间的通信需要定义多邮箱来实现才能互不干扰

应用场合:两个或多个任务间需要传递一条数据的场合。

相关函数:创建,收,发,查询,删除

使用流程:

定义一个消息邮箱OS_EVENT  *str_box;

创建

收/发

(删除)


消息队列(每次可传递多条消息的机制)

和邮箱类似但是每次传递的数据较多,不同任务间的通信需要定义多个队列来实现才能互不干扰

应用场合:两个或多个任务间需要传递多条数据的场合。

相关函数:创建,收,发,查询,删除

使用流程:

定义消息指针数组 void *MsgGrp[消息队列长度];

定义事件控制块 OS_EVENT  *str_Q;

创建

收/发

(删除)




3, 中断和时间管理

  OSTimeDly() 延时以时钟节拍算
  OSTimeDlyHMSM() 延时按时分秒毫秒算
  OSTimeDlyResu()  取消延时
  OSTimeGet() 系统时间获取
  OSTimeSet() 系统时间设置



4, 内存管理

相关函数

注册内存区

申请内存块

释放内存块


使用流程:

开辟内存区 就是定义两位数组INT8U      Partition[100][32];

注册内存区

申请内存块

使用内存块

释放内存块


四,ucosii剪裁和优化



原创粉丝点击