零基础STM32单片机编程入门(五)FreeRTOS实时操作系统详解及实战含源码视频

news2024/11/20 10:24:11

文章目录

    • 一.概要
    • 二.什么是实时操作系统
    • 三.FreeRTOS的特性
    • 四.FreeRTOS的任务详解
      • 1.任务函数定义
      • 2.任务的创建
      • 3.任务的调度原理
    • 五.CubeMX配置一个FreeRTOS例程
      • 1.硬件准备
      • 2.创建工程
      • 3.调试FreeRTOS任务调度
    • 六.CubeMX工程源代码下载
    • 七.讲解视频链接地址
    • 八.小结

一.概要

FreeRTOS是一个迷你的实时操作系统内核。作为一个轻量级的操作系统,功能包括:任务管理、时间管理、信号量、消息队列、内存管理、记录功能、软件定时器、协程等,可基本满足较小系统的需要。
由于RTOS需占用一定的系统资源(尤其是RAM资源),只有μC/OS-II、embOS、salvo、FreeRTOS等少数实时操作系统能在小RAM单片机上运行。相对μC/OS-II、embOS等商业操作系统,FreeRTOS操作系统是完全免费的操作系统,具有源码公开、可移植、可裁减、调度策略灵活的特点,可以方便地移植到各种单片机上运行。

二.什么是实时操作系统

操作系统是一个控制程序,作为硬件和应用程序之间的桥梁,主要是和硬件打交道,负责协调分配计算资源和内存资源给不同的应用程序使用,并防止系统出现故障。面对来自不同应用程序的大量且互相竞争的资源请求,操作系统通过一个调度算法和内存管理算法尽可能把资源公平且有效率地分配给不同的程序。应用程序则通过调用操作系统提供的API接口获得相应资源完成指定的任务。

实时操作系统(RTOS-Real Time Operating System)中实时(Real Time)指的是任务(Task)或者说实现一个功能的线程(Thread)必须在给定的时间(Deadline)内完成。

三.FreeRTOS的特性

具有抢占式或者合作式的实时操作系统内核
功能可裁剪,最小占用10kB左右rom空间,0.5kB ram空间
灵活的任务优先级分配
具有低功耗模式
有互斥锁、信号量、消息队列等功能
运行过程可追踪
支持中断嵌套

四.FreeRTOS的任务详解

FreeRTOS的核心是任务调度器(Task Scheduler),它负责按照一定的调度策略将任务分配给处理器执行。每个任务都是一个独立的函数,可以有不同的优先级和堆栈大小。任务调度器根据任务的优先级和调度策略决定哪个任务被执行。

下图就是任务调度简单介绍
在这里插入图片描述

下面代码就是个简单的示例代码,通过调用osThreadCreate函数创建了两个任务LED_Thread1(驱动LED灯灭)和LED_Thread2(驱动LED灯亮)。在main函数中,通过调用osKernelStart函数启动了实时系统,使得任务可以被调度执行,由于两个任务都能不断运行,所以能驱动LED灯闪烁。

//定义任务函数1
void LED_Thread1(void const * argument)
{
  (void) argument;
  for (;;)
  {
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);//PC13输出高,LED灭
  osDelay(100);//等待100ms
  }
}
//定义任务函数2
void LED_Thread2(void const * argument)
{
  (void) argument;
  for (;;)
  {
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);//PC13输出低,LED亮
  osDelay(250);//等待250ms
  }
}

int main(void)
{
  HAL_Init();
  SystemClock_Config();//外部8M晶振,系统72M主频
  MX_GPIO_Init();//PC13配置成推挽输出
  MX_FREERTOS_Init();//实时系统初始化
  /* Start scheduler */
	osThreadDef(THREAD1, LED_Thread1, osPriorityNormal, 0, 128);
  THREAD1Handle = osThreadCreate(osThread(THREAD1), NULL);//建立任务1
  /* definition and creation of THREAD2 */
  osThreadDef(THREAD2, LED_Thread2, osPriorityNormal, 0, 128);
  THREAD2Handle = osThreadCreate(osThread(THREAD2), NULL);//建立任务2
  osKernelStart();//实时系统启动
  while (1)
  {
  }

}

