2. 移植uCOS III到i.MX RT¶
本章开始,先新建一个基于野火i.MX RT全系列(包含M7)开发板的的uCOS III的工程模板,让uCOS III先跑起来。以后所有的uCOS III相关的例程我们都在此模板上修改和添加代码,不用再反反复复地新建。在本书配套的例程中,每一章的例程对野火I.MX RT的每一个板子都会有一个对应的例程,但是区别都很小,如果有区别的地方我会在教程里面详细指出,如果没有特别备注那么都是一样的。
2.1. 获取i.MX RT的裸机工程模板¶
I.MX RT的裸机工程模板我们直接使用野火i.MX RT开发板配套的固件库例程即可。这里我们选取比较简单的例程—“GPIO输出—使用固件库点亮LED”作为裸机工程模板。 该裸机工程模板均可以在对应板子的书籍配套例程的目录下获取到,下面以野火RT1052PRO板子的光盘目录为例,具体见 图16-1。
2.2. 下载uCOS III源码¶
在移植之前,我们首先要获取到uCOS III的官方的源码包,首先,打开Micrium 公司官方网站(http://micrium.com/),打开网站链接之后,我们点击“Downloads”选项卡进入下载页面,在“Brouse by MCU Manufacturer”栏目展开“STMicroelectronics”,单击“Viewall STMicroelectronics”,具体见 图16-2 与 图16-3 。
uCOS-III是一个操作系统,其实也可以理解成一个软件库,它可以移植到多种硬件平台,如M3、M4还有M7内核的i.MX RT,或者ARM9等等其他芯片。核心代码肯定是一致的,但是针对不同的处理器肯定要不同的实现部分。这里选择与我们开发板最为接近的版本(NXPi.MX RT series),因为我们的野火i.MX RT系列开发板属于是i.MX RT series系列的,而uCOS-III的这个官方代码就满足我们的需求,目的也在于少花费工夫,要知道,若要从0开始移植uCOS-III到目标硬件平台,需要极大的精力和软件水平。
在“ Projects”栏目中只有一个基于 IAR(EWARM)V8.x 平台在 cortex-M7 内核 MCU 评估板上测试的 uC/OS-III 源码,单击即可。我们选择“MIMXRT150-EVK”这个项目的代码,点击后进入下载即可,不过uCOS官网下载这些源码是需要注册账号的, 而我们野火已经将这些源码下载了,在配套源码中,这样子就免去下载这一步了,直接拿来使用即可具体见 图16-4、图16-5 与 图16-6。
2.3. uCOS III源码文件介绍¶
我们从uCOS III源码下面的文件夹夹中看到,里面的文件夹不多,只有4个,分别是EvalBoards、uC-CPU、uC-LIB、uCOS-III,下面我们就来介绍一下这几个文件夹的作用。
2.3.1. MIMXRT1050-EV¶
MIMXRT1050-EV文件夹里面包含评估板相关文件,在移植时我们添加部分文件,将图16-7的源码复制添加到我们的工程目的新建cfg目录下,具体见 图16-7_,具体见 图16-8。 .. image:: media/section14/sectio007.png
- align
center
- name
图16-7
- alt
图片没有找到
将“\MIMXRT1050-EVKNXPBSPInterrupts”和“MIMXRT1050-EVKNXPBSP\ MIMXRT1050-EVK”路径下的文件添加到我们工程中的新建目录BSP文件夹下,具体见 图16-9 与 图16-10。
2.3.2. uC-CPU¶
这是和CPU紧密相关的文件,里面的一些文件很重要,都是我们需要使用的。在ARM-Cortex-M4文件夹下,存在cpu_c.c 一些对不同编译器移植相关的文件,目前只有IAR,里面有一些很重要的文件,但是目前我们使用的开发环境是MDK(keil),IAR与keil这部分文件是不同的,但是相同的文件可以复制同为M7内核的文件即可。下面具体来介绍一下里面的文件,具体见 图16-11。
2.3.2.1. cpu_c.h文件¶
包含了一些数据类型的定义,让uCOSIII与CPU架构和编译器的字宽无关。同时还指定了CPU使用的是大端模式还是小端模式,还包括一些与CPU架构相关的函数的声明。
这两个文件主要是CPU 底层相关的一些CPU 函数,cpu_c.c 文件中放的是C 函数,包含了一些CPU架构相关的代码,为什么要用C语言实现呢?uCOS是为了移植方便而采用C语言编写;而 cpu_a.asm 存放的是汇编代码,有一些代码只能用汇编实现,包含一些用来开关中断,前导零指令等。
2.3.2.2. cpu_core.c¶
cpu_core.c文件包含了适用于所有的CPU架构的C代码,也就是常说的通用代码。是一个很重要的文件。主要包含的函数是CPU 名字的命名,时间戳的计算等等,跟CPU底层的移植没有太大的关系,主要保留的是 CPU 前导零的 C 语言计算函数以及一些其他的函数,因为前导零指令是依靠硬件实现的,这里采用C语言方式实现,以防止某些CPU不支持前导零指令
2.3.2.3. cpu_core.h¶
主要是对 cpu_core.c 文件里面一些函数的说明,以及一些时间戳相关等待定义。
2.3.2.4. cpu_def.h¶
包含CPU相关的一些宏定义,常量,利用#define进行定义的相关信息。
2.3.3. uC-LIB¶
Micrium公司提供的官方库,诸如字符串操作、内存操作等接口,可用可不用。一般能用于代替标准库中的一些函数,使得在嵌入式中应用更加方便安全。
2.3.4. uCOS-III¶
这是关键目录,我们下来着重分析的文件位于此目录下。
首先先看看uCOS-IIIPortsARM-Cortex-MARMv7-MIAR目录下的文件,具体见 图16-12。
uCOS是软件,我们的开发版是硬件,软硬件必须有桥梁来连接,这些与处理器架构相关的代码,可以称之为RTOS硬件接口层,它们位于uCOS-IIIPorts文件夹下,这些文件不需要我们去修改,也不需要我们去理会,都是官方给我们写好的,直接使用即可。
2.3.4.1. os_cpu.h¶
定义数据类型、处理器相关代码、声明函数原型。
2.3.4.2. oc_cpu_a.asm¶
与处理器相关的汇编代码,主要是与任务切换相关。
2.4. 移植到i.MX RT工程¶
在前一章节中,我们看到了uCOS III源码中那么多文件,一开始学我们根本看不过来那么多文件,我们需要提取源码中的最简洁的部分代码,方便同学们学习,更何况我们学习的只是uCOS III的实时内核中的知识,因为这才是uCOS III的核心,那些demo都是基于此移植而来的,上一章节我们只是将uCOS III的源码放到了本地工程目录下,还没有添加到开发环境里面的组文件夹里面,所以uCOS III也就没有移植到我们的工程中去,现在开始讲uCOS III的源码添加到工程中。
2.4.2. 添加文件到对应分组¶
向“user”分组添加“uCOS-IIIcfg”目录下的所有文件,具体见 图16-16。
向“ BSP”分组添加“ \uCOS-IIIBSP”文件夹下的所有文件,使用工程自带的即可具体见 图16-17。
向“ uC/CPU”分组添加“uCOS-IIIuC-CPU”文件夹下的所有文件和“ \uCOS-IIIuC-CPUARM-Cortex-M4IAR”文件夹下的所有文件,具体见 图16-18。
向“uC/LIB”分组添加“uCOS-IIIuC-LIB”文件夹下的所有文件和“uCOS-IIIuC-LIBPortsARM-Cortex-M4IAR”文件夹下的所有文件,具体见 图16-19。
向“ uC/OS-III Source”分组添加“ \uCOS-IIIuCOS-IIISource”文件夹下的所有文件,具体见 图16-20。
向“uC/OS-III Port”分组添加“uCOS-IIIuCOS-IIIPortsARM-Cortex-MARMv7-MIAR”文件夹下的所有文件,具体见 图16-21。
至此,我们的源码文件就添加到工程中了,当然此时仅仅是添加而已,并不是移植成功了,如果你编译一下工程就会发现一大堆错误,所以还需努力移植工程才行。
2.4.3. 添加头文件路径到工程中¶
Ucos III的源码已经添加到开发环境的组文件夹下面,编译的时候需要为这些源文件指定头文件的路径,不然编译会报错,此时我们先将头文件添加到我们的工程中,具体见 图16-22。
至此,UCOS的整体工程基本移植完毕,我们需要修改UCOS配置文件,按照我们的需求来进行修改。
2.4.4. 具体的工程文件修改¶
添加完头文件路径后,我们可以编译一下整个工程,但肯定会有错误的, uC/OS-III 的移植尚未完毕,接下来需要对工程文件进行修改。首先修改工程的启动文件“startup_MIMXRT1052.s”。其中将图中的PendSV_Handler 和 SysTick_Handler 分别改为 OS_CPU_PendSVHandler 和OS_CPU_SysTickHandler,只有一处需要修改,因为uCOS官方已经给我们处理好对应的中断函数,就无需我们自己处理与系统相关的中断了,同时我们还需要在启动文件中添加EXTERN OS_CPU_PendSVHandler和EXTERN OS_CPU_SysTickHandler,具体见 图16-23、图16-24 与 图16-25。
如果使用的是M7内核带有FPU(浮点运算单元)的处理器,不需要增加其他代码,在SystemInit()函数中就已经写好。具体见 代码清单16-1 与 图16-26。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | void SystemInit (void)
{
#if ((__FPU_PRESENT == 1) && (__FPU_USED == 1))
SCB->CPACR |= ((3UL << 10*2) | (3UL << 11*2)); /* set CP10, CP11 Full Access */
#endif/* ((__FPU_PRESENT == 1) && (__FPU_USED == 1)) */
#if defined(__MCUXPRESSO)
externuint32_t g_pfnVectors[]; // Vector table defined in startup code
SCB->VTOR = (uint32_t)g_pfnVectors;
#endif
/* Watchdog disable */
/*省略与FPU无关内容*/
}
|
同时将对应芯片头文件中启用FPU的宏定义__FPU_PRESENT配置为1(默认是使能的),然后在Option->Target->Floating Point Hardware中选择启用浮点运算,具体见 图16-25。
修改完启动文件后,还需要修改cpu.h文件中的两处位置,分别是增加头文件“cmsis_compiler.h”和修改CPU_INT_DIS()的宏定义,由于工程是从IAR版本移植过来的,所以在cpu.h文件中缺少了写底层的宏定义文件。具体看 图16-26、图16-27。
2.4.5. 添加bsp.c与bsp.h文件¶
我们知道bsp就是板级相关的文件,也就是对应开发板的驱动文件,而在i.MX RT的uCOS III源码中需要添加一个这样的文件,主要是对系统的板级驱动初始化和板级驱动的头文件包含。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | /*
*********************************************************************
* @file bsp.c
* @author fire
* @version V1.0
* @date 2019-xx-xx
* @brief 板级驱动
********************************************************************
* @attention
*
* 实验平台:野火 i.MXRT1052开发板
* 论坛 :http://www.firebbs.cn
* 淘宝 :http://firestm32.taobao.com
*
****************************************************************
*/
/*
******************************************************************
* 包含的文件
******************************************************************
*/
//板级驱动
#include"fsl_debug_console.h"
#include"board.h"
#include"pin_mux.h"
#include"clock_config.h"
#include"./led/bsp_led.h"
#include"bsp.h"
/*
***************************************************************
* 函数名 : BSP_Init
* 描述 : 所有的硬件设备都应该放在这个函数里边初始化
* 形参 : 无
* 返回值 : 无
****************************************************************
*/
void BSP_Init (void)
{
/* 初始化内存保护单元 */
BOARD_ConfigMPU();
/* 初始化开发板引脚 */
BOARD_InitPins();
/* 初始化开发板时钟 */
//BOARD_BootClockRUN();
/* 初始化调试串口 */
BOARD_InitDebugConsole();
/* 打印系统时钟 */
PRINTF("\r\n");
PRINTF("*****欢迎使用野火i.MX RT1052 开发板*****\r\n");
PRINTF("CPU: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_CpuClk));
PRINTF("AHB: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_AhbClk));
PRINTF("SEMC: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SemcClk));
PRINTF("SYSPLL: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SysPllClk));
PRINTF("SYSPLLPFD0: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SysPllPfd0Clk));
PRINTF("SYSPLLPFD1: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SysPllPfd1Clk));
PRINTF("SYSPLLPFD2: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SysPllPfd2Clk));
PRINTF("SYSPLLPFD3: %d Hz\r\n", CLOCK_GetFreq(kCLOCK_SysPllPfd3Clk));
PRINTF("这是一个[野火]-全系列开发板-uCOS-III 任务管理实验!\n\n");
/* 硬件BSP初始化统统放在这里,比如LED,串口,LCD等 */
LED_GPIO_Config(); //初始化LED
}
|
bsp.h文件中需要添加我们自己的板级驱动头文件,头文件代码具体见 代码清单16-3。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | #ifndef BSP_H_
#define BSP_H_
/*********************************************************************
* EXTERNAL C LANGUAGE LINKAGE
*
* Note(s) : (1) C++ compilers MUST 'extern'ally declare ALL C function prototypes &
riable/object
* declarations for correct C language linkage.
************************************************************************
*/
#ifdef __cplusplus
extern"C" { /* See Note #1. */
#endif
/*
************************************************************************
* 包含的文件
***********************************************************************
*/
#include"./led/bsp_led.h"
/*
*************************************************************************
* 函数原型
*************************************************************************
*/
void BSP_Init(void);
/*
*************************************************************************
* MODULE END
*************************************************************************
*/
#endif
|
2.5. 按需配置最适的工程¶
虽然前面的编译是没有错误的,并且工程模板也是可用的,但是此时还不是我们最适合使用的工程模板,最适合的工程往往是根据需要进行配置的,而uCOS提供裁剪的功能,我们可以按需对系统进行裁剪。
2.5.1. os_cfg.h¶
os_cfg.h文件是系统的配置文件,主要是让用户自己配置一些系统默认的功能,用户可以选择某些或者全部的功能,比如消息队列、信号量、互斥量、事件标志位等,系统默认全部使用的,如果如果用户不需要的话,则可以直接关闭,在对应的宏定义中设置为0即可,这样子就不会占用系统的SRAM,以节省系统资源,os_c fg.h文件的配置说明具体见 代码清单16-4。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | #ifndef OS_CFG_H
#define OS_CFG_H
/* -------------- 其他配置 --------------- */
#define OS_CFG_APP_HOOKS_EN DEF_ENABLED/* 是否使用子函数*/
#define OS_CFG_ARG_CHK_EN DEF_ENABLED/* 是否使用参数检查*/
#define OS_CFG_CALLED_FROM_ISR_CHK_EN DEF_ENABLED/* 是否使用中断调用检查*/
#define OS_CFG_DBG_EN DEF_ENABLED/* 是否使用debug*/
#define OS_CFG_DYN_TICK_EN DEF_DISABLED/* 是否使用动态勾选*/
#define OS_CFG_INVALID_OS_CALLS_CHK_EN DEF_ENABLED/* 是否使用检查无效的内核调用 */
#define OS_CFG_OBJ_TYPE_CHK_EN DEF_ENABLED/* 是否使用对象类型检查*/
#define OS_CFG_TS_EN DEF_ENABLED/* 是否使用时间戳 */
#define OS_CFG_PRIO_MAX 64u/* 定义任务优先级的最大数量(请参阅OS_PRIO数据类型*/
#define OS_CFG_SCHED_LOCK_TIME_MEAS_EN DEF_DISABLED/* 是否包含DEF_ENABLED)代码以测量调度程
锁定时间*/
#define OS_CFG_SCHED_ROUND_ROBIN_EN DEF_ENABLED/* 是否包含DEF_ENABLED)循环调度的代码*/
#define OS_CFG_STK_SIZE_MIN 64u/*最小允许任务堆栈大小*/
/* -------------- 事件标志位------------- */
#define OS_CFG_FLAG_EN DEF_ENABLED/*是否使用事件标志位*/
#define OS_CFG_FLAG_DEL_EN DEF_ENABLED/*是否包含OSFlagDel()的代码 */
#define OS_CFG_FLAG_MODE_CLR_EN DEF_ENABLED/*是否包含清除事件标志位的代码 */
#define OS_CFG_FLAG_PEND_ABORT_EN DEF_ENABLED/*是否包含OSFlagPendAbort()的代码
/* --------------- 内存管理 ----------- */
#define OS_CFG_MEM_EN DEF_ENABLED/* 是否使用内存管理 */
/* --------------- 互斥量 ------------- */
#define OS_CFG_MUTEX_EN DEF_ENABLED/*是否使用互斥量 */
#define OS_CFG_MUTEX_DEL_EN DEF_ENABLED/*是否包含OSMutexDel()的代码*/
#define OS_CFG_MUTEX_PEND_ABORT_EN DEF_ENABLED/*是否包含OSMutexPendAbort()的代
/* ---------- 消息队列---------------- */
#define OS_CFG_Q_EN DEF_ENABLED/*是否使用消息队列 */
#define OS_CFG_Q_DEL_EN DEF_ENABLED/*是否包含OSQDel()的代码 */
#define OS_CFG_Q_FLUSH_EN DEF_ENABLED/*是否包含OSQFlush()的代码 */
#define OS_CFG_Q_PEND_ABORT_EN DEF_ENABLED/*是否包含OSQPendAbort()的代码 */
/* --------------- 信号量 ------------ */
#define OS_CFG_SEM_EN DEF_ENABLED/*是否使用信号量 */
#define OS_CFG_SEM_DEL_EN DEF_ENABLED/*是否包含OSSemDel()的代码 */
#define OS_CFG_SEM_PEND_ABORT_EN DEF_ENABLED/*是否包含OSSemPendAbort()的代码*
#define OS_CFG_SEM_SET_EN DEF_ENABLED/*是否包含OSSemSet()的代码 */
/* ----------- 任务管理 -------------- */
#define OS_CFG_STAT_TASK_EN DEF_ENABLED/*是否使用任务统计功能 */
#define OS_CFG_STAT_TASK_STK_CHK_EN DEF_ENABLED/*从统计任务中检查任务堆栈 */
#define OS_CFG_TASK_CHANGE_PRIO_EN DEF_ENABLED/*是否包含OSTaskChangePrio()代码*
#define OS_CFG_TASK_DEL_EN DEF_ENABLED/*是否包含OSTaskDel()代码*/
#define OS_CFG_TASK_IDLE_EN DEF_ENABLED/*是否使用空闲任务*/
#define OS_CFG_TASK_PROFILE_EN DEF_ENABLED/*是否使用OS_TCB中的变量用来分析*/
#define OS_CFG_TASK_Q_EN DEF_ENABLED/*是否包含OSTaskQXXXX()代码*/
#define OS_CFG_TASK_Q_PEND_ABORT_EN DEF_ENABLED/*是否包含OSTaskQPendAbort()代码*
#define OS_CFG_TASK_REG_TBL_SIZE 1u/*任务特定寄存器的数量*/
#define OS_CFG_TASK_STK_REDZONE_EN DEF_DISABLED/*是否使用堆栈 redzone */
#define OS_CFG_TASK_STK_REDZONE_DEPTH 8u/*堆栈redzone的深度*/
#define OS_CFG_TASK_SEM_PEND_ABORT_EN DEF_ENABLED/*是否包含OSTaskSemPendAbort()代
#define OS_CFG_TASK_SUSPEND_EN DEF_ENABLED/*是否包含OSTaskSuspend()和
askResume()代码 */
#define OS_CFG_TASK_TICK_EN DEF_ENABLED/*是否包含(DEF_ENABLED)内核tick
*/
/* ------- 任务本地存储管理 ------- */
#define OS_CFG_TLS_TBL_SIZE 0u/* 是否包含任务本地存储(TLS)寄存器的代码
F_ENABLED)*/
/* -------- 时间管理 ------------- */
#define OS_CFG_TIME_DLY_HMSM_EN DEF_ENABLED/*是否包含OSTimeDlyHMSM()的代码*/
#define OS_CFG_TIME_DLY_RESUME_EN DEF_ENABLED/*是否包含OSTimeDlyResume()的代码
/* ---------- 定时器管理 -------- */
#define OS_CFG_TMR_EN DEF_ENABLED/*是否使用定时器 */
#define OS_CFG_TMR_DEL_EN DEF_ENABLED/*是否支持OSTmrDel()*/
/*-----------跟踪录音机-----------*/
#define OS_CFG_TRACE_EN DEF_DISABLED/*是否使用 uC/OS-III 跟踪仪器*/
#define OS_CFG_TRACE_API_ENTER_EN DEF_DISABLED/*是否使用 uC/OS-III Trace API进
测*/
#define OS_CFG_TRACE_API_EXIT_EN DEF_DISABLED/*是否使用 uC/OS-III Trace API退
测*/
#endif
|
2.5.2. cpu_cfg.h¶
cpu_cfg.h文件主要是配置CPU相关的一些宏定义,我们可以选择对不同的CPU进行配置,当然,如果我们没有对CPU很熟悉的话,就直接忽略这个文件即可,在这里我们只需要注意关于时间戳与前导零指令相关的内容,我们使用的CPU是i.MX RT,是32位的CPU,那么时间戳我们使用32位的变量即可,而且i.MX RT支持前导零指令,可以使用它让系统进行寻找最高优先级的任务更加快捷,具体见 代码清单16-5。
UCOS支持两种方法选择下一个要执行的任务:一个采用C语言实现前导零指令,这种方法我们通常称为通用方法,CPU_CFG_LEAD_ZEROS_ASM_PRESENT没有被定义的时候使用才使用通用方法获取下一个即将运行的任务,通用方法可以用于所有uCOS支持的硬件平台,因为这种方法是完全用C语言实现, 所以效率略低于特殊方法,但不强制要求限制最大可用优先级数目;另一个是硬件方式查找下一个要运行的任务,必须定义CPU_CFG_LEAD_ZEROS_ASM_PRESENT这个宏,因为这种方法是必须依赖一个或多个特定架构的汇编指令(一般是类似计算前导零[CLZ]指令,在M3、M4、M7内核中都有,这个指 令是用来计算一个变量从最高位开始的连续零的个数),所以效率略高于通用方法,但受限于硬件平台。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #ifndef CPU_CFG_MODULE_PRESENT
#define CPU_CFG_MODULE_PRESENT
/* 是否使用CPU名字:DEF_ENABLED或者DEF_DISABLED*/
#define CPU_CFG_NAME_EN DEF_DISABLED
/* CPU名字大小(ASCII字符串形式)*/
#define CPU_CFG_NAME_SIZE 16
/* CPU时间戳功能配置(只能选择其中一个)*/
/* 是否使用32位的时间戳变量:DEF_ENABLED或者DEF_DISABLED*/
#define CPU_CFG_TS_32_EN DEF_ENABLED
/* 是否使用64位的时间戳变量:DEF_ENABLED或者DEF_DISABLED*/
#define CPU_CFG_TS_64_EN DEF_DISABLED
/* *配置CPU时间戳计时器字大小 */
#define CPU_CFG_TS_TMR_SIZE CPU_WORD_SIZE_32
/* 是否使用测量CPU禁用中断的时间 */
#if 0
#define CPU_CFG_INT_DIS_MEAS_EN
#endif
/* 配置测量的次数*/
#define CPU_CFG_INT_DIS_MEAS_OVRHD_NBR 1u
/* 是否使用CPU前导零指令(需要硬件支持) */
#if 1
#define CPU_CFG_LEAD_ZEROS_ASM_PRESENT
#endif
/* 是否配置CPU计数尾随零位 */
#if 0
#define CPU_CFG_TRAIL_ZEROS_ASM_PRESENT
#endif
/*是否定义CPU数据字存储顺序参见注释#2*/
#if 0
#define CPU_CFG_ENDIAN_TYPE CPU_ENDIAN_TYPE_BIG
#endif
/*是否定义定义CPU数据字存储顺序(参见注1)*/
#define CPU_CFG_CACHE_MGMT_EN DEF_DISABLED
#endif
|
2.5.3. os_cfg_app.h¶
os_cfg_app.h是系统应用配置的头文件,简单来说就是系统默认的任务配置,如任务的优先级、堆栈大小等基本信息,但是有两个任务是必须开启的,一个就是空闲任务, 另一个就是时钟节拍任务,这两个是让系统正常运行的最基本任务,而其他任务我们自己按需配置即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | #ifndef OS_CFG_APP_H
#define OS_CFG_APP_H
/* ------------------ 其他配置 ------------------- */
#define OS_CFG_ISR_STK_SIZE 256u/*ISR堆栈的大小*/
#define OS_CFG_MSG_POOL_SIZE 32u/* 支持的最大消息数量*/
#define OS_CFG_TASK_STK_LIMIT_PCT_EMPTY 10u/*检查堆栈的剩余大小(百分百形
此处是10%*/
/* -------------------- 空闲任务 --------------------- */
#define OS_CFG_IDLE_TASK_STK_SIZE 64u/* 空闲任务堆栈大小*/
/* ------------------ 统计任务 ------------------ */
#define OS_CFG_STAT_TASK_PRIO ((OS_PRIO)(OS_CFG_PRIO_MAX-2u))/* 优先级*/
#define OS_CFG_STAT_TASK_RATE_HZ 10u/* 执行率(1至10 Hz)*/
#define OS_CFG_STAT_TASK_STK_SIZE 128u/* 堆栈大小(CPU_STK元素的数
)*/
/* ---------------------- 时钟节拍任务 ----------------------- */
#define OS_CFG_TICK_RATE_HZ 1000u/*系统的时钟节拍(一般为10 到
00 Hz)*/
#define OS_CFG_TICK_TASK_PRIO 1u/*时钟节拍任务的优先级 */
#define OS_CFG_TICK_TASK_STK_SIZE 128u/*时钟节拍任务的堆栈大小 */
/* --------------------- 定时器任务 ----------------------- */
#define OS_CFG_TMR_TASK_PRIO ((OS_PRIO)(OS_CFG_PRIO_MAX-3u))/*“计时器任务”的优先级
#define OS_CFG_TMR_TASK_RATE_HZ 1u/*定时器的频率*/
#define OS_CFG_TMR_TASK_STK_SIZE 128u/*定时器任务的堆栈大小*/
#endif
|
此处要注意时钟节拍任务,uCOS的时钟节拍任务是用于管理时钟节拍的,建议将其优先级设置更高一些,这样子在调度的时候,时钟节拍任务能抢占其他任务执行,从而能够更新任务,相对于其他操作系统,寻找处于最高优先级的就绪任务都是在中断中,uCOS将其放于任务中能更好解决关中断时间过长的问题。
2.6. 修改main.c¶
我们将原来裸机工程里面main.c的文件内容全部删除,新增如下内容,具体见 代码清单16-7。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | /*
*****************************************************************
* @file main.c
* @author fire
* @version V1.0
* @date 2019-xx-xx
* @brief uCOS-III 系统移植
****************************************************************
* @attention
*
* 实验平台:野火 i.MXRT1052开发板
* 论坛 :http://www.firebbs.cn
* 淘宝 :http://firestm32.taobao.com
*
*****************************************************************
*/
/*
******************************************************************
* 包含的文件
********************************************************************
*/
//ucosiii系统相关
#include <cpu.h>
#include <lib_mem.h>
#include <os.h>
#include <bsp_os.h>
#include <bsp_clk.h>
#include <bsp_int.h>
#include"os_app_hooks.h"
#include"app_cfg.h"
//板级驱动
/*
********************************************************************
* 函数名 : main
* 描述 : 标准的C函数入口
* 形参 : 无
* 返回值 : 无
********************************************************************
*/
int main(void)
{
}
|
2.7. 下载验证¶
将程序编译好,用DAP仿真器把程序下载到野火i.MX RT系列开发板(具体型号根据你买的板子而定,每个型号的板子都配套有对应的程序),一看,啥现象都没有,一脸懵逼,我说,你急个肾,目前我们还没有在main函数里面创建任务,系统也没有跑起来,main函数中什么都没有,那当然是没有现象。如果要想看现象, 得自己在main创建里面应用任务,并且让uCOS跑起来,关于如何使用uCOS创建任务,请看下一章“创建任务”。