经典教程:嵌入式实时操作系统uc/os-ii Jean J.Labrosse著 邵贝贝等译

1. 从主函数开始

int main (void)
{init();//一些硬件的初始化InstallInterruptHandler((unsigned int) OSTickISR, (unsigned int) 0x18);//Timer 1 Interrupt Level 8 指定定时器中断中断号InstallInterruptHandler((unsigned int) OSCtxSw, (unsigned int) 0x80);//Context Switch 指定上下文切换陷阱InitialiseSystemTimer(ACTIVE_TICK_TIMER);OSInit(); /* Initialize uC/OS-II*/OSTaskCreate(FirstTestTask, (void *)0, &FirstTestTaskStk[TEST_STK_SIZE - 1], APP_TASK_ONE_PRIO);//创造任务1,给出任务1的地址、堆栈大小和优先级OSTaskCreate(SecondTestTask, (void *)0, &SecondTestTaskStk[TEST_STK_SIZE - 1], APP_TASK_TWO_PRIO);OSStart();  /* Start multitasking   */return 0;
}

其中重要的有三个函数OSInit() OSTskCreate() OSStart():

1.1.OSInit()

void  OSInit (void)
{OSInitHookBegin();                                           /* Call port specific initialization code   */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_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)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  */
#endifOS_InitTaskIdle();                                           /* Create the Idle Task                     */
#if OS_TASK_STAT_EN > 0uOS_InitTaskStat();                                           /* Create the Statistic Task                */
#endif
#if OS_TMR_EN > 0uOSTmr_Init();                                                /* Initialize the Timer Manager             */
#endifOSInitHookEnd();                                             /* Call port specific init. code            */
#if OS_DEBUG_EN > 0uOSDebugInit();
#endif
}

其中hook为钩子函数,是作者留给开发人员的发挥空间,可以在这里完成一些开发人员想做的事情,比如初始化自己的硬件。条件编译“开关”都在ucos_ii.h中,可以在这里对内核进行“剪裁”,决定保留什么功能,去除什么功能。

在OSInit中最重要的是三个部分:就绪表、任务块、事件块。

1.1.1就绪表

每个任务有自己的优先级0~63。处于就绪态的任务会在就绪表的相应位置1。

如果一个任务的优先级为8=00001000,即OSRdyGrp=YYY=001,OSRdyTbl[001]=XXX=000

每个任务的优先级都会分成两部分分别记录在OSRdyGrp和OSRdyTbl中。

当就绪表中的值是一定的,则有且仅有唯一一个最小值(优先级最高的任务),如当第7/22/30位置一,则最小值为7。

在就绪表中找到优先级最高的任务:

y = OSUnMapTbl[OSRdyGrp];
x = OSUnMapTbl[OSRdyTbl[y]];
prio = (y<<3) + x;

OSUnMapTbl为:

若某时刻OSRdyGrp为0x68,OSRdyTbl为0xE4。则

3 = OSUnMapTbl[0x68];
2 = OSUnMapTbl[0xE4];
26 = (3<<3) + 2;//最高优先级任务为26

1.1.2任务控制块

以下为任务控制块精简版本:

typedef struct os_tcb {OS_STK          *OSTCBStkPtr;           /* Pointer to current top of stack                         */struct os_tcb   *OSTCBNext;             /* Pointer to next     TCB in the TCB list                 */struct os_tcb   *OSTCBPrev;             /* Pointer to previous TCB in the TCB list                 */INT32U           OSTCBDly;              /* Nbr ticks to delay task or, timeout waiting for event   */INT8U            OSTCBStat;             /* Task      status                                        */INT8U            OSTCBStatPend;         /* Task PEND status                                        */INT8U            OSTCBPrio;             /* Task priority (0 == highest)                            */INT8U            OSTCBX;                /* Bit position in group  corresponding to task priority   */INT8U            OSTCBY;                /* Index into ready table corresponding to task priority   */OS_PRIO          OSTCBBitX;             /* Bit mask to access bit position in ready table          */OS_PRIO          OSTCBBitY;             /* Bit mask to access bit position in ready group          */} OS_TCB;

一旦任务建立,一个任务控制块就被赋值。当任务的CPU使用权被剥夺,uc/os-ii用它来保存该任务的状态。OS_TCB全部驻留在RAM中。

在ucos初始化时,所有任务控制块OS_TCB都被连接成单向空任务链表,然后OSTCBFreeList的值调整为指向链表下一个空的任务控制块。一旦任务被删除,任务控制块就还给空任务链表。

任务链表初始化:

