微内核 uC/OS-II 及其移植


STM32F107——uC/OS-II 源码包的快速下载

如果想自己亲身前往官网下载,请看官网源码下载的详细教程☞☞ Micrium官网下载uC/OS II源码


文章目录

一、uC/OS-II内核结构的详细分析

二、微内核 uC/OS-II 中的任务

1、那在 uC/OS-II中,任务是什么呢?

2、关于任务的数据结构?

三、微内核 uC/OS-II 的移植


一、uC/OS-II内核结构的详细分析

实时微内核 uC/OS-II ,由 Jean J. Labrosse 在 1992 年编写发行,代码开源,如下图所示。

uC/OS-II内核结构

 第一部分 (1):与硬件无关的高层的操作系统部分

大部分是关于任务的创建、信号量的创建、邮箱和队列的创建,以及它们所使用的函数库。另外,该部分还提供内存和实时时钟管理。

该部分中几个重要的.c文件
OS_Mbox.c 消息邮箱(Mailbox)服务模块文件
OS_MEM.c 存储管理服务模块文件
OS_Q.c 队列(Queue)服务模块文件
OS_SEM.c 信号量(Semaphore)服务模块文件
OS_Task.c 任务管理服务模块文件
OS_Time.c 时间管理服务模块文件

第二部分 (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文件由三个汇编函数组成,,如下表。

 OsStartHighRdy( ) 运行优先级最高的就绪任务。
Os_Task_Sw( ) 任务切换函数
OsIntCtxSw( ) 中断级的任务切换函数

这三个汇编函数非常重要(uC/OS-II 的移植工作大部分都基于这三个汇编函数,均与处理器硬件直接相关)

而 OS_CPU_C.C 主要包括任务堆栈的初始化函数、若干C语言的钩子函数(可以不加任何代码)。

 

二、微内核 uC/OS-II 中的任务

μC/OS-II 操作系统内核的主要工作——对任务进行管理和调度。

1、那在 uC/OS-II中,什么是任务呢?

“自顶向下,分而治之”的设计范型下,一 个大型的任务会被分解成不能再分解的若干小任务,而与上述小任务对应的程序实体就叫做“任务”。

从代码级别上看,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,注释掉我们刚才修改过的函数部分

更新中···

发布了76 篇原创文章 · 获赞 38 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42605300/article/details/105511399