1.任务函数定义

无论采用何种方法创建任务,均需要用到任务函数。FreeRTOS 规定任务函数的返回值必须为void,而且带有一个void型指针参数。

void LED_Thread1(void const * argument)
{
  (void) argument;
  for (;;)
  {
  HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);//PC13输出高,LED灭
  osDelay(100);//等待100ms
  }
}

STM32F103C8T6单片机只有一个内核,那怎么让多个人同时干活呢?其实每个子任务虽然都是死循环,但并不是每个子任务一直都在执行,每个子任务在执行期间,可能需要延时,这边就通过 osDelay(100),等待100ms,单片机就可以停止此任务,然后切换到其它任务执行,这样看起来就是多个人在同时干活了。

2.任务的创建

osThreadDef(THREAD1, LED_Thread1, osPriorityNormal, 0, 128);//定义一个任务,任务名,任务函数,优先级,堆栈大小
THREAD1Handle = osThreadCreate(osThread(THREAD1), NULL);  //根据上面定义的任务,创建一个任务

osThreadDef函数中的128是任务栈大小定义:

任务栈大小指定了任务可以使用多少RAM来存储局部变量和其他临时数据。这个大小应该足够大,能够容纳任务在执行期间可能出现的最大需求。

osThreadDef函数中的LED_Thread1是任务函数:

任务函数是任务执行的代码,它应该是一个无返回值的函数,其参数是一个可选的指针,可以用来传递任何需要的数据,我们代码中的任务就是控制GPIO输出高或者低电平。

osThreadDef函数中的osPriorityNormal任务优先级:

任务优先级决定了任务在操作系统调度下的执行顺序。数值越大,优先级越高。

osThreadCreate函数的返回值THREAD1Handle是任务句柄:

任务句柄是一个指针,可以用来引用已经创建的任务,以便可以在任务创建后对其进行操作,例如删除、挂起、恢复等。

3.任务的调度原理

FreeRTOS默认使用抢占式调度策略,对同等优先级的任务使用时间片轮询调度,时间片轮询就是可轮流享有相同的单片机时间(可设置),一个时间片等于SysTick中断周期。
抢占式调度是指调度器始终运行优先级最高且处于可运行状态的任务,无论任务何时可以运行。如在中断服务函数中更改了优先级最高且可运行的任务,调度器会停止当前执行的低优先级任务,并启动高优先级任务。
刚才程序中的osDelay 是通过将当前任务加入到延时列表中,并设置一个定时器来在指定的延时时间,延时时间过去之后将任务从延时列表中移除并将其设置为就绪状态。这样当定时器触发时,任务重新被加入到就绪列表中,等待被调度器再次调度执行。

上面代码中的LED_Thread1(驱动LED灯灭)和LED_Thread2(驱动LED灯亮)两个任务的调度顺序以及时间,如下图所示,横坐标是时间,箭头代表运行顺序
在这里插入图片描述

下面代码截图就是操作系统底层寻找就绪任务的最高优先级,获取优先级最高的就绪任务的 TCB(任务控制块),然后更新到 pxCurrentTCB ,当前运行的任务只可能有一个,因此pxCurrentTCB只是单个TCB_t指针,它始终指向当前运行的任务。通过xPortPendSVHandler(PendSV_Handler)函数实现调度
在这里插入图片描述
PendSV_Handler 是 ARM Cortex-M 处理器中的一个特殊的中断处理函数,用于处理挂起 PendSV(Pending Supervisor Call)中断。PendSV 中断是 Cortex-M 架构中的一种特殊的软件中断,它可以用来实现任务切换或者其他与系统调度相关的操作。
PendSV_Handler 在中断向量表的位置
在这里插入图片描述

__asm void xPortPendSVHandler( void )

