【2022得捷创新设计大赛】项目分享帖之二:uCOSIII v3.05 在 stm32f7 上的移植
[复制链接]
一、uCOSIII 简介
UCOS系统简介
UCOS是Micrium公司出品的RTOS类实时操作系统, UCOS目前有两个版本:
UCOSII和UCOSIII。
UCOSIII是一个可裁剪、可剥夺型的多任务内核,而且没有任务数限制。
UCOSIII提供了实时操作系统所需的所有功能,包括资源管理、同步、任务通信等。
UCOSIII是用C和汇编来写的,其中绝大部分都是用C语言编写的,只有极少数的与处理器密切相关的部分代码才是用汇编写的, UCOSIII结构简洁,可读性很强!最主要的是非常适合初次接触嵌入式实时操作系统学生、嵌入式系统开发人员和爱好者学习。
二、移植准备
1、下载 uCOSIII 源码包,这里我们进入 uCOSIII 官网,下载官方 STM32F7 移植好的, 链接如下
找到 STM32F7 的移植包,下载下来,如下图 1 所示
2、解压文件,打开后,会发现如下图 2 所示几个文件夹
三、开始移植(MDK 环境)
1、添加文件到工程
本实验以裸机程序中的实验 2 为工程模板,在此工程根目录下新建一个 uCOS-III 文件夹,将下载的源码目录 Software 下的内容(图 3 右)复制到此文件夹下,如图 3 所示
接着在 uCOS-III 文件夹下再新建 2 个文件夹 uC-BSP 和 uC-CFG,进入下载的源码目录Example->ST->STM32746G-PROTO->BSP 下,将 bsp.c、bsp.h 和 cpu_bsp.c 这几个文件拷贝到 uC-BSP 目录下,再进入 Example->ST->STM32746G-PROTO->OS3 目录下,将如下图 4 所示文件拷贝到 uC-CFG 目录下
最后将文件加入工程,如下图所示
添加头文件路径,如下图 所示:
至此,工程搭建完毕,由于官方移植是基于 IAR 开发环境的,我们要将其进行修改才能在 MDK 下面编译通过,下面我们开始移植。
2、修改文件
由于官方移植用的编译器是 IAR,在 MDK 下,要作以下修改: 修改处 1:
修改处 2:
修改处 4:
打开Systick.c 文件,在SysTick_Handler 中断服务函数中添加OS_CPU_SysTickHandler();
函数调用,在 SysTick_Init 函数中,修改如下SysTick_Config(HAL_RCC_GetHCLKFreq()/OSCfg_TickRate_Hz); 最后在文件开始处添加#include <os.h>
至此,uCOSIII 移植完成,MDK 编译一下,没有错误,最后就可以编写 uCOSIII 应用
程序了。
四、运行 uCOSIII 任务
编写一个简易 uCOSIII 应用程序,实现 led 闪烁功能,代码如下:
#include "MyIncludes.h"
//分配启动任务优先级、堆栈大小、任务堆栈
#define START_TASK_PRIO 3 //任务优先级#define START_TASK_STK_SIZE 512 //任务堆栈大小
CPU_STK START_TASK_STK[START_TASK_STK_SIZE]; //任务堆栈
OS_TCB StartTaskTCB; //任务控制块
//启动任务函数
void Task_Start(void *p_arg);
//分配 LED 任务优先级、堆栈大小、任务堆栈
#define LED_TASK_PRIO 4 //任务优先级#define LED_TASK_STK_SIZE 128 //任务堆栈大小
CPU_STK LED_TASK_STK[LED_TASK_STK_SIZE]; //任务堆栈
OS_TCB LedTaskTCB; //任务控制块
//led 任务函数
void Task_Led(void *p_arg);
int main(void)
{
OS_ERR err;
System_Init();
SysTick_Init(NULL); //初始化 SysTick 定时器,提供 uCosIII 时基
LED_Init();
OSInit(&err); //初始化 UCOSIII
//创建开始任务
OSTaskCreate((OS_TCB * )&StartTaskTCB, //任务控制块(CPU_CHAR * )"start task", //任务名字(OS_TASK_PTR )Task_Start, //任务函数
(void * )0, //传递给任务函数的参数(OS_PRIO )START_TASK_PRIO, //任务优先级(CPU_STK * )&START_TASK_STK[0], //任务堆栈基地址
(CPU_STK_SIZE)START_TASK_STK_SIZE/10, // 任务堆栈深度
限位
(CPU_STK_SIZE)START_TASK_STK_SIZE, //任务堆栈大小(OS_MSG_QTY )0, // 任务内部消息队列能够
接收的最大消息数目,为 0 时禁止接收消息
(OS_TICK )0, // 当使能时间片轮转时的
时间片长度,为 0 时为默认长度,
(void * )0, //用户补充的存储区
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR, //任务选项
(OS_ERR * )&err); //存放该函数错误时的返回值OSStart(&err); //启动 UCOSIII
while(1)
{
}
}
/**************************************************************************
*****
创建通信工具
***************************************************************************
****/
void Task_Start(void *p_arg)
{
OS_ERR err; /* Initialize BSP functions */ CPU_SR_ALLOC(); //调用 OS_CRITICAL_ENTER 之前要调用此函数
CPU_Init(); //初始化 CPU 组件(时间戳、关中断时间测量和主机名)
Mem_Init(); //初始化内存管理组件(堆内存池和内存池表) Math_Init();
#if OS_CFG_STAT_TASK_EN > 0u //如果使能(默认使能)了统计任务OSStatTaskCPUUsageInit(&err); //统计任务
#endif
#ifdef CPU_CFG_INT_DIS_MEAS_EN //如果使能了测量中断关闭时间CPU_IntDisMeasMaxCurReset(); //复位(清零)当前最大关中断时间
#endif
#if OS_CFG_SCHED_ROUND_ROBIN_EN //使能时间片轮转
//使能时间片轮转调度功能,时间片长度为 1 个系统时钟节拍,既 1ms OSSchedRoundRobinCfg(DEF_ENABLED,1,&err);
#endif
OS_CRITICAL_ENTER(); //进入临界区
//创建 LED 任务
OSTaskCreate((OS_TCB * )&LedTaskTCB,
(CPU_CHAR * )"led task", (OS_TASK_PTR )Task_Led, (void * )0,
(OS_PRIO )LED_TASK_PRIO, (CPU_STK * )&LED_TASK_STK[0], (CPU_STK_SIZE)LED_TASK_STK_SIZE/10, (CPU_STK_SIZE)LED_TASK_STK_SIZE, (OS_MSG_QTY )0,
(OS_TICK )0,
(void * )0,
(OS_OPT )OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR,
(OS_ERR * )&err);
OS_CRITICAL_EXIT(); //退出临界区OS_TaskSuspend(&StartTaskTCB,&err); //挂起开始任务
}
//led 闪烁任务,每个任务必须是一个死循环
void Task_Led(void *p_arg)
{
OS_ERR err; (void)p_arg;
while(DEF_TRUE)
{
节拍(1s)
}
HAL_GPIO_TogglePin(GPIOI,GPIO_PIN_1); // 翻 转 LED OSTimeDly(1000, OS_OPT_TIME_PERIODIC, &err); //周期性延时 1000 个时钟
}
附件为PDF文件详解:
|