RTOS实例

学习嵌入式实时操作系统(RTOS),以uc/OS-III为例,将其移植到stm32F103上,构建至少3个任务(task):其中两个task分别以1s和3s周期对LED等进行点亮-熄灭的控制;另外一个task以2s周期通过串口发送“hello uc/OS! 欢迎来到RTOS多任务环境!”。记录详细的移植过程。

一. us/OS-lll介绍

UCOS是Micrium公司出品的RTOS类实时操作系统, UCOS目前有两个版本:UCOSII和UCOSIII。

UCOSIII是一个可裁剪、可剥夺型的多任务内核,而且没有任务数限制,提供了实时操作系统所需的所有功能,包括资源管理、同步、任务通信等。

UCOSIII是用C和汇编来写的,其中绝大部分都是用C语言编写的,只有极少数的与处理器密切相关的部分代码才是用汇编写的, UCOSIII结构简洁,可读性很强!非常适合初次接触嵌入式实时操作系统学生、嵌入式系统开发人员和爱好者学习。

什么是任务?

任务(线程)是简单的程序。单CPU 中,在任何时刻只能是一个任务被执行。
任务看起来像C 函数。在大多数嵌入式系统中,任务通常是无限循环的。任务不能像C 函数那样,它是不能return 的。

在UCOSIII中任务是以何种面貌存在的呢?

在UCOSIII中任务就是程序实体,UCOSIII能够管理和调度这些小任务(程序)。UCOSIII中的任务由三部分组成:任务堆栈、任务控制块和任务函数。

任务堆栈:上下文切换的时候用来保存任务的工作环境,就是STM32的内部寄存器值。
任务堆栈是任务的重要部分,堆栈是在RAM中按照“先进先出(FIFO)”的原则组织的一块连续的存储空间。为了满足任务切换和响应中断时保存CPU寄存器中的内容及任务调用其它函数时的需要,每个任务都应该有自己的堆栈。

#define START_STK_SIZE 512 //堆栈大小
CPU_STK START_TASK_STK[START_STK_SIZE]; //定义一个数组来作为任务堆栈
任务堆栈初始化

任务如何才能切换回上一个任务并且还能接着从上次被中断的地方开始运行?

恢复现场即可,现场就是CPU的内部各个寄存器。因此在创建一个新任务时,必须把系统启动这个任务时所需的CPU各个寄存器初始值事先存放在任务堆栈中。这样当任务获得CPU使用权时,就把任务堆栈的内容复制到CPU的各个寄存器,从而可以任务顺利地启动并运行。

把任务初始数据存放到任务堆栈的工作就叫做任务堆栈的初始化,UCOSIII提供了完成堆栈初始化的函数:OSTaskStkInit()。

当然,用户一般不会直接操作堆栈初始化函数,任务堆栈初始化函数由任务创建函数OSTaskCreate()调用。不同的CPU对于的寄存器和对堆栈的操作方式不同,因此在移植UCOSIII的时候需要用户根据各自所选的CPU来编写任务堆栈初始化函数。

任务控制块:任务控制块用来记录任务的各个属性。
任务控制块是用来记录与任务相关的信息的数据结构,每个任务都要有自己的任务控制块。我们使用OSTaskCreate()函数来创建任务的时候就会给任务分配一个任务控制块。任务控制块由用户自行创建。

OS_TCB StartTaskTCB; //创建一个任务控制块

**USOCIII提供了用于任务控制块初始化的函数:OS_TaskInitTCB()。**但是,用户不需要自行初始化任务控制块。因为和任务堆栈初始化函数一样,函数OSTaskCreate()在创建任务的时候会对任务的任务控制块进行初始化。

任务函数:由用户编写的任务处理代码,是实实在在干活的,任务函数通常是一个无限循环,也可以是一个只执行一次的任务。任务的参数是一个void类型的,可以可以传递不同类型的数据甚至是函数。
任务函数其实就是一个C语言的函数,但是在使用UCOIII的情况下这个函数不能有用户自行调用,任务函数何时执行执行,何时停止完全有操作系统来控制。

UCOSIII支持时间片轮转调度,因此在一个优先级下会有多个任务,那么我们就要对这些任务做一个管理,这里使用OSRdyList[]数组管理这些任务。

OSRdyList[]数组中的每个元素对应一个优先级,比如OSRdyList[0]就用来管理优先级0下的所有任务。OSRdyList[0]为OS_RDY_LIST类型,从上面OS_RDY_LIST结构体可以看到成员变量:HeadPtr和TailPtr分别指向OS_TCB,我们知道OS_TCB是可以用来构造链表的,因此同一个优先级下的所有任务是通过链表来管理的,HeadPtr和TailPtr分别指向这个链表的头和尾,NbrEntries用来记录此优先级下的任务数量,图5.5.2表示了优先级4现在有3个任务时候的就绪任务列表。

同一优先级下如果有多个任务的话最先运行的永远是HeadPtr所指向的任务

在这里插入图片描述

二.实验过程