{

extern uxCriticalNesting;

extern pxCurrentTCB;

extern vTaskSwitchContext;

PRESERVE8

mrs r0, psp //(1)        读取进程栈指针,保存在寄存器 R0 里面。

isb

ldr r3, =pxCurrentTCB//(2)   获取当前任务的任务控制块,并将任务控制块的地址保存在寄存器 R2 里面。

ldr r2, [r3] //(3)

tst r14, #0x10 //(4)        判断任务是否使用了 FPU

it eq //(5)

vstmdbeq r0!, {s16-s31}// (6)

stmdb r0!, {r4-r11, r14} //(7)

str r0, [r2] //(8)

stmdb sp!, {r3} //(9)

mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY //(10)       

msr basepri, r0 //(11)           关闭中断,进入临界区

dsb

isb

bl vTaskSwitchContext //(12)    调用函数 vTaskSwitchContext(),此函数用来获取下一个要运行的任务,并将pxCurrentTCB 更新为这个要运行的任务。

mov r0, #0 //(13)

msr basepri, r0 //(14)        打开中断,退出临界区。

ldmia sp!, {r3} //(15)

ldr r1, [r3] //(16)

ldr r0, [r1] //(17)

ldmia r0!, {r4-r11, r14} //(18)

tst r14, #0x10 //(19)

it eq //(20)

vldmiaeq r0!, {s16-s31} //(21)

msr psp, r0 //(22)           更新进程栈指针 PSP 的值

isb

bx r14 //(23)     执行此行代码以后硬件自动恢复寄存器 R0~R3、 R12、 LR、 PC 和 xPSR 的值,确定异常返回以后应该进入处理器模式还是进程模式,使用主栈指针(MSP)还是进程栈指针(PSP)。很明显这里会进入进程模式,并且使用进程栈指针(PSP),寄存器 PC 值会被恢复为即将运行的任务的任务函数,新的任务开始运行!至此,任务切换成功。

}

五.CubeMX配置一个FreeRTOS例程

1.硬件准备

STLINK接STM32F103C8T6小系统板,STLINK接电脑USB口。

在这里插入图片描述

2.创建工程

打开STM32CubeMX软件,新建工程
在这里插入图片描述
Part Number处输入STM32F103C8,再双击就创建新的工程
在这里插入图片描述
配置下载口引脚
在这里插入图片描述
配置外部晶振引脚
在这里插入图片描述

可以查看STM32F103C8T6小系统板原理图,PC13连接LED灯,所以配置PC13为GPIO输出

在这里插入图片描述
配置FreeRTOS
在这里插入图片描述
配置系统主频
在这里插入图片描述
配置工程文件名,保存路径,KEIL5工程输出方式
在这里插入图片描述
生成工程
在这里插入图片描述
用Keil5打开工程
在这里插入图片描述
添加代码
在这里插入图片描述
在这里插入图片描述

3.调试FreeRTOS任务调度

调试代码,能更好理解任务调度。
下载调试,在LED_Thread1打断点,程序能运行到断点处停止
在这里插入图片描述
在LED_Thread2打断点,程序也能运行到断点处停止
在这里插入图片描述

在xPortPendSVHandler调度函数中打断点,可以看到操作系统将要跳转到任务1运行
在这里插入图片描述
单步执行,运行指针就跳转到任务1开始运行
在这里插入图片描述

xPortPendSVHandler调度函数中打断点,可以看到操作系统将要跳转到任务2运行
在这里插入图片描述
单步执行,运行指针就跳转到任务2开始运行
在这里插入图片描述

六.CubeMX工程源代码下载

链接:https://pan.baidu.com/s/1f50X8w2UXnDtbM6U6zwYqw
提取码:0sys
如果链接失效,可以联系博主给最新链接

程序下载下来之后解压就行

七.讲解视频链接地址

FreeRTOS实验

八.小结