static  void  OS_InitTCBList (void)
{INT8U    ix;INT8U    ix_next;OS_TCB  *ptcb1;OS_TCB  *ptcb2;OS_MemClr((INT8U *)&OSTCBTbl[0],     sizeof(OSTCBTbl));      /* Clear all the TCBs                 */OS_MemClr((INT8U *)&OSTCBPrioTbl[0], sizeof(OSTCBPrioTbl));  /* Clear the priority table           */for (ix = 0u; ix < (OS_MAX_TASKS + OS_N_SYS_TASKS - 1u); ix++) {    /* Init. list of free TCBs     */ix_next =  ix + 1u;ptcb1   = &OSTCBTbl[ix];ptcb2   = &OSTCBTbl[ix_next];ptcb1->OSTCBNext = ptcb2;
#if OS_TASK_NAME_EN > 0uptcb1->OSTCBTaskName = (INT8U *)(void *)"?";             /* Unknown name                       */
#endif}ptcb1                   = &OSTCBTbl[ix];ptcb1->OSTCBNext        = (OS_TCB *)0;                       /* Last OS_TCB                        */
#if OS_TASK_NAME_EN > 0uptcb1->OSTCBTaskName    = (INT8U *)(void *)"?";              /* Unknown name                       */
#endifOSTCBList               = (OS_TCB *)0;                       /* TCB lists initializations          */OSTCBFreeList           = &OSTCBTbl[0];
}

1.1.3事件控制块

事件控制块ECB是用于实现以下功能函数的基本数据结构:信号量管理、互斥型信号量管理、消息邮箱管理以及消息队列管理。

typedef struct os_event {INT8U    OSEventType;                    /* Type of event control block (see OS_EVENT_TYPE_xxxx)    事件类型*/void    *OSEventPtr;                     /* Pointer to message or queue structure                   等待任务所在的组*/INT16U   OSEventCnt;                     /* Semaphore Count (not used if other EVENT type)          计数器(当事件是信号量的时候)*/OS_PRIO  OSEventGrp;                     /* Group corresponding to tasks waiting for event to occur 指向消息或者消息队列的指针*/OS_PRIO  OSEventTbl[OS_EVENT_TBL_SIZE];  /* List of tasks waiting for event to occur                等待任务列表*/#if OS_EVENT_NAME_EN > 0uINT8U   *OSEventName;
#endif
} OS_EVENT;

每个信号量、互斥型信号量、消息邮箱以及消息队列都应分配到一个事件控制块ECB。

1.2.OSTaskCreate()

通过将任务的地址和其他参数如优先级传递到此函数中来建立任务。

1.3.OSStart()

void OSStart(void){

if (OSRunning == OS_FALSE) { OS_SchedNew(); /* Find highest priority's task priority number */ OSPrioCur = OSPrioHighRdy; OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run */ OSTCBCur = OSTCBHighRdy; OSRunning = 1; OSStartHighRdy(); /* Execute target specific code to start task */ } }

在这里完成最高优先级查找和开始执行最高优先级任务。


两个用户任务的定义:

void FirstTestTask (void *pdata)
{pdata = pdata;InitiateTimer(ACTIVE_TICK_TIMER);while(1){get_status_for_ucos();//用户任务OSTimeDly(10);//任务延时10个时钟节拍}
}
void SecondTestTask (void *pdata)
{pdata = pdata;InitiateTimer(ACTIVE_TICK_TIMER);while(1){get_vector_for_ucos();OSTimeDly(15);//任务延时15个时钟节拍}
}

2. 系统的基本运作

在任务开始运行之后,每遇到任务的“OSTimeDly”,任务就进入等待状态。在这个函数中会调用OS_Sched()函数进行任务调度,重新寻找就绪列表中的最高优先级任务,并调用OS_TASK_SW()函数,出发陷阱,开始任务切换。

3.系统移植

与处理器相关的代码只有OS_CPU.H,OS_CPU_A.ASM,OS_CPU_C.C。

OS_CPU.H中包含临界区的实现方式。

OS_CPU_A.ASM中实现OSStartHighRdy()使就绪态任务中优先级最高的任务开始运行,OSCtxSw()任务切换,OSIntCtxSw()和OSTickISR()提供节拍定时中断。

OS_CPU_C.C中实现任务堆栈初始化以及所有钩子函数(可以不写)。

uc/os-ii学习相关推荐

  1. UART0串口编程(四):UART0串口编程之在UC/OS—II中遭遇的危机

    UART0串口编程之在UC/OS-II中遭遇的危机 一.潜在的危机 1.在uc/os操作系统中设计串口编程时,由于ISR和多个任务并发执行,情况比较复杂.尤其是接收状态为被动状态时,只能靠串行口中断来 ...

  2. Lab 6:uC/OS II

    为什么80%的码农都做不了架构师?>>>    目标: 移植uC/OS II到RPi上,实现两个任务的调度.这两个任务能轮流点亮LED,并通过串口发送消息表明自己正在运行 具体步骤: ...

  3. uc/OS II——多任务设计

    uc/OS II--多任务设计 (1)设计 开始任务 [1]/声明 开始任务 任务块 static OS_STK App_TaskStartStk[APP_TASK_START_STK_SIZE]; ...

  4. linux串口互斥,UART0串口编程之在UC/OS—II中遭遇的危机

    一.潜在的危机 1.在uc/os操作系统中设计串口编程时,由于ISR和多个任务并发执行,情况比较复杂.尤其是接收状态为被动状态时,只能靠串行口中断来接收数据. 2.在进行串行通信时,双方遵循相同的通信 ...

  5. 【嵌入式系统—实时操作系统】uC/OS II源码的官网下载

    要下载源码为:STM32F107-uC/OS-II源码包 Micrium官网的下载地址:Micrium_uC-Eval-STM32F107_uCOS-II 怎么找? 到官网的产品专区目录入口查找STM ...

  6. 【 uC/OS II 】uC/OS II 源代码阅读(os_task.c)任务管理

    前言 这个任务管理源代码,是整个系统最核心的部分,也是最难的部分,多看几遍吧.其中的核心结构体是: typedef struct os_tcb {OS_STK *OSTCBStkPtr; /* Poi ...

  7. uc os ii与linux,uC/OS-II嵌入式实时操作系统的几大特点

    uC/OS-II嵌入式实时操作系统的几大特点 出处:网络 发布于:2018-09-12 14:46:03 uC/OS-II的特点 1.uC/OS-II是由Labrosse先生编写的一个开放式内核,主要 ...

  8. UC/OS II 消息邮箱

    消息邮箱是uC/OS-II中的另一种通信机制,可以使一个任务或者中断服务子程序向另一个任务发送一个指针型的变量.通常该指针指向一个包含了"消息"的特定数据结构.如果该指针为空,说明 ...

  9. 【 uC/OS II 】uC/OS II 源代码阅读(os_mbox.c)消息邮箱

    前言 关于消息邮箱,是一个消息邮箱里面,只能存储一条消息.核心结构体如下: #if (OS_EVENT_EN) && (OS_MAX_EVENTS > 0u) typedef s ...

  10. UC/OS II 任务管理(4)之任务创建

    任务的创建函数 ucosii之前的版本都只支持64个任务,但是V2.90版本支持的任务数量达到了256. 用法和原理都差不多.我这里就只介绍任务数不大于64的情况.当任务大于64的时候,只需要配置相关 ...

最新文章

  1. LaxTex---问题1: ! I can't write on file `***.pdf'.(Press Enter to retry, or Control-Z to exit; \ldots
  2. 验证身份照号码是否有效
  3. mysql 5.6.30 添加用户_mysql5.6创建账户不能本地登录
  4. 转:(图文并茂)SQL Server 2005详细安装过程及配置
  5. 【转载保存】获取页面编码
  6. 全球计算机用户人数,NIC2019年11月:全球IPv6 用户数占比中国居43位
  7. Linux---生产者与消费者模型
  8. Disruptor高性能缓存队列入门指导
  9. LA 2218 Triathlon (Geometry, Half Plane Intersection)
  10. 《精通LabVIEW虚拟仪器程序设计与案例实现》一2.1 LabVIEW安装
  11. ButterKnife的安装与使用以及ButterKnife右键不显示的大坑
  12. 常见问题数组索引越界异常
  13. Android知识体系思维导图
  14. [WARNING]:登录失败:密码错误或账号被冻结
  15. 航班信息显示系统-总结
  16. 文本相似度计算 python去停用词_python专业方向 | 文本相似度计算
  17. 顺丰王国--传奇创造者
  18. java将英文字符(无论大小写)转化为小写
  19. 宝塔低内存安装mysql_宝塔面板安装mysql 8.0提示最低内存和最低CPU限制的三种解决方法...
  20. 编程实践(Pandas)Task05

热门文章

  1. html如何做滑动门效果,div+css制作简单滑动门效果
  2. 【大数据集群搭建-Apache】Apache版本进行大数据集群各组件环境部署
  3. Linux 中查找 IP 地址的方法
  4. 周周过,周周结(十九)
  5. windows环境安装adb驱动
  6. 豆瓣电视剧评论的爬取以及进行情感分析+生成词云
  7. 我国自主研发航空新材料,实现铝中“自生”陶瓷
  8. 计算机组成原理之控制器
  9. linux磁盘配额指令,Linux磁盘配额相关指令
  10. 资源管理:caching模式