1.建立新工程,选择STM32F103C8T6
在这里插入图片描述
2.配置时钟源,选择外部时钟源,配置72HZ频率
在这里插入图片描述
3.设置DeBug
在这里插入图片描述
4.配置串口,设置位异步通信
在这里插入图片描述
5.设置文件名,选择对应的keil版本
在这里插入图片描述

三.获取 us/OS-lll源码

进入 Micrium 公司官网下载中心:
http://micrium.com/downloadcenter/
选择ST系列,点击 View all STMicroelectronics,点击 STMicroelectronics STM32F107
之后按照提示注册下载即可。

四.移植过程

1.找到下载的文件
在这里插入图片描述
2.将下载好的文件复制到创建工程的MDK-ARM目录下
在这里插入图片描述
3.具体移植
点击这个图标,快速添加
在这里插入图片描述
点击虚线框添加文件名字,点击add在将之前复制下来的文件夹里的文件添加进来
在这里插入图片描述
CPU文件移植
在这里插入图片描述

同时在ARM-Cortex文件中,找到realview文件,添加对应文件,最后需要添加到如下的几个文件
在这里插入图片描述
LIB文件
在这里插入图片描述
在这里插入图片描述
port文件,添加ucos-lll文件中port文件里的realview中添加如下文件
在这里插入图片描述

SOURCE文件的添加,将ucos-lll中的source文件加入
在这里插入图片描述
CONFIG文件的添加
在这里插入图片描述
BSP文件的添加
在这里插入图片描述
导入文件路径
在这里插入图片描述
4.建立文件,并为bsp.c和bsp.h添加代码
bsp.h文件

#ifndef  __BSP_H__
#define  __BSP_H__

#include "stm32f1xx_hal.h"

void BSP_Init(void);

#endif

bsp.c文件

// bsp.c
#include "includes.h"

#define  DWT_CR      *(CPU_REG32 *)0xE0001000
#define  DWT_CYCCNT  *(CPU_REG32 *)0xE0001004
#define  DEM_CR      *(CPU_REG32 *)0xE000EDFC
#define  DBGMCU_CR   *(CPU_REG32 *)0xE0042004

#define  DEM_CR_TRCENA                   (1 << 24)
#define  DWT_CR_CYCCNTENA                (1 <<  0)

CPU_INT32U  BSP_CPU_ClkFreq (void)
{
   
    return HAL_RCC_GetHCLKFreq();
}

void BSP_Tick_Init(void)
{
   
	CPU_INT32U cpu_clk_freq;
	CPU_INT32U cnts;
	cpu_clk_freq = BSP_CPU_ClkFreq();
	
	#if(OS_VERSION>=3000u)
		cnts = cpu_clk_freq/(CPU_INT32U)OSCfg_TickRate_Hz;
	#else
		cnts = cpu_clk_freq/(CPU_INT32U)OS_TICKS_PER_SEC;
	#endif
	OS_CPU_SysTickInit(cnts);
}



void BSP_Init(void)
{
   
	BSP_Tick_Init();
	MX_GPIO_Init();
}


#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED)
void  CPU_TS_TmrInit (void)
{
   
    CPU_INT32U  cpu_clk_freq_hz;


    DEM_CR         |= (CPU_INT32U)DEM_CR_TRCENA;                /* Enable Cortex-M3's DWT CYCCNT reg.                   */
    DWT_CYCCNT      = (CPU_INT32U)0u;
    DWT_CR         |= (CPU_INT32U)DWT_CR_CYCCNTENA;

    cpu_clk_freq_hz = BSP_CPU_ClkFreq();
    CPU_TS_TmrFreqSet(cpu_clk_freq_hz);
}
#endif


#if (CPU_CFG_TS_TMR_EN == DEF_ENABLED
  • 17
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
RT-Thread 是一个实时操作系统(RTOS),它的设计目标是为嵌入式系统提供高效、快速和稳定的运行环境。下面我来介绍一些 RT-Thread 的实例应用。 1. 电子产品:许多电子产品都需要使用实时操作系统来进行控制和管理。比如智能家居设备、智能手表、智能穿戴设备等。RT-Thread 的小巧且高效的特点使得它非常适合这些资源有限的嵌入式系统。 2. 工业自动化:工业领域对于实时性要求非常高,对于一些需要精确控制的应用场景,如机器人控制系统、自动化生产线等,RT-Thread 可以提供可靠的实时运行环境,保证数据的准确性和系统的稳定性。 3. 通信设备:无线通信设备、物联网设备等都需要一个可靠的操作系统来实现数据的传输和处理。RT-Thread 高度可定制的特点使得它可以适应不同的通信接口和协议,满足各种通信设备的需求。 4. 汽车电子:现代汽车中的电子控制单元(ECU)往往需要一个可靠的实时操作系统来处理车辆的各种数据和控制信息。RT-Thread 可以为汽车电子提供稳定的运行环境,实现各种功能,如发动机控制、车载娱乐系统等。 5. 医疗设备:医疗设备往往对实时性和安全性要求非常高。RT-Thread 的可靠性和稳定性可以保证医疗设备的正常运行,如医疗监护仪、手术机器人等。 综上所述,RT-Thread 在各个领域都有广泛的应用。它的小巧、高效和可靠的特点使得它成为了嵌入式行业中流行的实时操作系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值