FreeRTOS实时操作系统能使在STM32软件开发中,程序结构清晰,单片机执行效率提升许多,在多个任务模块的代码中,可以考虑使用FreeRTOS。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1881765.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

世界羽坛失去了一位天才选手:如何预防运动场上发生意外

世界羽坛失去了一位天才选手:如何预防运动场上发生意外 --中国羽毛球新星张志杰赛场突发意外,年仅17岁离世 中国羽毛球界的一颗新星、年仅17岁的张志杰,在印尼举行的2024亚洲青年羽毛球锦标赛中不幸离世。这位出生于嘉兴的天才选手&#xf…

北京酒店订房小程序开发的优势与主要功能

随着我国经济与交通的飞速发展,人们出行的次数越来越多,频率也越来越快。无论是出差还是出游,人家对外出酒店的舒适度与便捷度的要求也越来越高。为了满足人们对于酒店的新需求,北京酒店订房小程序与互联网技术相结合,…

经典文献阅读之--BALM2(高效且一致的激光雷达点云束调整)

0. 简介 束调整(Bundle Adjustment,BA)是指同时确定传感器姿态和场景几何的问题,这是机器人视觉中的一个基本问题。本文提出了一种高效且一致的激光雷达束调整方法。该方法利用边缘和平面特征来表示场景几何,并直接最…

制定全面测试计划:使用TS-GNSS模拟器助力接收器选择

GPS/GNSS信号无处不在,也是目前定位导航应用中最为关键的一环,而GNSS接收器芯片组的低成本和高性能使得将GNSS接收器更容易得集成到以前从未有过的产品中去。由于存在以多种频率传输信号的多个GNSS星座,以及用于提高GNSS精度的各种可用技术&a…

并发控制-事务的调度、数据不一致问题(更新丢失、脏读、不可重复读)、非串行调度的的可串行化

一、引言 1、数据库管理系统DBMS的事务处理技术实现的另一个主要功能部分是并发控制机制。并发控制机制完成的功能就是对并发执行的事务进行控制,保证事务的隔离性,从而进一步保持数据库的一致性。 2、事务的并发控制就是对并发执行的不同事务中的数据…

NLP特征提取的惊人历史演变

NLP特征提取的惊人演变 1.理解特征提取2. 文本表示的演变2.1.词袋的简单性2.2. N-Gram 模型的进步2.3. TF-IDF 的崛起 3. 深入研究词嵌入3.1.探索 Word2Vec3.2.深入了解 GloVe3.3.深入研究 FastText 4. 上下文嵌入的影响4.1 ELMo 的突破4.2 理解 BERT 的机制4.3 Transformer的出…

MySQL-核心知识要点

1、索引的数据结构-Btree BTree的优势: B树的内节点无data,一个节点可以存储更多的K-V对。在构造树时,需要的内节点会更少,那么树的层级也会越低。查询一条数据时,1. 扫描的层级低,扫描过的节点更少&…

Java使用Tessdata做OCR图片文字识别【搬代码】

下载tessdata各语言集合包.zip 找个盘下面解压缩&#xff0c;名字改成英文的 pom文件依赖 <dependency><groupId>net.sourceforge.tess4j</groupId><artifactId>tess4j</artifactId><version>4.5.4</version></dependency>j…

第二天:ALOAM前端讲解【第2部分】

