STM32
直播中

南中南

8年用户 979经验值
擅长:光电显示
私信 关注
[问答]

微内核 uC/OS-II 该怎样去移植呢

uC/OS-II内核结构是如何构成的?
微内核 uC/OS-II 中的任务到底是什么呢?

微内核 uC/OS-II 该怎样去移植呢?

回帖(1)

李淑兰

2021-10-29 18:05:28
  一、uC/OS-II内核结构的详细分析
  实时微内核 uC/OS-II ,由 Jean J. Labrosse 在 1992 年编写发行,代码开源,如下图所示。
  
  uC/OS-II内核结构
  第一部分 (1):与硬件无关的高层的操作系统部分
  大部分是关于任务的创建、信号量的创建、邮箱和队列的创建,以及它们所使用的函数库。另外,该部分还提供内存和实时时钟管理。
  该部分中几个重要的.c文件 [tr]OS_Mbox.c[td]消息邮箱(Mailbox)服务模块文件[tr]OS_MEM.c[td]存储管理服务模块文件[tr]OS_Q.c[td]队列(Queue)服务模块文件[tr]OS_SEM.c[td]信号量(Semaphore)服务模块文件[tr]OS_Task.c[td]任务管理服务模块文件[tr]OS_Time.c[td]时间管理服务模块文件第二部分 (2):与用户应用相关的配置头文件
  主要定义了应用程序中的最大任务数、最低优先级、邮箱、信号量及钩子函数的使用情况等。
  例如STM32F107评估板,其OS_CFG.H 配置头文件中的代码片段如下:
  #ifndef OS_CFG_H
  #define OS_CFG_H
  ···
  #define OS_MAX_QS 4 /* Max. number of queue control blocks in your application */
  #define OS_MAX_TASKS 20 /* Max. number of tasks in your application, MUST be 》= 2 */
  ···
  /* --------------------- TASK STACK SIZE ---------------------- */
  #define OS_TASK_TMR_STK_SIZE 128 /* Timer task stack size (# of OS_STK wide entries) */
  ···
  /* --------------------- TASK MANAGEMENT ---------------------- */
  #define OS_TASK_CHANGE_PRIO_EN 1 /* Include code for OSTaskChangePrio() */
  #define OS_TASK_CREATE_EN 1 /* Include code for OSTaskCreate()
  ···
  /* ----------------------- EVENT FLAGS ------------------------ */
  #define OS_FLAG_EN 1 /* Enable (1) or Disable (0) code generation for EVENT FLAGS */
  #define OS_FLAG_ACCEPT_EN 1 /* Include code for OSFlagAccept() */
  ···
  /* -------------------- MESSAGE MAILBOXES --------------------- */
  #define OS_MBOX_EN 1 /* Enable (1) or Disable (0) code generation for MAILBOXES */
  #define OS_MBOX_ACCEPT_EN 1 /* Include code for OSMboxAccept() */
  ···
  /* --------------------- MEMORY MANAGEMENT -------------------- */
  #define OS_MEM_EN 1 /* Enable (1) or Disable (0) code generation for MEMORY MANAGER */
  ···
  ···
  /* ------------------------ SEMAPHORES ------------------------ */
  #define OS_SEM_EN 1 /* Enable (1) or Disable (0) code generation for SEMAPHORES */
  #define OS_SEM_ACCEPT_EN 1 /* Include code for OSSemAccept() */
  。..
  #endif
  第三部分 (3):与硬件处理器相关的代码
  由 OS_CPU.H 、 OS_CPU_A.ASM 和 OS_CPU_C.C 构 成 。
  其中,OS_CPU_A.ASM文件由三个汇编函数组成,,如下表。
  [tr] OsStartHighRdy( )[td]运行优先级最高的就绪任务。[tr]Os_Task_Sw( )[td]任务切换函数[tr]OsIntCtxSw( )[td]中断级的任务切换函数
  这三个汇编函数非常重要(uC/OS-II 的移植工作大部分都基于这三个汇编函数,均与处理器硬件直接相关)
  而 OS_CPU_C.C 主要包括任务堆栈的初始化函数、若干C语言的钩子函数(可以不加任何代码)。
  二、微内核 uC/OS-II 中的任务
  μC/OS-II 操作系统内核的主要工作——对任务进行管理和调度。
  1、那在 uC/OS-II中,什么是任务呢?
  “自顶向下,分而治之”的设计范型下,一 个大型的任务会被分解成一个个独立的且不能再分解的若干小任务(无法返回的函数),而与上述小任务对应的程序实体就叫做“任务”,也有人称之为线程。任务的大概形式具体如下。
  void Task (void *parg)
  {
  /* 任务主体,无限循环且不能返回 */
  for (;;) {
  /* 任务主体代码 */
  }
  }
  
  从代码级别上看,uC/OS-II 中的任务就是一个函数,由三个部分组成:任务程序代码、任务堆栈和任务控制块。
  2、关于任务的数据结构?
  
  N 个任务用双向链表串连起来,其中每个任务的数据结构由任务控制块(Task Control Block-TCB)和任务堆栈组成。
  ① 任务控制块:关联了任务代码的程序控制块(主要由指向任务堆栈的指针、指向前一个任务控制块的指针、指向后一个任务控制块的指针及任务的优先级等构成)。
  任务控制块TCB的部分代码片段(在/uCOS-II/。../source/ucos_ii. h中),如下:
  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 */
  ···
  void *OSTCBMsg; /* Message received from OSMboxPost() or OSQPost() */
  ···
  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 */
  ···
  INT8U OSTCBDelReq; /* Indicates whether a task needs to delete itself */
  INT32U OSTCBCtxSwCtr; /* Number of time the task was switched in */
  INT32U OSTCBCyclesTot; /* Total number of clock cycles the task has been running */
  INT32U OSTCBCyclesStart; /* Snapshot of cycle counter at start of task resumption */
  OS_STK *OSTCBStkBase; /* Pointer to the beginning of the task stack */
  INT32U OSTCBStkUsed; /* Number of bytes used from the stack */
  INT8U *OSTCBTaskName;
  INT32U OSTCBRegTbl[OS_TASK_REG_TBL_SIZE];
  } OS_TCB;
  ② 任务堆栈:保存任务的工作环境(主要用来保存任务断点的寄存器的状态值,在ARM处理器中则用于保存 PC、LR、 R0-R12、CPSR、SPSR 的状态值。任务堆栈在文件 os_cpu_c.c 中进行初始化)。
  其堆栈初始化代码(在/Ports/。../RealView/os_cpu_c.c中),如下:
  OS_STK *OSTaskStkInit (void (*task)(void *p_arg), void *p_arg, OS_STK *ptos, INT16U opt)
  {
  OS_STK *stk;
  (void)opt; /* ‘opt’ is not used, prevent warning */
  stk = ptos; /* Load stack pointer */
  /* Registers stacked as if auto-saved on exception */
  *(stk) = (INT32U)0x01000000uL; /* xPSR */
  *(--stk) = (INT32U)task; /* Entry Point */
  *(--stk) = (INT32U)OS_TaskReturn; /* R14 (LR) */
  *(--stk) = (INT32U)0x12121212uL; /* R12 */
  *(--stk) = (INT32U)0x03030303uL; /* R3 */
  *(--stk) = (INT32U)0x02020202uL; /* R2 */
  *(--stk) = (INT32U)0x01010101uL; /* R1 */
  *(--stk) = (INT32U)p_arg; /* R0 : argument */
  /* Remaining registers saved on process stack */
  *(--stk) = (INT32U)0x11111111uL; /* R11 */
  *(--stk) = (INT32U)0x10101010uL; /* R10 */
  *(--stk) = (INT32U)0x09090909uL; /* R9 */
  *(--stk) = (INT32U)0x08080808uL; /* R8 */
  *(--stk) = (INT32U)0x07070707uL; /* R7 */
  *(--stk) = (INT32U)0x06060606uL; /* R6 */
  *(--stk) = (INT32U)0x05050505uL; /* R5 */
  *(--stk) = (INT32U)0x04040404uL; /* R4 */
  return (stk);
  }
  
  任务堆栈的增长方向
  ③ 任务程序代码:任务的执行部分。
  三、微内核 uC/OS-II 的移植
  1、在原有的STM32工程添加相应目录
  原有SMT32工程文件夹下,新建一个目录uCOS-II,并在该目录下新建两个子目录:Ports和Source;
  MDK工程目录下,新建uCOS-II_Source组、uCOS-II_Ports组。
  2、添加源码文件到刚刚新建的目录下
  (1)添加文件到本地工程文件夹
  ① /uCOS-II/Source文件下除os_cfg_c.h和os_dbg_r.c全部复制到移植工程目录下的Source子目录下
  ② /uCOS-II/Ports/ARM-Cortex-M3/Generic/RealView下的全部文件拷贝到移植目录的Ports子目录下
  ③ EvalBoards/Micrium/uC-Eval-STM32F107/uCOS-II下的app_cfg.h、includes.h 、 os_cfg.h和app_hooks.c(主要定义了一些钩子函数)这四个文件拷贝到移植工程的APP目录下。
  (2)添加文件到MDK工程目录
  分别在uCOS-II_Source组、uCOS-II_Ports组、APP组导入相应的本地工程文件。
  3、修改includes.h
  /*
  *********************************************************************************************************
  * EXAMPLE CODE
  *
  * (c) Copyright 2003-2013; Micrium, Inc.; Weston, FL
  *
  * All rights reserved. Protected by international copyright laws.
  * Knowledge of the source code may NOT be used to develop a similar product.
  * Please help us continue to provide the Embedded community with the finest
  * software available. Your honesty is greatly appreciated.
  *********************************************************************************************************
  */
  /*
  *********************************************************************************************************
  *
  * MASTER INCLUDES
  *
  * ST Microelectronics STM32
  * on the
  *
  * Micrium uC-Eval-STM32F107
  * Evaluation Board
  *
  * Filename : includes.h
  * Version : V1.00
  * Programmer(s) : EHS
  *********************************************************************************************************
  */
  #ifndef INCLUDES_PRESENT
  #define INCLUDES_PRESENT
  /*
  *********************************************************************************************************
  * STANDARD LIBRARIES
  *********************************************************************************************************
  */
  #include 《stdarg.h》
  #include 《stdio.h》
  #include 《stdlib.h》
  #include 《math.h》
  /*
  *********************************************************************************************************
  * LIBRARIES
  *********************************************************************************************************
  */
  //#include 《cpu.h》
  //#include 《lib_def.h》
  //#include 《lib_ascii.h》
  //#include 《lib_math.h》
  //#include 《lib_mem.h》
  //#include 《lib_str.h》
  /*
  *********************************************************************************************************
  * APP / BSP
  *********************************************************************************************************
  */
  #include “bsp.h”
  /*
  *********************************************************************************************************
  * OS
  *********************************************************************************************************
  */
  #include 《ucos_ii.h》
  /*
  *********************************************************************************************************
  * ST
  *********************************************************************************************************
  */
  /*
  *********************************************************************************************************
  * INCLUDES END
  *********************************************************************************************************
  */
  #endif
  4、修改main.c
  /******************************************************************************
  * File : main.c
  * Function : 主文件
  * Description: None
  * Version : V1.00
  * Author : WXP
  * Date :
  * History :
  ******************************************************************************/
  #include “includes.h”
  //START 任务
  //设置任务优先级
  #define START_TASK_PRIO 10 //开始任务的优先级设置为最低
  //设置任务堆栈大小
  #define START_STK_SIZE 64
  //任务堆栈
  OS_STK START_TASK_STK[START_STK_SIZE];
  //任务函数
  void start_task(void *pdata);
  //LED0任务
  //设置任务优先级
  #define LED0_TASK_PRIO 7
  //设置任务堆栈大小
  #define LED0_STK_SIZE 64
  //任务堆栈
  OS_STK LED0_TASK_STK[LED0_STK_SIZE];
  //任务函数
  void led0_task(void *pdata);
  //LED1任务
  //设置任务优先级
  #define LED1_TASK_PRIO 6
  //设置任务堆栈大小
  #define LED1_STK_SIZE 64
  //任务堆栈
  OS_STK LED1_TASK_STK[LED1_STK_SIZE];
  //任务函数
  void led1_task(void *pdata);
  int main(void)
  {
  Bsp_Init();
  OSInit();
  OSTaskCreate(start_task,(void *)0,(OS_STK *)&START_TASK_STK[START_STK_SIZE-1],START_TASK_PRIO );//创建起始任务
  OSStart();
  while(1)
  {
  }
  }
  //开始任务
  void start_task(void *pdata)
  {
  OS_CPU_SR cpu_sr=0;
  pdata = pdata;
  OS_ENTER_CRITICAL(); //进入临界区(无法被中断打断)
  OSTaskCreate(led0_task,(void *)0,(OS_STK*)&LED0_TASK_STK[LED0_STK_SIZE-1],LED0_TASK_PRIO);
  OSTaskCreate(led1_task,(void *)0,(OS_STK*)&LED1_TASK_STK[LED1_STK_SIZE-1],LED1_TASK_PRIO);
  OSTaskSuspend(START_TASK_PRIO); //挂起起始任务。
  OS_EXIT_CRITICAL(); //退出临界区(可以被中断打断)
  }
  //LED0任务
  void led0_task(void *pdata)
  {
  while(1)
  {
  LED2(ON);
  OSTimeDlyHMSM(0,0,0,200);
  LED2(OFF);
  OSTimeDlyHMSM(0,0,0,200);
  }
  }
  //LED1任务
  void led1_task(void *pdata)
  {
  while(1)
  {
  LED3(ON);
  OSTimeDlyHMSM(0,0,0,500);
  LED3(OFF);
  OSTimeDlyHMSM(0,0,0,500);
  }
  }
  5、修改uCOS-II_Ports下的os_cpu_a.asm
  ① 第一处
  EXPORT OS_CPU_PendSVHandler 改为 EXPORT PendSVHandler。
  ② 第二处
  
  ③ 第三个要改的:
  将stm32f10x_it.c中的PendSV_Handler函数注释掉
  6、修改bsp_systick.c
  ① 添加代码,如下
  #include “includes.h” ② 在void SysTick_Init (void)函数中,修改为Syslick_Config(SystemCoreCIock OS_TICKS_PER_SEC//滴答时钟定时周期为1ms。
  ③ 第三处
  
  7、修改uCOS-II_Ports文件夹下的os_cpu_c.c中的关于systick的配置初始化及中断处理部分
  更新中···
  8、uCOS-II_Ports文件夹下的os_cpu.h,注释掉我们刚才修改过的函数部分
  更新中···
举报

更多回帖

发帖
×
20
完善资料,
赚取积分