三、scan2scan 3. 帧间匹配 特征关联与损失函数计算 (1)线特征 点到线的距离公式: d ϵ = ∣ ( X ~ ( k +

高温电子设备对设计和可靠性带来挑战

1 高温应用 地下石油和天然气行业&#xff0c;温度&#xff1e;150℃&#xff0c;最高温度可达200℃。 地下钻探作业 地下钻探时&#xff0c;需要收集周围的地质构造&#xff0c;可通过测量电阻率、放射性、声音传播时间、磁共振和其他属性&#xff0c;同时还会监控压力、温度、…

[go-zero] goctl 生成api和rpc

文章目录 1.goctl 概述2.go-zero 需要安装的组件3.生成 api4.生成 rpc 1.goctl 概述 goctl支持多种rpc&#xff0c;较为流行的是google开源的grpc&#xff0c;这里主要介绍goctl rpc protoc的代码生成与使用。protoc是grpc的命令&#xff0c;作用是将proto buffer文件转化为相…

2024.07使用gradle上传maven组件到central.sonatype,非常简单

本文基于sonatypeUploader2.0版本 在1.0版本我们还需要手动去添加maven-publish和signing插件&#xff0c;在2.0版本他已经内置了&#xff0c;如果你仍然需要手动配置&#xff0c;你可以手动添加这两个插件及逻辑。 具体信息参考开源仓库&#xff1a; 插件仓库&#xff1a;h…

GPT-5:博士级智能的破晓,人工智能的新里程碑

随着科技的飞速发展&#xff0c;人工智能领域再次迎来了一场革命性的突破。备受瞩目的新一代大语言模型GPT-5即将在一年半之后发布&#xff0c;这一创新不仅将再次刷新人们对人工智能的认知&#xff0c;更有可能在多个领域展现出超越人类博士级智能的卓越能力。本文将对GPT-5的…

一体化导航的优点及应用领域

一体化导航&#xff0c;作为现代导航技术的重要发展方向&#xff0c;正日益展现出其独特的魅力和广泛的应用前景。这种导航方式将多种导航技术、信息系统以及数据处理方法集成于一个统一的平台上&#xff0c;为用户提供高效、准确、便捷的导航服务。 一体化导航的核心在于其高度…

【Python】从基础到进阶(二):了解Python语言基础以及数据类型转换、基础输入输出

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 一、引言二、基本数据类型转换1. 隐式转换2. 显式转换 三、基本输入输出1. 输入&#xff08;input&#xff09;2. 输出&#xff08;print&#xff09;3. 案例&#xff1a;输入姓名、年龄、身高以及体重&#xff0c;计算BMI指…

onnx文件QNN部署

一、准备环境 1.linux配置qnn sdk &#xff08;1&#xff09;下载qnn sdk https://qpm.qualcomm.com/#/main/tools/details/qualcomm_ai_engine_direct &#xff08;2&#xff09;下载qpm3 https://softwarecenter.qualcomm.com/#/catalog/item/3097f479-8993-11ea-9571-06…

Luminar Neo 1.20.0 (macOS Universal) - 创新 AI 图像编辑器

Luminar Neo 1.20.0 (macOS Universal) - 创新 AI 图像编辑器 利用尖端的人工智能生成技术&#xff0c;轻松增强照片效果 请访问原文链接&#xff1a;https://sysin.org/blog/luminar-neo/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1…

揭秘Wish自养号秘诀:新手卖家如何快速出单?

对于卖家来说&#xff0c;如果想要提升店铺的转化率和销量&#xff0c;有几个关键策略是必不可少的&#xff1a; 一、精心挑选热销产品 成功的第一步在于选品。选择热销产品如同掌握了成功的钥匙。卖家需要深入分析平台用户群体&#xff0c;了解他们的需求和偏好。例如&#…

Powershell 简易爬虫,提取种子网站的磁力链接

目录 一. 需求二. 分析2.1 思路分析2.2 技术点 三. 代码四. 效果 一. 需求 ⏹有网站如下所示&#xff0c;先要求从按照关键词搜索到的网页中&#xff0c;提取出所有的磁力链接。 二. 分析 2.1 思路分析 打开网页之后&#xff0c;从网页中先提取出所有的标题相关的url然后再打…

XXL-JOB分布式任务调度框架详解(全网最详细!!!)

引言 第一部分&#xff1a;XXL-JOB概述 第二部分&#xff1a;架构与组件 第三部分&#xff1a;使用教程 第四部分&#xff1a;源码分析 第五部分&#xff1a;最佳实践 引言 在分布式系统中&#xff0c;任务调度是一项基础而又关键的服务&#xff0c;它涉及到定时任务的管理…